I've reproduced the jQuery selector function in JavaScript.
Here are the two rules that come with this function:
- You may not use any JavaScript libraries.
document.querySelector/document.querySelectorAll
may not be used.
var $ = function (selector) {
var elements = [];
// get starting index position of id / class
var classPosition = selector.split('').indexOf(".");
var idPosition = selector.split('').indexOf("#");
// split selector into array
var selectorArray = selector.split("");
if ( classPosition === -1 && idPosition === -1){
// simply set equal elements to DOM object with the specific tag name
elements = document.getElementsByTagName(selector);
}else if (classPosition > -1 && idPosition === -1 ){
if (classPosition === 0) {
selectorArray.shift();
// array elements returns DOM object with the desired class name
elements = document.getElementsByClassName(selectorArray.join(""));
}else {
// array elements returns DOM object with the matching class
var tagElem = selectorArray.slice(0,classPosition).join("");
var className = selectorArray.slice(classPosition + 1,selectorArray.length).join("");
var tagElemCollection = document.getElementsByTagName(tagElem);
// iterate through DOM object check if class match match className
for (var i = 0; i < tagElemCollection.length; i++) {
if (tagElemCollection[i].className != "") {
var eachClass = tagElemCollection[i].className.split(" ");
for (var e = 0;e < eachClass.length;e++) {
if (eachClass[e] === className ) {
elements.push(tagElemCollection[i]);
}
}
}
}
}
}else if ( idPosition > -1 && classPosition === -1){
if (idPosition === 0) {
// array elements returns DOM object if an id is passed in
selectorArray.shift();
elements.push(document.getElementById(selectorArray.join("")));
}else {
var tagElem = selectorArray.slice(0,idPosition).join("");
var idName = selectorArray.slice(idPosition + 1,selectorArray.length).join("");
var tagElemCollection = document.getElementsByTagName(tagElem);
// iterate through DOM object check if id match match idName (same logic as before)
for (var i = 0; i < tagElemCollection.length; i++) {
if (tagElemCollection[i].id != "") {
var eachId = tagElemCollection[i].id.split(" ");
for (var e = 0;e < eachId.length;e++) {
if (eachId[e] === idName ) {
elements.push(tagElemCollection[i]);
}
}
}
}
}
}else if (idPosition > -1 && classPosition > -1){
// check if position of id is before position of class
if (idPosition < classPosition) {
var selectorIdTag = selectorArray.slice(idPosition,classPosition);
selectorIdTag.shift();
// push in elements the DOM object with id specified
elements.push(document.getElementById(selectorIdTag.join("")));
}else{
// if class is before id loop through DOM object with that class and select
// only the one that has also the id specified.
var selectorClassTag = selectorArray.slice(classPosition,idPosition);
var selectorIdTag = selectorArray.slice(idPosition, selectorArray.length);
selectorClassTag.shift();
selectorIdTag.shift();
var ClassMatch = document.getElementsByClassName(selectorClassTag.join(""));
for (var p=0; p < ClassMatch.length; p++){
if (ClassMatch[p].id === selectorIdTag.join("") ){
elements.push(ClassMatch[p]);
}
}
}
}
return elements;
}
Here, the function $
takes an argument selector
which is a string representing the desired DOM element.
Example
Let's say I have an HTML page that looks like this:
<html>
<head>
<script src="Answer.js"></script>
</head>
<body onload="test$()">
<div></div>
<div id="some_id" class="some_class some_other_class"></div>
<img id="some_other_id" class="some_class some_other_class"></img>
<input type="text">
</body>
</html>
Using the function $
just created, select the element div
of class some_other_class
:
$('div.some_other_class')
returns an array containing the desired element(s):
[<div id="some_id" class="some_class some_other_class"></div>]
I'd like to know about the quality and performance of my code. I do feel like I'm doing too many iterations.