Ausnahme gefangen: SSL certificate problem: certificate is not yet valid 📌 Make your own jQuery from scratch

🏠 Team IT Security News

TSecurity.de ist eine Online-Plattform, die sich auf die Bereitstellung von Informationen,alle 15 Minuten neuste Nachrichten, Bildungsressourcen und Dienstleistungen rund um das Thema IT-Sicherheit spezialisiert hat.
Ob es sich um aktuelle Nachrichten, Fachartikel, Blogbeiträge, Webinare, Tutorials, oder Tipps & Tricks handelt, TSecurity.de bietet seinen Nutzern einen umfassenden Überblick über die wichtigsten Aspekte der IT-Sicherheit in einer sich ständig verändernden digitalen Welt.

16.12.2023 - TIP: Wer den Cookie Consent Banner akzeptiert, kann z.B. von Englisch nach Deutsch übersetzen, erst Englisch auswählen dann wieder Deutsch!

Google Android Playstore Download Button für Team IT Security



📚 Make your own jQuery from scratch


💡 Newskategorie: Programmierung
🔗 Quelle: dev.to

jQuery is one of the most popular JavaScript library . It greatly simplifies JavaScript programming. You might be curious about how jQuery is made. If you look through the source code of any well-known library, it's likely that you won't understand anything or you may feel that you need to be a genius to build one. However, it's not as difficult as it seems in reality. In this article I'm going show you how you can make your own library like jQuery from scratch.

Lets get started!

Creating the selector function

const $ = function(el) {
    return new jQuery(el);
}

As you can see the selector function returns a class named jQuery. Every time you use the selector a new instance of jQuery will be created .

Now lets create our jQuery Class

jQuery object

 class jQuery extends Array{
    constructor(el) {
        super();
        if (el == document || el instanceof HTMLElement) {
            this.push(el);
        } else {
            let elements=document.querySelectorAll(el);
            for(let i=0;i<elements.length;i++){
                this.push(elements[i]);
            }
        }
    }
}

Our jQuery class extends the build-in Array class so every instance behave like an array and an object at the same time.Every time we create a new jQuery instance it checks if the element is html element or if it is the document itself. If not then it performs a querySelectorAll to get the all matched elements. Then it pushes each element to itself. Now we can add our methods to it.

Chaining

The best thing I like about jQuery is that you can chain methods, like

$('div').addClass('red').html('hello');

to apply Chaining to our jQuery class we just need to return the current instance, i.e adding
return this after every method.

ready()

ready(callback){
    this[0].addEventListener('readystatechange', e => {
        if(this[0].readyState === "complete"){
            callback();
            return true;
        }
      });
}
$(document).ready(function(){
 //codes
})

Checks the readyStates of an element if the readyState is complete than we know the element is completely loaded and ready for use;

each()

each(callback) {
    if (callback || typeof(callback) == 'function') {
        if (this[0] == document || this[0] instanceof HTMLElement){
            callback(this[0])
        }
        for (let i = 0; i < this.length; i++) {
            callback(this[i], i);
        }
        //Chaining
        return this;
    } 
}
$('div').each(function(el){
    $(el).html('text')
})

this method iterate over all elements and give a callback for each element. We will use this for creating other methods.

siblings()

siblings(){
    return  [...this[0].parentNode.children].filter(c=>c!=this[0])
}
console.log($('script').siblings())

It's a pretty simple one liner. We first select all the child elements of parent element and then just remove the current element from the list , resulting an array of sibling elements.

addClass()

addClass(className) {
    this.each(function(el) {
        el.classList.add(className);
    })
    return this;
}
$('div').addClass('pink')

we use classList.add() to add the className to each item with the help of this.each method.

removeClass()

removeClass(className) {
    this.each(function(el) {
        el.classList.remove(className);
    })
    return this;
}
$('div').removeClass('pink')

similar to addClass we use classList.remove() to remove the className .

hasClass()


