Skip to content

Instantly share code, notes, and snippets.

@jung-han
Created May 4, 2018 00:14
Show Gist options
  • Save jung-han/051b5c760b5a056c7bd490ddff9d0a0f to your computer and use it in GitHub Desktop.
Save jung-han/051b5c760b5a056c7bd490ddff9d0a0f to your computer and use it in GitHub Desktop.
'use strict';
var arrayutil = require('./arrayutil');
var domutil = {
getElementsByClassName: function(element, selector) {
if (!selector) {
throw new Error('Uncaught TypeError: Failed to execute "getElementsByClassName": 1 argument required, but only 0 present.');
}
if (!element.getElementsByClassName) {
element.getElementsByClassName = function(query) {
return element.querySelectorAll('.' + query);
};
}
return Array.prototype.slice.call(document.getElementsByClassName(selector));
},
getElementById: function(element, selector) {
return element.getElementById(selector);
},
getElementsByTagName: function(element, selector) {
return Array.prototype.slice.call(element.getElementsByTagName(selector));
},
querySelector: function(selector) {
var result = domutil.querySelectorAll(selector);
return result.length > 0 ? result[0] : null;
},
querySelectorAll: function(selector) {
var selectorArr = [],
firstNodes = [],
retFirstNodes = [],
resultNodes = [],
multipleQueryArr = [],
firstNodesLen,
queryType,
query,
queryArrLen,
node,
i,
customQuerySelectorAll,
getFirstNodes,
selectorArrLen;
if (!selector) {
throw new Error('Uncaught TypeError: Failed to execute "querySelector": 1 argument required, but only 0 present.');
}
selectorArr = selector.split(' ');
selectorArrLen = selectorArr.length;
for (i = 0; i < selectorArrLen; i += 1) {
selectorArr[i] = arrayutil.removeEmptyString(selectorArr[i].replace('.', ' .').replace('#', ' #').split(' '));
if (!this.isValidMultipleSelector(selectorArr[i])) {
throw new Error('Failed to execute "querySelector": ' + selectorArr[i] + ' is not a valid selector.');
}
}
getFirstNodes = function(queryArr) {
multipleQueryArr = queryArr[queryArrLen - 1];
query = multipleQueryArr[0];
queryType = domutil.getSelectorType(query);
if (queryType === 'class') {
firstNodes = domutil.getElementsByClassName(document, query.slice(1));
} else if (queryType === 'id') {
firstNodes = new Array(domutil.getElementById(document, query.slice(1)));
} else {
firstNodes = domutil.getElementsByTagName(document, query);
}
for (i = 0; i < firstNodes.length; i += 1) {
if (domutil.isMatchToAllQueiresNode(firstNodes[i], multipleQueryArr, 1)) {
retFirstNodes.push(firstNodes[i]);
}
}
return retFirstNodes;
};
customQuerySelectorAll = function(queryArr) {
queryArrLen = queryArr.length;
firstNodes = getFirstNodes(queryArr);
if (queryArrLen > 1) {
firstNodesLen = firstNodes.length;
for (i = 0; i < firstNodesLen; i += 1) {
node = firstNodes[i];
if (domutil.isMatchingToQueriesNode(node.parentNode, queryArr)) {
resultNodes.push(node);
}
}
} else {
resultNodes = firstNodes;
}
return arrayutil.removeDuplicates(resultNodes);
};
return customQuerySelectorAll(selectorArr);
},
getSelectorType: function(selector) {
var type;
switch (selector[0]) {
case '#':
type = 'id';
break;
case '.':
type = 'class';
break;
default:
type = 'tag';
}
return type;
},
isMatchToAllQueiresNode: function(node, queryArr, startIdx) {
var i,
queryArrLen = queryArr.length,
result = true;
for (i = startIdx; i < queryArrLen; i += 1) {
result = domutil.isMatchToQueryNode(node, queryArr[i]) && result;
}
return result;
},
isMatchToQueryNode: function(node, query) {
var queryType = domutil.getSelectorType(query);
if (queryType === 'class') {
return domutil.isNodeHavingClass(node, query.slice(1));
}
return queryType === 'id' ? domutil.isNodeHavingId(node, query.slice(1)) : domutil.isNodeHavingTagName(node, query);
},
isNodeHavingClass: function(node, className) {
var re = new RegExp('\\b\\*?' + className + '*\\b', 'g');
return re.test(node.className);
},
isNodeHavingId: function(node, id) {
return node.id === id;
},
isNodeHavingTagName: function(node, tagName) {
return node.tagName.toLowerCase() === tagName.toLowerCase();
},
isMatchingToQueriesNode: function(node, queryArr) {
var queryArrLen = queryArr.length,
query,
matchToQuery,
queryArrIdx = queryArrLen - 2;
while (node.parentNode !== null) {
query = queryArr[queryArrIdx];
matchToQuery = domutil.isMatchToAllQueiresNode(node, query, 0);
node = node.parentNode;
if (queryArrIdx === 0 && matchToQuery) {
break;
}
if (matchToQuery) {
queryArrIdx -= 1;
}
}
return queryArrIdx === 0 && matchToQuery;
},
isValidSelector: function(selector) {
var re = /^[$,.,#,_0-9a-zA-Z]{0,1}[a-zA-Z0-9-_]{1}[#.a-zA-Z0-9-_]{0,}/;
return re.test(selector);
},
isValidMultipleSelector: function(selectorArr) {
var i;
for (i = 0; i < selectorArr.length; i += 1) {
if (!this.isValidSelector(selectorArr[i])) {
return false;
}
}
return true;
}
};
module.exports = domutil;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment