代码之家  ›  专栏  ›  技术社区  ›  Chad

javascript:让用户选择一个HTML元素,比如firebug?

  •  27
  • Chad  · 技术社区  · 15 年前

    我想编写一个浏览器(chrome/ff)扩展,需要在网页上选择一个元素。我希望它表现得像Firebug的元素检查器一样。单击“检查”箭头,然后可以悬停/突出显示元素。单击所需元素时,将检查该元素。我只是对允许用户选择元素的代码感兴趣,而不是实际检查它或任何类似的东西。

    因为我正在编写一个扩展,所以如果您可以提供非jquery/prototype/etc,那就更好了。代码,所以我不必分发它。

    9 回复  |  直到 7 年前
        1
  •  18
  •   Andrew Childs    13 年前

    我使用jquery作为另一个项目的组件编写了一个实现。资料来源和文件可在这里获得: https://github.com/andrewchilds/jQuery.DomOutline

        2
  •  17
  •   iConnor    11 年前

    我最近为一个我正在工作的项目需要这样一个特性,结果我不得不用边来创建一个框,否则 event.target 当你移动的时候,鼠标会变成选择器,如果我使用 z-index: -1 会有点 鱼腥味 当你有很多元素重叠…等等。

    为了您的利益,我从我的项目中转换了一个版本,它涉及jquery,但转换为 香草 作为唯一 mousemove &安培; css 使用jquery中的方法。

    逐步说明。

    首先创建 需要的HTML元素。

    <div id="selector">
        <div id="selector-top"></div>
        <div id="selector-left"></div>
        <div id="selector-right"></div>
        <div id="selector-bottom"></div>
    </div>
    

    其次创造一个 移动鼠标 事件上 document (或您的容器)

    $(document).mousemove(function(event) { ... });
    

    然后在里面 移动鼠标 我们将做一些基本检查,以防止选择 HTML, BODY, selector

    var id = event.target.id, tagName = event.target.tagName;
    
    if(id.indexOf('selector') !== -1 || tagName === 'BODY' || tagName === 'HTML') {
       return;
    } 
    

    然后我们需要创建一个对象来存储这样的元素。

    var elements = {
        top: $('#selector-top'),
        left: $('#selector-left'),
        right: $('#selector-right'),
        bottom: $('#selector-bottom')
    };
    

    之后,我们存储一些变量来保存关于目标元素的一些信息,就像这样。

    var $target = event.target;
        targetOffset = $target.getBoundingClientRect(),
        targetHeight = targetOffset.height,
        targetWidth  = targetOffset.width;
    

    那么我们要做的就是计算 位置 和; 高度 为了所有 选择器的侧面是这样的。

    elements.top.css({
        left:  (targetOffset.left - 4),
        top:   (targetOffset.top - 4),
        width: (targetWidth + 5)
    });
    
    elements.bottom.css({
        top:   (targetOffset.top + targetHeight + 1),
        left:  (targetOffset.left  - 3),
        width: (targetWidth + 4)
    });
    
    elements.left.css({
        left:   (targetOffset.left  - 5),
        top:    (targetOffset.top  - 4),
        height: (targetHeight + 8)
    });
    
    elements.right.css({
        left:   (targetOffset.left + targetWidth + 1),
        top:    (targetOffset.top  - 4),
        height: (targetHeight + 8)
    });
    

    所有的 +aFewPixels 只是一点优化,所以 2px 选择器和目标之间的间隙。

    对于 CSS 这就是我想出来的。

    #selector-top, #selector-bottom {
        background: blue;
        height:3px;
        position: fixed;
        transition:all 300ms ease;
    }
    
    #selector-left, #selector-right {
        background: blue;
        width:3px;
        position: fixed;
        transition:all 300ms ease;
    }
    

    这个 transition 使选择器具有非常好的滑动效果。

    试用演示 http://jsfiddle.net/rFc8E/9/

    注:这也适用于 transform: scale(2); 当一个元素按大小缩放时。

    编辑: 我刚刚更新了这个,我注意到 elements 对象是 里面 事件处理程序,我在演示中将它移到了外面,这是一个非常重要的性能改进,因为现在 元素 仅创建对象 一旦 而不是 几十万 如果没有 数以百万计的 里面的时间 移动鼠标 事件。

        3
  •  9
  •   antonj    15 年前

    一个简单的方法是使用大纲而不是边框:

    .highlight { outline: 4px solid #07C; }
    

    只需将该类添加到要选择/取消选择的任何元素中并将其移除(下面的代码未正确测试):

    document.body.addEventListener("mouseover", function(e) {
        e.stopPropagation();
        e.target.addEventListener("mouseout", function (e) {
            e.target.className = e.target.className.replace(new RegExp(" highlight\\b", "g"), "");
        });
        e.target.className += " highlight";
    });
    

    由于您使用的是大纲(由chrome支持),而不是边框,因此元素不会跳转。我用的是类似的东西 EasyReader Extension .

        4
  •  8
  •   Chad    15 年前
        5
  •  3
  •   phreakhead    12 年前

    也可以看看这个:

    http://rockingcode.com/tutorial/element-dom-tree-jquery-plugin-firebug-like-functionality/

    我觉得这很有洞察力。这里有一个演示:

    http://rockingcode.com/demos/elemtree/

    希望这有帮助。

        6
  •  2
  •   Community Mohan Dere    8 年前

    StackOverflow上也有类似的问题,有很多好的答案: Does anyone know a DOM inspector javascript library or plugin?

    对于那些正在寻找快速和肮脏解决方案的人:

    http://userscripts.org/scripts/review/3006 是最简单的。把代码放进去 <script></script> 标签和你很好去。

    https://github.com/josscrowcroft/Simple-JavaScript-DOM-Inspector/blob/master/inspector.js 稍微好一点,仍然很容易集成。

    对于更复杂的元素检查器,您可能需要查看UDI所指的selectorgadget。检查员选择代码在 http://www.selectorgadget.com/stable/lib/interface.js

        7
  •  2
  •   hsynlms    7 年前

    这里有一个用纯JavaScript编写的库作为替代。

    TheRoom JS: https://github.com/hsynlms/theroomjs

    // theroom information template for target element
    var template="";
    template += "<div id=\"theroom-info\">";
    template += "  <span id=\"theroom-tag\"><\/span>";
    template += "  <span id=\"theroom-id\"><\/span>";
    template += "  <span id=\"theroom-class\"><\/span>";
    template += "<\/div>";
    template += "";
    template += "<style>";
    template += "  #theroom-info {";
    template += "    position: fixed;";
    template += "    bottom: 0;";
    template += "    width: 100%;";
    template += "    left: 0;";
    template += "    font-family: \"Courier\";";
    template += "    background-color: #ffffff;";
    template += "    padding: 10px;";
    template += "    color: #333333;";
    template += "    text-align: center;";
    template += "    box-shadow: 0px 4px 20px rgba(0,0,0,0.3);";
    template += "  }";
    template += "";
    template += "  #theroom-tag {";
    template += "    color: #C2185B;";
    template += "  }";
    template += "";
    template += "  #theroom-id {";
    template += "    color: #5D4037;";
    template += "  }";
    template += "";
    template += "  #theroom-class {";
    template += "    color: #607D8B;";
    template += "  }";
    template += "<\/style>";
    
    var options = {
      template: template,
      showInfo: true
    };
    
    // initialize
    theRoom.start(options);
    

    codepen demo

        8
  •  1
  •   gblazex    10 年前

    您需要做的是为突出显示创建4个元素。它们会形成一个 空正方形 所以你的鼠标事件可以自由触发。这个和这个相似 overlay example 我做了。

    不同的是,您只需要四个元素(没有调整大小标记),并且四个框的大小和位置略有不同(模仿红色边框)。然后你可以用 event.target 在事件处理程序中,因为默认情况下它会获取真正的最上面的元素。

    另一种方法 是隐藏exra元素,获取 elementFromPoint ,计算后放回原处。

    我可以告诉你,它们比光还快。即使爱因斯坦也会同意:)

    1.)元素从点覆盖/边框-[ Demo1 ] FF需要V3.0+

    var box = $("<div class='outer' />").css({
      display: "none", position: "absolute", 
      zIndex: 65000, background:"rgba(255, 0, 0, .3)"
    }).appendTo("body");
    
    var mouseX, mouseY, target, lastTarget;
    
    // in case you need to support older browsers use a requestAnimationFrame polyfill
    // e.g: https://gist.github.com/paulirish/1579671
    window.requestAnimationFrame(function frame() {
      window.requestAnimationFrame(frame);
        if (target && target.className === "outer") {
            box.hide();
            target = document.elementFromPoint(mouseX, mouseY);
        }
        box.show();   
    
        if (target === lastTarget) return;
    
        lastTarget = target;
        var $target = $(target);
        var offset = $target.offset();
        box.css({
            width:  $target.outerWidth()  - 1, 
            height: $target.outerHeight() - 1, 
            left:   offset.left, 
            top:    offset.top 
        });
    });
    
    $("body").mousemove(function (e) {
        mouseX = e.clientX;
        mouseY = e.clientY;
        target = e.target;
    });
    

    2.)鼠标悬停边框-[ Demo2 ]

    var box = new Overlay();
    
    $("body").mouseover(function(e){
      var el = $(e.target);
      var offset = el.offset();
      box.render(el.outerWidth(), el.outerHeight(), offset.left, offset.top);
    });​
    
    /**
     * This object encapsulates the elements and actions of the overlay.
     */
    function Overlay(width, height, left, top) {
    
        this.width = this.height = this.left = this.top = 0;
    
        // outer parent
        var outer = $("<div class='outer' />").appendTo("body");
    
        // red lines (boxes)
        var topbox    = $("<div />").css("height", 1).appendTo(outer);
        var bottombox = $("<div />").css("height", 1).appendTo(outer);  
        var leftbox   = $("<div />").css("width",  1).appendTo(outer);
        var rightbox  = $("<div />").css("width",  1).appendTo(outer);
    
        // don't count it as a real element
        outer.mouseover(function(){ 
            outer.hide(); 
        });    
    
        /**
         * Public interface
         */
    
        this.resize = function resize(width, height, left, top) {
          if (width != null)
            this.width = width;
          if (height != null)
            this.height = height;
          if (left != null)
            this.left = left;
          if (top != null)
            this.top = top;      
        };
    
        this.show = function show() {
           outer.show();
        };
    
        this.hide = function hide() {
           outer.hide();
        };     
    
        this.render = function render(width, height, left, top) {
    
            this.resize(width, height, left, top);
    
            topbox.css({
              top:   this.top,
              left:  this.left,
              width: this.width
            });
            bottombox.css({
              top:   this.top + this.height - 1,
              left:  this.left,
              width: this.width
            });
            leftbox.css({
              top:    this.top, 
              left:   this.left, 
              height: this.height
            });
            rightbox.css({
              top:    this.top, 
              left:   this.left + this.width - 1, 
              height: this.height  
            });
    
            this.show();
        };      
    
        // initial rendering [optional]
        // this.render(width, height, left, top);
    }
    
        9
  •  1
  •   Zach Saucier    9 年前

    一个非常基本的实现可以很容易地完成,而无需使用jquery .onmouseover e.target :

    var last,
        bgc;
    document.onmouseover = function(e) {
        var elem = e.target;
    
        if (last != elem) {
            if (last != null) {
                last.classList.remove("hovered");
            }
    
            last = elem;
            elem.classList.add("hovered");
        }
    }
    

    如果希望孩子们也更改背景,请使用下面的CSS:

    .hovered,
    .hovered * {
        cursor: pointer;
        color: black;
        background-color: red;
    }
    

    Demo


    如果您只想选择边缘附近的元素(或选择边缘附近的父元素以及其他任何地方的元素本身),则可以使用 .getBoundingClientRect .

    var last;
    window.addEventListener("mousemove", function(e) {
      if(last) {
        last.style.background = ''; // empty is enough to restore previous value
      }
        var elem = e.target;
    
      if(elem === document.body || elem === document.documentElement) {
        return;
      }
      var bb = elem.getBoundingClientRect();
      var xr = e.pageX - bb.left; // x relative to elem
      var yr = e.pageY - bb.top; // y relative to elem
      var ew = 10; // edge width
    
      if(
           xr <= ew
        || xr >= bb.width - ew
        || yr <= ew
        || yr >= bb.height - ew
      ){
        elem.style.background = 'red';
        last = elem;
      }
    });
    

    与一些边框配对,这对于选择非常有用。 Demo