forked from fczbkk/css-selector-generator
-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
126 lines (107 loc) · 2.89 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
function isElement(node)
{
return node.nodeType === Node.ELEMENT_NODE;
}
function parents(node)
{
var nodes = [];
var currentNode = node;
while (isElement(currentNode)) {
nodes.push(currentNode);
currentNode = currentNode.parentNode;
}
return nodes;
}
function tagSelector(element)
{
return element.localName.toLowerCase();
}
function idSelector(element)
{
var id = element.getAttribute("id");
return id ? "#" + id : null;
}
function classSelectors(element)
{
var selectors = [];
var classList = element.classList;
for (var i = 0, count = classList.length; i < count; ++i)
selectors.push("." + classList[i]);
return selectors;
}
function attributeSelectors(element)
{
var selectors = [];
var attributes = element.attributes;
for (var i = 0, count = attributes; i < count; ++i) {
var attribute = attributes[i];
if (attribute === "id" || attribute === "class")
continue;
selectors.push("[" + attribute.nodeName + "=" + attribute.nodeValue + "]");
}
return selectors;
}
function nthChildSelector(element)
{
var parent = element.parentNode;
if (!parent)
return null;
var count = 1;
var child = parent.firstElementChild;
while (child !== element) {
child = child.nextElementSibling;
count++;
}
return ":nth-child(" + count + ")";
}
function testSelector(element, selector)
{
if (!selector)
return false;
var elements = element.ownerDocument.querySelectorAll(selector);
return elements.length === 1 && elements[0] === element;
}
function testUniqueness(element, selector)
{
var elements = element.parentNode.querySelectorAll(selector);
return elements.length === 1 && elements[0] === element;
}
function uniqueSelector(element)
{
var id = idSelector(element);
if (id)
return id;
var tag = tagSelector(element);
if (testUniqueness(element, tag))
return tag;
var classes = classSelectors(element);
if (classes.length) {
var allClasses = classes.join();
if (testUniqueness(element, allClasses))
return allClasses;
var tagAndClass = tag + allClasses;
if (testUniqueness(element, tagAndClass))
return tagAndClass;
}
return nthChildSelector(element);
}
module.exports = function(element)
{
if (!element || !element.parentNode)
return;
var selectors = [];
parents(element).forEach(function(parent) {
var selector = uniqueSelector(parent);
if (selector)
selectors.push(selector);
});
if (!selectors.length)
return;
var selector = selectors[0];
for (var i = 0, count = selectors.length; i < count; ++i) {
if (i > 0)
selector = selectors[i] + " > " + selector;
if (testSelector(element, selector))
return selector;
}
}