5

我有一个 javascript 小书签,我把它放在一起使一项艰巨的任务变得更容易忍受。基本上,我正在浏览数百页的培训材料,并确保所有这些材料都已正确地从 Helvetica 交换到 Arial。小书签代码如下,但快速分解是它创建了一个 mousemove 事件侦听器和一个小的、绝对定位的 div。在 mousemove 事件中,div 移动到新的鼠标位置(向下和向右偏移 10px),使用 elementFromPoint 获取鼠标下的元素并显示该元素的 font-family 属性。哦,它会根据 Arial 是否出现在属性中来改变它的背景颜色。

var bodyEl=document.getElementsByTagName("body")[0];
var displayDiv=document.createElement("div");
displayDiv.style.position="absolute";
displayDiv.style.top="0px";
displayDiv.style.top="0px";
bodyEl.appendChild(displayDiv);


function getStyle(el,styleProp) {
  var camelize = function (str) {
    return str.replace(/\-(\w)/g, function(str, letter){
      return letter.toUpperCase();
    });
  };

  if (el.currentStyle) {
    return el.currentStyle[camelize(styleProp)];
  } else if (document.defaultView && document.defaultView.getComputedStyle) {
    return document.defaultView.getComputedStyle(el,null)
                               .getPropertyValue(styleProp);
  } else {
    return el.style[camelize(styleProp)]; 
  }
}
function getTheElement(x,y) {return document.elementFromPoint(x,y);}

fn_displayFont=function displayFont(e) {
    e = e || window.event;
    var divX=e.pageX+10;
    var divY=e.pageY+10;
    var font=getStyle(getTheElement(e.pageX,e.pageY),"font-family");
    if (font.toLowerCase().indexOf("arial") != -1) {
        displayDiv.style.backgroundColor = "green";
    } else {
        displayDiv.style.backgroundColor = "red";
    }
    displayDiv.style.top= divY.toString() + "px";
    displayDiv.style.left= divX.toString() + "px";
    displayDiv.style.fontFamily=font;
    displayDiv.innerHTML=font;
}

window.addEventListener('mousemove', fn_displayFont);
document.onkeydown = function(evt) {
    evt = evt || window.event;
    if (evt.keyCode == 27) {
        window.removeEventListener('mousemove', fn_displayFont);
        bodyEl.removeChild(displayDiv);
    }
};

(作为记录,我从 SO 上的答案中窃取了样式确定代码,但不久之后我丢失了标签。谢谢,匿名的互联网人!)所以这一切都很好 - 直到我尝试将鼠标悬停在部分从顶部向下滚动的页面。如果我在滚动到页面顶部时将鼠标放在屏幕的最底部,并且如果我向下滚动足够远,则 div 将位于该位置,并且如果我向下滚动足够远,则萤火虫开始记录 e.pageX 未定义。

有任何想法吗?

4

2 回答 2

9

好吧,想通了。我看到http://www.daniweb.com/web-development/javascript-dhtml-ajax/threads/276742/elementfrompoint-problems-when-window-has-been-scrolled-并认为这意味着我必须减去 pageoffset直接从 e.pageX/Y 值开始,在我用它来计算 div 位置或其他任何东西之前,这对我来说破坏了一切,所以我认为它一定是不相关的 - 不是这样!根据我现在的理解, elementFromPoint 方法在浏览器的当前视图中取一个相对点,也就是说,基于当前可以看到的左上角,而不是整个页面。我通过在获取元素时仅从 X 和 Y 值中获取偏移量来修复它。现在工作的代码如下。

var bodyEl=document.getElementsByTagName("body")[0];
var displayDiv=document.createElement("div");
displayDiv.style.position="absolute";
displayDiv.style.top="0px";
displayDiv.style.top="0px";
bodyEl.appendChild(displayDiv);


function getStyle(el,styleProp) {
  var camelize = function (str) {
    return str.replace(/\-(\w)/g, function(str, letter){
      return letter.toUpperCase();
    });
  };

  if (el.currentStyle) {
    return el.currentStyle[camelize(styleProp)];
  } else if (document.defaultView && document.defaultView.getComputedStyle) {
    return document.defaultView.getComputedStyle(el,null)
                               .getPropertyValue(styleProp);
  } else {
    return el.style[camelize(styleProp)]; 
  }
}
function getTheElement(x,y) {return document.elementFromPoint(x,y);}

fn_displayFont=function displayFont(e) {
    e = e || window.event;
    var divX=e.pageX + 10;
    var divY=e.pageY + 10;
    var font=getStyle(getTheElement(e.pageX - window.pageXOffset,e.pageY - window.pageYOffset),"font-family");
    if (font.toLowerCase().indexOf("arial") != -1) {
        displayDiv.style.backgroundColor = "green";
    } else {
        displayDiv.style.backgroundColor = "red";
    }
    displayDiv.style.top= divY.toString() + "px";
    displayDiv.style.left= divX.toString() + "px";
    displayDiv.style.fontFamily=font;
    displayDiv.innerHTML=font;
}

document.addEventListener('mousemove', fn_displayFont);
document.onkeydown = function(evt) {
    evt = evt || window.event;
    if (evt.keyCode == 27) {
        window.removeEventListener('mousemove', fn_displayFont);
        bodyEl.removeChild(displayDiv);
    }
};
于 2012-11-02T06:53:07.527 回答
0

嗯,而不是用鼠标检查,为什么不检查每个叶节点呢?如果任何叶节点的字体系列为 arial,那么它应该指示其祖先之一的字体系列为 Arial。

首先,您需要将 jquery 放到页面上。试试这个书签

然后运行这段代码:

(function(){
    var arialNodes = $('div:not(:has(*))').filter(function(){
        return $(this).css('font-family').toLowerCase().indexOf("arial") != -1;
    });
})();

arialNodes变量应包含具有“Arial”字体系列的每个叶节点。然后,您可以使用它来确定哪个父元素具有声明。

或者,如果您只想查看页面是否合规,只需检查长度即可。

更新

更新以反映以下评论

(function() {
    var arialNodes = $('*:not(:has(*))', $('body')).filter(function() {
        return $(this).css('font-family').toLowerCase().indexOf("arial") === -1;
    });

    var offendingParents = [];
    arialNodes.each(function(){
        var highestOffendingParent = $(this).parentsUntil('body').filter(function(){
            return $(this).css('font-family').toLowerCase().indexOf("arial") === -1;
        }).last();
        if(offendingParents.indexOf(highestOffendingParent) === -1){
            offendingParents.push(highestOffendingParent);
        }
    });

})();
于 2012-11-02T05:30:51.247 回答