5
\$\begingroup\$

I've reproduced the jQuery selector function in JavaScript.

Here are the two rules that come with this function:

  1. You may not use any JavaScript libraries.
  2. 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.

\$\endgroup\$
5
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.