hasClass((className) {
    return this[0].classList.contains(className);
}
console.log($('div').hasClass('pink')) //returns true or false

hasClass check if the 1st selected element has any specific class with the help of classList.contains() and return true or false accordingly.

css()

 css(propertyObject) {
       this.each(function(el) {
           Object.assign(el.style,propertyObject);
        })
        return this;
    }
$('div').css({
    color:'red'
})

in this method the parameter is a type of object. each property of this object is added to the element.style object using in-build Object.assign function()

attr()

attr(attr, value = null) {
    let getattr = undefined;
    if (value) {
        this.each(function(el) {
            el.setAttribute(attr, value);
            getattr = this;
        });
    } else {
            getattr = this[0].getAttribute(attr);
    }
    return getattr;
}
console.log($('div').attr('class')) //gets the attribute value
$('div').attr('name','div') //sets the name attribute with value

If the value argument is not present then we just simple return the attribute value else we set the attribute for each element.

html()

html(data) {
    if (data) {
        this.each(function(el) {
            el.innerHTML = data;
        })
    } else {
        return this[0].innerHTML;
    }
    return this;
}
console.log($('div').html()) //gets the innerHTML 
$('div').html('x') //add the innerHTML

Similar to attr() method just uses innerHTML instead of attribute

prepend()

prepend(el){
    this[0].prepend(el);
    return this;
}
let h1=document.createElement('h1');
h1.innerHTML='this is a heading';
$('div').prepend(h1) //prepend the node
$('div').prepend('hello') //prepend the string 

prepend a node or string to the selected elements using in-build node.prepend().

append()

append(el){
    this[0].append(el);
    return this;
}
let h1=document.createElement('h1');
h1.innerHTML='this is a heading';
$('div').append(h1) //append the node
$('div').append('hello') //append the string

append a node or string to the selected elements using in-build node.append().

hide()

hide() {
    this.each(function(el) {
        el.style.display = "none";
    });
    return this;
}
$('div').hide()

change the style.display property to none

show()

show() {
    this.each(function(el) {
        el.style.display = "block";
    });
    return this;
}
$('div').show()

change the style.display property to block

on()

on(event, child, callback = null) {
    if (callback != null) {
        let selector = child;
        this.each(function(element) {
            element.addEventListener(event, function(event) {
                if (event.target.matches(selector + ', ' + selector + ' *')) {
                    callback.apply(event.target.closest(selector), arguments);
                }
            })
        })
    } else {
    //if the callback argument is not present then assume  the child argument is being use as callback
        callback = child;
        this.each(function(element) {
        element.addEventListener(event, callback);
        })
    }

    return this;
}
$('div').on('click',function(){
    alert('x')
})
$(document).on('click','div',function(){
    alert('x')
})

this one is little bit complex.
If we pass all three arguments to the method it will add an EventListener to the parent element and only if the target matches child element then will give a callback.

but if we just pass two argument then it will simply add an EventListener to the element with a callback.

for the first case we can take this as an example

$(document).on('click','div',function(){
    alert('x')
})

and for the second case

$('div').on('click',function(){
    alert('x')
})

both serves their different purpose . First one is very useful for binding event to dynamic element.
Second one is useful for general event binding .

$.ajax()

$.ajax=function(args) {
        let url = args["url"];
        let type = "get";
        let success =function(){};
        let fail = function(){};
        if(args['success']){
            success=args['success'];
        }
        if(args['fail']){
            fail=args['fail'];
        }
        let xhttp = new XMLHttpRequest();
        xhttp.onerror = function(error){
        //return fial callback with error 
            return fail(error);
        }
        xhttp.onload = function() {
            let response;
            if (this.readyState == 4 && this.status == 200) {
                let response="";
                try {
                //check if the response in json 
                //if json the parse it
                    response=JSON.parse(this.responseText)
                } catch (e) {
                //if not json the simple reurn the response
                    response = this.responseText;
                    }
                 // give a success callback
                return success(response);
            } else {
            //give a fail callback with the error status 
                return fail(this.status);
            }
        };
        let parameters="";
        if (args) {
            type = args["type"];
            if ('data' in args) {
            //converting object to url URLSearchParams
                parameters = new URLSearchParams(args['data']).toString();
            }

        }
        if (type && type.toUpperCase()=='POST') {
            xhttp.open("POST", url, true);
            xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            xhttp.send(parameters);
        } else if (!type || type.toUpperCase()=='GET'){
            xhttp.open("GET", url + "?" + parameters, true);
            xhttp.setRequestHeader("X-Requested-With", "XMLHttpRequest");
            xhttp.send();
        }
    }
$.ajax({
    url:'post.php',
    type:'post',
    data:{
        name:'hello'
    },
    success: function(res){
        console.log(res)
    }
})

this ajax function is not a method but works as a property of $ object.
this function takes url,type,data,success and fail arguments just like the original jQuery.
What we do is that we create a new new XMLHttpRequest() each time the function is called and send post or get request. Now if we receive the response then we check if it is JSON response.For JSON response we parse it otherwise just simply return a success callback with the response.But if request gives a error, fail callback with the status code will be returned.

Putting it all together

class jQuery extends Array{
    constructor(el) {
        super();
        if (el == document || el instanceof HTMLElement) {
            this.push(el);
        } else {
            let elements=document.querySelectorAll(el);
            for(let i=0;i<elements.length;i++){
                this.push(elements[i]);
            }
        }
    }
    ready(callback){
        this[0].addEventListener('readystatechange', e => {
            if(this[0].readyState === "complete"){
                callback();
                return true;
            }
          });
    }
    each(callback) {
        if (callback || typeof(callback) == 'function') {
            if (this[0] == document || this[0] instanceof HTMLElement){
                callback(this[0])
            }
            for (let i = 0; i < this.length; i++) {
                callback(this[i], i);
            }
            return this;
        } 
    }
    siblings(){
        return  [...this[0].parentNode.children].filter(c=>c!=this[0])
    }
    addClass(className) {
        this.each(function(el) {
            el.classList.add(className);
        })
        return this;
    }

    removeClass(className) {
        this.each(function(el) {
            el.classList.remove(className);
        })
        return this;
    }

    hasClass(className) {
        return this[0].classList.contains(className);
    }

    css(propertyObject) {
        this.each(function(el) {
            Object.assign(el.style,propertyObject);
        })
        return this;
    }

    attr(attr, value = null) {
        let getattr = undefined;
        if (value) {
            this.each(function(el) {
                el.setAttribute(attr, value);
                getattr = this;
            });
        } else {
            getattr = this[0].getAttribute(attr);
        }
        return getattr;
    }

    html(data) {
        if (data) {
            this.each(function(el) {
                el.innerHTML = data;
            })
        } else {
            return this[0].innerHTML;
        }
        return this;
    }
    append(el){
        this[0].append(el);
        return this;
    }
    prepend(el){
        this[0].prepend(el);
        return this;
    }
    hide() {
        this.each(function(el) {
            el.style.display = "none";
        });
        return this;
    }
    show() {
        this.each(function(el) {
            el.style.display = "block";
        });
        return this;
    }
    on(event, child, callback = null, state = null) {
        if (callback != null) {
            let selector = child;
            this.each(function(element) {
                element.addEventListener(event, function(event) {
                    if (event.target.matches(selector + ', ' + selector + ' *')) {
                        callback.apply(event.target.closest(selector), arguments);
                    }
                }, false)
            })
        } else {
            callback = child;
            this.each(function(element) {
                if (state) {
                    element.addEventListener(event, callback, state);
                } else {
                    element.addEventListener(event, callback, false);
                }
            })
        }

        return this;
    }
}
const $ = function(el) {
    return new jQuery(el);
}
$.ajax=function(args) {
        let url = args["url"];
        let type = "get";
        let success =function(){};
        let fail = function(){};
        if(args['success']){
            success=args['success'];
        }
        if(args['fail']){
            fail=args['fail'];
        }
        let xhttp = new XMLHttpRequest();
        xhttp.onerror = function(error){
            return fail(error);
        }
        xhttp.onload = function() {
            let response;
            if (this.readyState == 4 && this.status == 200) {
                let response="";
                try {
                    response=JSON.parse(this.responseText)
                } catch (e) {
                    response = this.responseText;
                    }
                return success(response);
            } else {
                return fail(this.status);
            }
        };
        let parameters="";
        if (args) {
            type = args["type"];
            if ('data' in args) {
                parameters = new URLSearchParams(args['data']).toString();
            }

        }
        if (type && type.toUpperCase()=='POST') {
            xhttp.open("POST", url, true);
            xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            xhttp.send(parameters);
        } else if (!type || type.toUpperCase()=='GET'){
            xhttp.open("GET", url + "?" + parameters, true);
            xhttp.setRequestHeader("X-Requested-With", "XMLHttpRequest");
            xhttp.send();
        }
    }

Now you have your own jQuery library. Of course the Original jQuery have more methods and good optimization but this is enough for regular tasks.

IF you are interested in this type of posts please check out my
blog

Read next
Virtual Dom Diffing Algorithm Implementation In Vanilla JavaScript

...



📌 Make your own jQuery from scratch


📈 47.76 Punkte

📌 Linux from scratch vs docker scratch?


📈 28.57 Punkte

📌 Medium CVE-2020-15164: Scratch-wiki Scratch login


📈 28.57 Punkte

📌 MIT Lifelong Kindergarten Scratch scratch-vm prior 0.2.0-prerelease.20200714185213 serialization/sb3.js deserialization


📈 28.57 Punkte

📌 jQuery bis 1.8.x jQuery(strInput) String Cross Site Scripting


📈 28.44 Punkte

📌 Medium CVE-2016-10707: Jquery Jquery


📈 28.44 Punkte

📌 Low CVE-2015-9251: Jquery Jquery


📈 28.44 Punkte

📌 Low CVE-2012-6708: Jquery Jquery


📈 28.44 Punkte

📌 jQuery up to 1.8.1 jQuery(strInput) String cross site scripting


📈 28.44 Punkte

📌 jQuery up to 1.11.3/2.2.4 on Node.js jQuery.globalEval Datatype cross site scripting


📈 28.44 Punkte

📌 jQuery bis 1.8.3 auf Node.js jQuery(strInput) Cross Site Scripting


📈 28.44 Punkte

📌 jQuery up to 1.8.3 on Node.js jQuery(strInput) cross site scripting


📈 28.44 Punkte

📌 Low CVE-2020-7656: Jquery Jquery


📈 28.44 Punkte

📌 Medium CVE-2020-28488: Jquery Jquery ui


📈 28.44 Punkte

📌 Low CVE-2022-2144: Jquery validation for contact form 7 project Jquery validation for contact form 7


📈 28.44 Punkte

📌 CVE-2021-4243 | claviska jquery-minicolors up to 2.3.5 jquery.minicolors.js cross site scripting


📈 28.44 Punkte

📌 jQuery bis 1.11.3/2.2.4 auf Node.js jQuery.globalEval Datatype Cross Site Scripting


📈 28.44 Punkte

📌 10 React Hooks Explained // Plus Build your own from Scratch


📈 26.68 Punkte

📌 Why Training Your Own Transformer Language Model from Scratch is (not) Stupid


📈 26.68 Punkte

📌 Learn to create your very own kernel from scratch for just a tenner! Ends midnight


📈 26.68 Punkte

📌 Creating your own ExpressJS from scratch (Part 1) - Basics, Methods, and Routing


📈 26.68 Punkte

📌 Creating your own ExpressJS from scratch (Part 2) - Middlewares and Controllers


📈 26.68 Punkte

📌 Build your own Transformer from scratch using Pytorch


📈 26.68 Punkte

📌 Build Your Own AI Avatar App From Scratch in Less Than 8 Hours


📈 26.68 Punkte

📌 Huawei releases it's own desktop PC with their own OS based on Linux and their own ARM CPU.


📈 26.67 Punkte

📌 Microsoft wants to let you dub videos using your own voice in your own language, new patent reveals


📈 24.79 Punkte

📌 Use Beat Saber's Level Editor to create your own tracks with your own music


📈 24.79 Punkte

📌 How you can create your own custom chatbot with your own custom data using Google Gemini API all for free


📈 24.79 Punkte

📌 How to make sure your company’s app is up to scratch


📈 24.65 Punkte

📌 How to make your IT security go beyond your network – and make people your perimeter


📈 24.24 Punkte

📌 Finally built my own Linux from Scratch!


📈 23.17 Punkte

📌 Finally built my own Linux from Scratch!


📈 23.17 Punkte

📌 Made my own Linux from Scratch distro at age 13


📈 23.17 Punkte

📌 Will your glasses fit inside or scratch the lenses of your Oculus Rift S?


📈 21.3 Punkte











matomo