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.
1 Answer 1
First off, you have a bug. On the line if (tagElemCollection[i].id != "") {
, you used the !=
operator instead of the !==
operator. This line should be changed to if (tagElemCollection[i].id !== "") {
.
Secondly, you have some spacing inconsistencies. For example, you wrote }else {
in some places, and }else{
in others, when it should be } else {
, and/or } else if {
. You also have stuff like this, (var e = 0;e < eachId.length;e++)
, or this (var p=0; p < ClassMatch.length; p++)
, that can both be typed like this: (var name = ...; name ... value; name...)
. Try to find inconsistencies like these and change them.
Finally, you have some indentation issues. The general style is that lines should be indented by one tab, or four spaces if they're in a if/else if/else/function/etc
block.
Explore related questions
See similar questions with these tags.