簡體   English   中英

用javascript檢測:first-letter

[英]Detecting :first-letter by javascript

我需要知道某個元素是否使用:first-letter樣式設置樣式,這應該是一種通用解決方案,因此我不會依賴於類名或特殊樣式屬性。 有什么辦法嗎? 例:

<p class="initial">First</p>
<p>Second</p>

.initial:first-letter {
float: left;
font-size: 1.5em;
font-weight: bold;
}

$('p').click(function(){
    // how to determine if :first-letter is applied to current paragraph?

});

如果您的CSS是自托管的,則可以:

  1. 獲取所有CSS塊的列表
  2. 過濾掉不包含:first-letter CSS塊
  3. 遍歷其余CSS塊的列表,然后運行matchesSelector() ,將目標元素作為接收器,將當前CSS塊的選擇器作為參數。
    1. 如果matchesSelector()返回true ,則當前CSS塊的規則會影響目標元素的首字母。
    2. 否則,移至列表中的下一個CSS塊

如果CSS不是自托管的,並且CDN不發送CORS標頭,則由於隱私問題,您將無法讀取CSS文件源,並且無法完成此操作。

我還沒有從算法中找出規則級聯。 道路上的另一個matchesSelector是弄清楚哪些偽選擇器以錯誤的方式影響matchesSelector

喜歡考慮:

p.webkitMatchesSelector("p:first-letter") //false

因此,在嘗試匹配之前,必須從字符串中刪除諸如:first-letter之類的偽內容,因為它們無關緊要(但諸如:nth-child類的偽內容並不是因為它們確實會影響匹配)。

演示http://jsfiddle.net/PBuzb/5/ (請記住,我提到的問題在這里並沒有得到很好的解決)(Crush最初的代碼庫)


為什么在跨域情況下不允許閱讀CSS源代碼?

您只能顯示圖像,從其他域運行css / js等的原因,但是絕對不能以任何方式訪問其數據是出於隱私。

這種情況最容易制作圖像。 假設我已經登錄到Facebook,並且Facebook使用url作為私人照片,例如http://facebook.com/myprofile.png 現在,我轉到evil.com,evil.com可以加載該圖像,因為我已登錄到Facebook,facebook將為他們提供該圖像。 通常,他們無論如何都無法訪問或竊取圖像,但是如果啟用了跨域數據訪問,則他們現在可以訪問我的私人照片並將其散布開。

CSS也可能發生同樣的情況,facebook服務器可能會生成特定於用戶的CSS,其中包含我的私人朋友的用戶ID。 如果我可以訪問任何網站,只需將其鏈接到該CSS並開始閱讀,它們便不再那么私密。

是的,主要問題是瀏覽器如何發送帶有跨域請求的cookie,如果瀏覽器在從evil.com請求facebook圖像/ css時未發送cookie,則facebook無法使用用戶特定的CSS或我的私人照片進行響應因為餅干是識別我所必需的。

現在,假設瀏覽器沒有發送Cookie。 Evil.com仍然可以這種方式訪問​​任何Intranet數據,因為我的瀏覽器可以訪問Intranet。 可以在evil.com網站http://intranet/Myboss.jpg顯示為圖像不是問題,但是Evil.com能夠讀取圖像數據並因此能夠復制和傳播它是一個問題。

您可以遍歷cssRules,構建所有::: ::first-letter規則的數組,然后檢查元素是否具有這些規則之一。

有效的演示版 (僅在Chrome中測試)

(function() {
    var firstLetterRules = [];

    var loadRules = function() {
        var stylesheets = document.styleSheets;

        for (var i = 0; i < stylesheets.length; i++) {
            var stylesheet = stylesheets[i];
            var rules = stylesheet.cssRules;

            for (var k = 0; k < rules.length; k++) {
                var rule = rules[k];

                if (rule.selectorText.indexOf("::first-letter") !== -1) {
                    //It is a ::first-letter selector. Add the rule to a list of ::first-letter rules.
                    firstLetterRules.push(rule.selectorText.toUpperCase());
                }
            }
        }
    };

    window.hasFirstLetterStyle = function(element) {
        var fullSelector = element.nodeName;

        if (element.className != '')
            fullSelector += '.' + element.className;

        fullSelector = fullSelector.toUpperCase() + "::FIRST-LETTER";

        for (var i = 0; i < firstLetterRules.length; i++) {
            if (fullSelector == firstLetterRules[i])
                return true;
        }

        return false;
    };

    loadRules();
})();

var element = document.getElementById("init");

if (hasFirstLetterStyle(element)) {
    console.log("Element has a first-letter style rule.");
}

你不能。

偽選擇器及其樣式無法通過JS代碼訪問。

最接近的方法是檢查元素是否具有觸發第first-letter樣式的相關類,並在JS代碼中假設如果有該類,則必須已應用first-letter樣式。

確實沒有其他方法,只需手動解析整個CSS文件即可。

這也適用於其他偽選擇器和偽元素(在此處您會發現許多類似的問題,它們會詢問有關:before:after類似問題,並提供類似的答案)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM