UNPKG

7.15 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = unique;
7
8var _getID = require('./getID');
9
10var _getClasses = require('./getClasses');
11
12var _getAttributes = require('./getAttributes');
13
14var _getNthChild = require('./getNthChild');
15
16var _getTag = require('./getTag');
17
18var _isUnique = require('./isUnique');
19
20var _getParents = require('./getParents');
21
22/**
23 * Returns all the selectors of the elmenet
24 * @param { Object } element
25 * @return { Object }
26 */
27function getAllSelectors(el, selectors, attributesToIgnore) {
28 var funcs = {
29 'Tag': _getTag.getTag,
30 'NthChild': _getNthChild.getNthChild,
31 'Attributes': function Attributes(elem) {
32 return (0, _getAttributes.getAttributes)(elem, attributesToIgnore);
33 },
34 'Class': _getClasses.getClassSelectors,
35 'ID': _getID.getID
36 };
37
38 return selectors.reduce(function (res, next) {
39 res[next] = funcs[next](el);
40 return res;
41 }, {});
42}
43
44/**
45 * Tests uniqueNess of the element inside its parent
46 * @param { Object } element
47 * @param { String } Selectors
48 * @return { Boolean }
49 */
50/**
51 * Expose `unique`
52 */
53
54function testUniqueness(element, selector) {
55 var parentNode = element.parentNode;
56
57 var elements = parentNode.querySelectorAll(selector);
58 return elements.length === 1 && elements[0] === element;
59}
60
61/**
62 * Checks all the possible selectors of an element to find one unique and return it
63 * @param { Object } element
64 * @param { Array } items
65 * @param { String } tag
66 * @return { String }
67 */
68function getUniqueCombination(element, items, tag) {
69 var combinations = getCombinations(items);
70 var uniqCombinations = combinations.filter(testUniqueness.bind(this, element));
71 if (uniqCombinations.length) return uniqCombinations[0];
72
73 if (Boolean(tag)) {
74 var _combinations = items.map(function (item) {
75 return tag + item;
76 });
77 var _uniqCombinations = _combinations.filter(testUniqueness.bind(this, element));
78 if (_uniqCombinations.length) return _uniqCombinations[0];
79 }
80
81 return null;
82}
83
84/**
85 * Returns a uniqueSelector based on the passed options
86 * @param { DOM } element
87 * @param { Array } options
88 * @return { String }
89 */
90function getUniqueSelector(element, selectorTypes, attributesToIgnore) {
91 var foundSelector = void 0;
92
93 var elementSelectors = getAllSelectors(element, selectorTypes, attributesToIgnore);
94
95 var _iteratorNormalCompletion = true;
96 var _didIteratorError = false;
97 var _iteratorError = undefined;
98
99 try {
100 for (var _iterator = selectorTypes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
101 var selectorType = _step.value;
102 var ID = elementSelectors.ID,
103 Tag = elementSelectors.Tag,
104 Classes = elementSelectors.Class,
105 Attributes = elementSelectors.Attributes,
106 NthChild = elementSelectors.NthChild;
107
108 switch (selectorType) {
109 case 'ID':
110 if (Boolean(ID) && testUniqueness(element, ID)) {
111 return ID;
112 }
113 break;
114
115 case 'Tag':
116 if (Boolean(Tag) && testUniqueness(element, Tag)) {
117 return Tag;
118 }
119 break;
120
121 case 'Class':
122 if (Boolean(Classes) && Classes.length) {
123 foundSelector = getUniqueCombination(element, Classes, Tag);
124 if (foundSelector) {
125 return foundSelector;
126 }
127 }
128 break;
129
130 case 'Attributes':
131 if (Boolean(Attributes) && Attributes.length) {
132 foundSelector = getUniqueCombination(element, Attributes, Tag);
133 if (foundSelector) {
134 return foundSelector;
135 }
136 }
137 break;
138
139 case 'NthChild':
140 if (Boolean(NthChild)) {
141 return NthChild;
142 }
143 }
144 }
145 } catch (err) {
146 _didIteratorError = true;
147 _iteratorError = err;
148 } finally {
149 try {
150 if (!_iteratorNormalCompletion && _iterator.return) {
151 _iterator.return();
152 }
153 } finally {
154 if (_didIteratorError) {
155 throw _iteratorError;
156 }
157 }
158 }
159
160 return '*';
161}
162
163/**
164 * Returns all the possible selector combinations
165 */
166function getCombinations(items) {
167 items = items ? items : [];
168 var result = [[]];
169 var i = void 0,
170 j = void 0,
171 k = void 0,
172 l = void 0,
173 ref = void 0,
174 ref1 = void 0;
175
176 for (i = k = 0, ref = items.length - 1; 0 <= ref ? k <= ref : k >= ref; i = 0 <= ref ? ++k : --k) {
177 for (j = l = 0, ref1 = result.length - 1; 0 <= ref1 ? l <= ref1 : l >= ref1; j = 0 <= ref1 ? ++l : --l) {
178 result.push(result[j].concat(items[i]));
179 }
180 }
181
182 result.shift();
183 result = result.sort(function (a, b) {
184 return a.length - b.length;
185 });
186 result = result.map(function (item) {
187 return item.join('');
188 });
189
190 return result;
191}
192
193/**
194 * Generate unique CSS selector for given DOM element
195 *
196 * @param {Element} el
197 * @return {String}
198 * @api private
199 */
200
201function unique(el) {
202 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
203 var _options$selectorType = options.selectorTypes,
204 selectorTypes = _options$selectorType === undefined ? ['ID', 'Class', 'Tag', 'NthChild'] : _options$selectorType,
205 _options$attributesTo = options.attributesToIgnore,
206 attributesToIgnore = _options$attributesTo === undefined ? ['id', 'class', 'length'] : _options$attributesTo;
207
208 var allSelectors = [];
209 var parents = (0, _getParents.getParents)(el);
210
211 var _iteratorNormalCompletion2 = true;
212 var _didIteratorError2 = false;
213 var _iteratorError2 = undefined;
214
215 try {
216 for (var _iterator2 = parents[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
217 var elem = _step2.value;
218
219 var selector = getUniqueSelector(elem, selectorTypes, attributesToIgnore);
220 if (Boolean(selector)) {
221 allSelectors.push(selector);
222 }
223 }
224 } catch (err) {
225 _didIteratorError2 = true;
226 _iteratorError2 = err;
227 } finally {
228 try {
229 if (!_iteratorNormalCompletion2 && _iterator2.return) {
230 _iterator2.return();
231 }
232 } finally {
233 if (_didIteratorError2) {
234 throw _iteratorError2;
235 }
236 }
237 }
238
239 var selectors = [];
240 var _iteratorNormalCompletion3 = true;
241 var _didIteratorError3 = false;
242 var _iteratorError3 = undefined;
243
244 try {
245 for (var _iterator3 = allSelectors[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
246 var it = _step3.value;
247
248 selectors.unshift(it);
249 var _selector = selectors.join(' > ');
250 if ((0, _isUnique.isUnique)(el, _selector)) {
251 return _selector;
252 }
253 }
254 } catch (err) {
255 _didIteratorError3 = true;
256 _iteratorError3 = err;
257 } finally {
258 try {
259 if (!_iteratorNormalCompletion3 && _iterator3.return) {
260 _iterator3.return();
261 }
262 } finally {
263 if (_didIteratorError3) {
264 throw _iteratorError3;
265 }
266 }
267 }
268
269 return null;
270}
\No newline at end of file