web-dev-qa-db-ja.com

Javascript:ユーザーにFirebugのようなHTML要素を選択させますか?

Webページ上の要素を選択する必要があるブラウザ(Chrome/FF)拡張機能を作成したいと思います。 Firebugの要素インスペクターと同じように動作させたいです。検査矢印をクリックすると、要素にカーソルを合わせてハイライト表示できます。必要な要素をクリックすると、その要素が検査されます。私は、ユーザーが要素を選択できるようにするコードに興味があります。実際に要素を検査したり、同様のものを調べたりすることではありません。

私は拡張機能を書いているので、jQuery/Prototype/etc ..以外のコードを提供できれば、それを配布する必要がないのでいいかもしれません。

30
Chad

別のプロジェクトのコンポーネントとしてjQueryを使用して、この実装を作成しました。ソースとドキュメントはここから入手できます: https://github.com/andrewchilds/jQuery.DomOutline

18
Andrew Childs

私は最近、作業中のプロジェクトにそのような機能を必要としましたが、ボックスを作成するために側面に使用する必要があることがわかりました。そうしないと、マウスを動かしたときに_event.target_がセレクターになり、 _z-index: -1_を使用することになっていましたが、重複する要素がたくさんある場合は、少し fishy になります...など.

これは私があなたの利益のために私のプロジェクトから変換したバージョンです、それはjQueryを含みますが、jQueryのmousemovecssメソッドだけが使われるので Vanilla に変換するのは非常に簡単です。

ステップバイステップの説明。

まず、必要な5 HTMLElementsを作成します。

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

次に、mousemove(またはコンテナ)にdocumentイベントを作成します

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

次に、mousemove内で、_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;
_

次に、セレクターのすべての4側についてpositionheightを計算するだけです。

_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オブジェクトが内部イベントハンドラーであることに気付きました。デモで外部に移動しました。これは非常に重要です。パフォーマンスが向上したのは、elementsオブジェクトが作成されるのは数十万ではなく1回であるためです数百万mousemoveイベント内で何度も作成されます。

17
iConnor

これを行う簡単な方法の1つは、境界線の代わりにアウトラインを使用することです。

.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 で似たようなものを使用しています。

10
antonj

私はFirebugグループに尋ねることになり、いくつかの大きな助けを得ました:

http://groups.google.com/group/firebug/browse_thread/thread/7d4bd89537cd24e7/2c9483d699efe257?hl=en#2c9483d699efe257

7
Chad

これもチェックしてください:

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

私はそれがかなり洞察に満ちていると思いました..そしてここにデモがあります:

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

お役に立てれば。

3
abourget

HTML要素ピッカー(Vanilla JS)

Vanilla JSのみを含むページ上のHTML要素を選択して強調表示します! Chrome、FF、Operaでテスト済みですが、IEでは機能しません。

使い方:

必要なものは実際には非常に単純です。 JSで背景のある空のdivボックスを作成し、それを移動して、ホバーされた要素の上で強調表示することができます。 JSコードは次のとおりです。

const hoverBox = document.createElement("div");
console.log("hoverBox: ", hoverBox);
hoverBox.style.position = "absolute";
// change to whatever highlight color you want
hoverBox.style.background = "rgba(153, 235, 255, 0.5)";
// avoid blocking the hovered element and its surroundings
hoverBox.style.zIndex = "0";
document.body.appendChild(hoverBox);
let previousTarget;
document.addEventListener("mousemove", (e) => {
    let target = e.target;
    if (target === hoverBox) {
        // the truely hovered element behind the added hover box
        const hoveredElement = document.elementsFromPoint(e.clientX, e.clientY)[1];
        if (previousTarget === hoveredElement){
            // avoid repeated calculation and rendering
            return;
        } else{
            target = hoveredElement;
        }
    } else{
        previousTarget = target;
    }
    const targetOffset = target.getBoundingClientRect();
    const targetHeight = targetOffset.height;
    const targetWidth = targetOffset.width;
    // add a border around hover box
    const boxBorder = 5;
    hoverBox.style.width = targetWidth + boxBorder * 2 + "px";
    hoverBox.style.height = targetHeight + boxBorder * 2 + "px";
    // need scrollX and scrollY to account for scrolling
    hoverBox.style.top = targetOffset.top + window.scrollY - boxBorder + "px";
    hoverBox.style.left = targetOffset.left + window.scrollX - boxBorder + "px";
});

デモを参照
また、背景色、境界線の幅、トランジションなど、さらに多くのユーザー構成を備えた要素ピッカー用に npmパッケージ を作成しました。これが GitHubページ です。

3
AlienKevin

これは、代わりに純粋な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

2
hsynlms

Stackoverflowで同様の質問があり、多くの良い答えがありました: DOMインスペクターのjavascriptライブラリまたはプラグインを知っている人はいますか?

迅速で汚い解決策を探している人のために:

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 にあります。

2
netvarun

あなたがする必要があるのは、ハイライトのための4つの要素を作成することです。それらは空の正方形を形成するため、マウスイベントは自由に発生します。これはこれに似ています オーバーレイの例 私が作成しました。

違いは、4つの要素のみが必要であり(サイズ変更マーカーは不要)、4つのボックスのサイズと位置が少し異なることです(赤い境界線を模倣するため)。次に、イベントハンドラーでevent.targetを使用できます。これは、デフォルトで実際の最上位要素を取得するためです。

別のアプローチは、exra要素を非表示にし、elementFromPointを取得し、計算してから元に戻すことです。

彼らは光よりも速いです、私はあなたに言うことができます。アインシュタインでさえ同意するでしょう:)

1。)elementFromPointオーバーレイ/ボーダー-[ 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);
}
1
gblazex

.onmouseovere.targetを使用すると、jQueryを使用せずに非常に基本的な実装を非常に簡単に実行できます。

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;
}

デモ


エッジの近くの要素のみを選択する(またはエッジの近くの親とその他の場所の要素自体を選択する)場合は、.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;
  }
});

いくつかの境界線と組み合わせると、これは選択にかなり使用できます。 デモ

1
Zach Saucier