Javascript:Разрешить пользователю выбрать элемент HTML, например Firebug?
-
25-09-2019 - |
Вопрос
Я хочу написать расширение браузера (Chrome/FF), которое должно выбирать элемент на веб-странице.Я бы хотел, чтобы он вел себя так же, как инспектор элементов Firebug.Вы нажимаете стрелку проверки и затем можете навести/выделить элементы.Когда вы нажимаете на нужный элемент, он проверяется.Меня просто интересует код, позволяющий пользователю выбирать элемент, а не его фактическая проверка или что-то подобное.
Поскольку я пишу расширение, было бы неплохо, если бы вы предоставили не-jQuery/Prototype/etc..код, поэтому мне не придется его распространять.
Решение
Я написал реализацию этого, используя jQuery в качестве компонента другого проекта. Источник и документация доступны здесь: https://github.com/andrewchilds/jquery.domoutline.
Другие советы
Я недавно требовал такой функции для проекта, над которой я работал, оказался, что мне пришлось использовать для боковых сторон, чтобы создать коробку, потому что в противном случае event.target
Когда вы двигаете мышь, в конечном итоге будет селектор, и если бы я использовал z-index: -1
Это было бы немного рыбный Когда у вас есть много элементов, которые перекрываются ... и т. Д.
Вот версия, которую я преобразовал из моего проекта для вашей выгоды, он включает в себя jQuery, но это чрезвычайно просто преобразовать в ваниль как только то mousemove
& css
Используются методы от jQuery.
Шаг за шагом инструкции.
Сначала создайте 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 Стороны селектора вроде так.
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
Объект создан только однажды вместо Сотни тысяч если не миллионы раз внутри mousemove
мероприятие.
Один простой способ сделать это - использовать наброски вместо границы:
.highlight { outline: 4px solid #07C; }
Просто добавьте и удалите этот класс на любой элемент, который вы хотите выбрать / SELECELECT (код ниже не проверяется правильно):
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.
Я закончил просить в группе Firebug и получил большую помощь:
Также проверьте этот раз:
http://rockingcode.com/tutorial /lement-dom-tree-jquery-plugin-firebug-like-funnality/
Я нашел это довольно проницательным .. И здесь демонстрация:
http://rockingcode.com/demos/elemtree/
Надеюсь это поможет.
HTML Picker (Vanilla JS)
Выберите и выделите любой HTML-элемент на странице с только ванильными JS! Испытано в Chrome, FF и Opera, не работает в IE.
Как это работает:
То, что вам нужно, на самом деле очень просто. Вы можете просто создать пустую коробку Div с фоном в JS и переместите его, чтобы выделить на вершине навязчивых элементов. Вот код 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.
Был подобный вопрос, заданный на StackoverFlow, и у него было много хороших ответов:Кто-нибудь знает библиотеку или плагин DOM инспектора JavaScript?
Для тех, кто ищет быстрое и грязное решение:
http://userscripts.org/scripts/review/3006. это самый простой. Просто поставьте код в течение <script></script>
Теги, и вы хороши, чтобы пойти.
https://github.com/josscrowcroft/simple-javascript-dom-inspector/blob/master/inspector.js. немного лучше и все еще очень легко интегрироваться.
Для более изощренного элемента инспектора вы можете захотеть проверить селекторгаджет, как указано на UDI. Код выбора инспектора находится в http://www.selectorgadget.com/stable/lib/interface.js.
Вот библиотека, написанная в чистом JavaScript в качестве альтернативы.
THAROM 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);
Вам нужно создать 4 элемента для подсветки.Они сформируют пустой квадрат, и поэтому ваши события мыши могут запускаться свободно.Это похоже на это пример наложения Я сделал.
Разница в том, что вам нужны только четыре элемента (без маркеров изменения размера), а размер и положение четырех блоков немного отличаются (чтобы имитировать красную рамку).Тогда вы можете использовать event.target
в вашем обработчике событий, потому что по умолчанию он получает самый верхний элемент.
Другой подход это скрыть дополнительный элемент, получить elementFromPoint
, посчитай и положи обратно.
Я вам скажу, они быстрее света.Даже Эйнштейн согласился бы :)
1.) наложение/границы elementFromPoint - [Демо1] ФФ нужна версия 3.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.) границы при наведении курсора мыши - [Демо2]
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);
}
Очень базовая реализация может быть сделана очень легко без 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;
}
Если вы хотите выбрать элементы только рядом с краями (или выберите родитель рядом с краями и сам элемент везде) вы можете использовать .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;
}
});
Сопряжены с некоторыми границами, это может быть довольно полезно для выбора. Демонстрация