Jquery에서 고유한 요소 선택기 가져오기
나는 사용자의 모든 행동을 추적하는 레코더와 같은 것을 만들고 싶습니다. 이를 위해서는 사용자가 상호 작용하는 요소를 식별해야 나중에 세션에서 이러한 요소를 참조할 수 있습니다.
의사 코드로 말하면 다음과 같은 것을 할 수 있기를 원합니다.
샘플 HTML(복잡할 수 있음):
<html>
<body>
<div class="example">
<p>foo</p>
<span><a href="bar">bar</a></span>
</div>
</body>
</html>
사용자가 링크와 같은 항목을 클릭합니다. 이제 클릭한 요소를 식별하고 나중에 사용할 수 있도록 DOM 트리에 위치를 저장해야 합니다.
(any element).onclick(function() {
uniqueSelector = $(this).getUniqueSelector();
})
이제 uniqueSelector는 다음과 같아야 합니다(xpath 또는 css 선택기 스타일인 경우 상관 없음).
html > body > div.example > span > a
이렇게 하면 해당 선택기 문자열을 저장하고 나중에 사용자가 수행한 작업을 재생하는 데 사용할 수 있습니다.
어떻게 그게 가능합니까?
업데이트
내 대답을 얻었습니다 : 요소에 대한 jQuery 선택기 얻기
수정해야 하는 솔루션을 찾았기 때문에 직접 답변하겠습니다. 다음 스크립트가 작동 중이며 Blixt 의 스크립트를 기반으로 합니다 .
jQuery.fn.extend({
getPath: function () {
var path, node = this;
while (node.length) {
var realNode = node[0], name = realNode.localName;
if (!name) break;
name = name.toLowerCase();
var parent = node.parent();
var sameTagSiblings = parent.children(name);
if (sameTagSiblings.length > 1) {
var allSiblings = parent.children();
var index = allSiblings.index(realNode) + 1;
if (index > 1) {
name += ':nth-child(' + index + ')';
}
}
path = name + (path ? '>' + path : '');
node = parent;
}
return path;
}
});
@Alp의 것과 동일한 솔루션이지만 여러 jQuery 요소와 호환됩니다.
jQuery('.some-selector')
하나 이상의 DOM 요소가 발생할 수 있습니다. @Alp의 솔루션은 불행히도 첫 번째 솔루션에서만 작동합니다. 내 솔루션은 모든 항목을 ,
.
첫 번째 요소만 처리하려면 다음과 같이 하십시오.
jQuery('.some-selector').first().getPath();
// or
jQuery('.some-selector:first').getPath();
개선된 버전
jQuery.fn.extend({
getPath: function() {
var pathes = [];
this.each(function(index, element) {
var path, $node = jQuery(element);
while ($node.length) {
var realNode = $node.get(0), name = realNode.localName;
if (!name) { break; }
name = name.toLowerCase();
var parent = $node.parent();
var sameTagSiblings = parent.children(name);
if (sameTagSiblings.length > 1)
{
var allSiblings = parent.children();
var index = allSiblings.index(realNode) + 1;
if (index > 0) {
name += ':nth-child(' + index + ')';
}
}
path = name + (path ? ' > ' + path : '');
$node = parent;
}
pathes.push(path);
});
return pathes.join(',');
}
});
(any element).onclick(function() {
uniqueSelector = $(this).getUniqueSelector();
})
this
IS 고유 선택자 및 클릭한 요소에 대한 경로입니다. 왜 그것을 사용하지 않습니까? jquery의 $.data()
방법을 활용 하여 jquery 선택기를 설정할 수 있습니다 . 또는 앞으로 사용해야 하는 요소를 푸시하면 됩니다.
var elements = [];
(any element).onclick(function() {
elements.push(this);
})
xpath가 정말로 필요한 경우 다음 코드를 사용하여 계산할 수 있습니다.
function getXPath(node, path) {
path = path || [];
if(node.parentNode) {
path = getXPath(node.parentNode, path);
}
if(node.previousSibling) {
var count = 1;
var sibling = node.previousSibling
do {
if(sibling.nodeType == 1 && sibling.nodeName == node.nodeName) {count++;}
sibling = sibling.previousSibling;
} while(sibling);
if(count == 1) {count = null;}
} else if(node.nextSibling) {
var sibling = node.nextSibling;
do {
if(sibling.nodeType == 1 && sibling.nodeName == node.nodeName) {
var count = 1;
sibling = null;
} else {
var count = null;
sibling = sibling.previousSibling;
}
} while(sibling);
}
if(node.nodeType == 1) {
path.push(node.nodeName.toLowerCase() + (node.id ? "[@id='"+node.id+"']" : count > 0 ? "["+count+"]" : ''));
}
return path;
};
참조: http://snippets.dzone.com/posts/show/4349
더 나은 솔루션은 임의의 ID를 생성한 다음 해당 ID를 기반으로 요소에 액세스하는 것입니다.
고유 ID 할당:
// or some other id-generating algorithm
$(this).attr('id', new Date().getTime());
고유 ID를 기반으로 선택:
// getting unique id
var uniqueId = $(this).getUniqueId();
// or you could just get the id:
var uniqueId = $(this).attr('id');
// selecting by id:
var element = $('#' + uniqueId);
// if you decide to use another attribute other than id:
var element = $('[data-unique-id="' + uniqueId + '"]');
질문은 jQuery에 대한 것이지만 ES6에서는 Vanilla JavaScript용 @Alp와 유사한 것을 얻는 것이 매우 쉽습니다( nameCount
사용을 최소화하기 위해 추적하는 몇 줄도 추가했습니다 nth-child
).
function getSelectorForElement (elem) {
let path;
while (elem) {
let subSelector = elem.localName;
if (!subSelector) {
break;
}
subSelector = subSelector.toLowerCase();
const parent = elem.parentElement;
if (parent) {
const sameTagSiblings = parent.children;
if (sameTagSiblings.length > 1) {
let nameCount = 0;
const index = [...sameTagSiblings].findIndex((child) => {
if (elem.localName === child.localName) {
nameCount++;
}
return child === elem;
}) + 1;
if (index > 1 && nameCount > 1) {
subSelector += ':nth-child(' + index + ')';
}
}
}
path = subSelector + (path ? '>' + path : '');
elem = parent;
}
return path;
}
순수 자바스크립트 솔루션
참고: 이것은 Array.from 및 Array.prototype.filter를 사용합니다 . 둘 다 IE11에서 폴리필해야 합니다.
function getUniqueSelector(node) {
let selector = "";
while (node.parentElement) {
const siblings = Array.from(node.parentElement.children).filter(
e => e.tagName === node.tagName
);
selector =
(siblings.indexOf(node)
? `${node.tagName}:nth-of-type(${siblings.indexOf(node) + 1})`
: `${node.tagName}`) + `${selector ? " > " : ""}${selector}`;
node = node.parentElement;
}
return `html > ${selector.toLowerCase()}`;
}
용법
getUniqueSelector(document.getElementsByClassName('SectionFour')[0]);
getUniqueSelector(document.getElementById('content'));
이 답변은 원래 질문 설명을 충족하지 않지만 제목 질문에 대한 답변입니다. 요소에 대한 고유 선택기를 얻는 방법을 찾고 있는 이 질문에 왔지만 선택기가 페이지 로드 간에 유효할 필요가 없었습니다. 따라서 내 대답은 페이지 로드 간에 작동하지 않습니다.
DOM을 수정하는 것은 이상적이지는 않지만 코드 한 톨 없이 고유한 선택기를 만드는 좋은 방법이라고 생각합니다. @Eli의 답변을 읽은 후이 아이디어를 얻었습니다.
고유한 값으로 사용자 정의 속성을 할당하십시오.
$(element).attr('secondary_id', new Date().getTime())
var secondary_id = $(element).attr('secondary_id');
그런 다음 해당 고유 ID를 사용하여 CSS 선택기를 빌드합니다.
var selector = '[secondary_id='+secondary_id+']';
그런 다음 요소를 선택하는 선택기가 있습니다.
var found_again = $(selector);
그리고 많은 사람들이 secondary_id
요소에 이미 속성 이 없는지 확인하고 싶어합니다 .
if ($(element).attr('secondary_id')) {
$(element).attr('secondary_id', (new Date()).getTime());
}
var secondary_id = $(element).attr('secondary_id');
함께 모아서
$.fn.getSelector = function(){
var e = $(this);
// the `id` attribute *should* be unique.
if (e.attr('id')) { return '#'+e.attr('id') }
if (e.attr('secondary_id')) {
return '[secondary_id='+e.attr('secondary_id')+']'
}
$(element).attr('secondary_id', (new Date()).getTime());
return '[secondary_id='+e.attr('secondary_id')+']'
};
var selector = $('*').first().getSelector();
ID 속성(예: id="something")이 있는 경우 다음과 같은 값을 가져와야 합니다.
var selector = "[id='" + $(yourObject).attr("id") + "']";
console.log(selector); //=> [id='something']
console.log($(selector).length); //=> 1
ID 속성이 없고 선택기를 가져오려는 경우 ID 속성을 만들 수 있습니다. 위와 같은 내용,
var uuid = guid();
$(yourObject).attr("id", uuid); // Set the uuid as id of your object.
당신은 당신의 자신의 GUID 방법을 사용하거나에있는 소스 코드를 사용할 수 있습니다 이 , 대답 있도록
function guid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4();
}
findCssSelector 도 살펴볼 수 있습니다 . 코드는 내 다른 답변에 있습니다.
나는 내 자신을 위해 수정 된 솔루션을 찾았습니다. 경로 선택기 #id, .className에 추가하고 #id에 대한 경로 길이를 자릅니다.
$.fn.extend({
getSelectorPath: function () {
var path,
node = this,
realNode,
name,
parent,
index,
sameTagSiblings,
allSiblings,
className,
classSelector,
nestingLevel = true;
while (node.length && nestingLevel) {
realNode = node[0];
name = realNode.localName;
if (!name) break;
name = name.toLowerCase();
parent = node.parent();
sameTagSiblings = parent.children(name);
if (realNode.id) {
name += "#" + node[0].id;
nestingLevel = false;
} else if (realNode.className.length) {
className = realNode.className.split(' ');
classSelector = '';
className.forEach(function (item) {
classSelector += '.' + item;
});
name += classSelector;
} else if (sameTagSiblings.length > 1) {
allSiblings = parent.children();
index = allSiblings.index(realNode) + 1;
if (index > 1) {
name += ':nth-child(' + index + ')';
}
}
path = name + (path ? '>' + path : '');
node = parent;
}
return path;
}
});
다음과 같이 할 수 있습니다.
$(".track").click(function() {
recordEvent($(this).attr("id"));
});
클래스 onclick
가 있는 모든 객체에 이벤트 핸들러를 연결합니다 track
. 개체를 클릭할 때마다 개체의 ID가 recordEvent()
함수에 입력됩니다 . 이 함수가 각 개체의 시간과 ID 또는 원하는 것을 기록하도록 할 수 있습니다.
$(document).ready(function() {
$("*").click(function(e) {
var path = [];
$.each($(this).parents(), function(index, value) {
var id = $(value).attr("id");
var class = $(value).attr("class");
var element = $(value).get(0).tagName
path.push(element + (id.length > 0 ? " #" + id : (class.length > 0 ? " .": "") + class));
});
console.log(path.reverse().join(">"));
return false;
});
});
작업 예: http://jsfiddle.net/peeter/YRmr5/
* 선택기(매우 느림)를 사용하고 이벤트 버블링을 중지할 때 문제가 발생할 수 있지만 더 많은 HTML 코드 없이는 실제로 도움이 되지 않습니다.
당신은 그런 일을 할 수 있습니다 (테스트되지 않음)
function GetPathToElement(jElem)
{
var tmpParent = jElem;
var result = '';
while(tmpParent != null)
{
var tagName = tmpParent.get().tagName;
var className = tmpParent.get().className;
var id = tmpParent.get().id;
if( id != '') result = '#' + id + result;
if( className !='') result = '.' + className + result;
result = '>' + tagName + result;
tmpParent = tmpParent.parent();
}
return result;
}
이 기능은 요소에 대한 "경로"를 저장합니다. 이제 나중에 요소를 다시 찾기 위해 html과 같은 방식으로 거의 불가능할 것입니다. 이 기능에서는 각 요소의 형제 인덱스를 저장하지 않고 저장만 하기 때문입니다. ID 및 클래스.
따라서 html 문서의 모든 요소에 ID가 없으면 이 접근 방식은 작동하지 않습니다.
ReferenceURL : https://stackoverflow.com/questions/5706837/get-unique-selector-of-element-in-jquery
'IT이야기' 카테고리의 다른 글
함수의 arity 얻기 (0) | 2021.10.17 |
---|---|
오래된 DLL 파일이 계속 사용 중입니다. (0) | 2021.10.17 |
AngularJS 컨트롤러에서 현재 범위 dom-element를 얻으려면 (0) | 2021.10.16 |
Composer 패키지를 개발하고 포함하는 방법 (0) | 2021.10.16 |
임의의 파이썬 소스 파일을 가져옵니다. (0) | 2021.10.16 |