πŸ“œ ⬆️ ⬇️

Implementation and alternative of basic jQuery functions in pure javascript

When I started to learn web programming, I met the best of all, in my opinion, frameworks - jQuery. In that distant time, it was impossible to imagine normal programming without it, since it could do in one line what JavaScript did for 95.

In today's time, javascript has changed a lot. It added a great functionality that reduces the amount of code at times and makes programming more convenient. But even with these updates, it cannot reproduce some, even the simplest, functions from jQuery, and when we decide to abandon this framework, it feels some difficulty because of this.

So, in this article I want to talk about the implementation of some functions from jQuery in pure JavaScript.

')
  1. $ (document) .ready (Function); or $ (Function);


    For those who don't know, this is the DOM tree readiness feature. Those. This function starts when the DOM page has been fully loaded.

    Starting with IE9 +, this function can be replaced with the DOMContentLoaded event of the hanged-on document .

    Example:
     document.addEventListener('DOMContentLoaded', function() { //   }, false); 

    If you need support starting with IE4 +, you can use the older method - using the readystatechange event hung on the document and checking the readyState .

    Example:
     document.onreadystatechange = function(){ if(document.readyState === 'complete'){ //   } }; 

    If we look into the jQuery source, the following function will be released:

    Example:
     var ready = (function() { var readyList, DOMContentLoaded, class2type = {}; class2type["[object Boolean]"] = "boolean"; class2type["[object Number]"] = "number"; class2type["[object String]"] = "string"; class2type["[object Function]"] = "function"; class2type["[object Array]"] = "array"; class2type["[object Date]"] = "date"; class2type["[object RegExp]"] = "regexp"; class2type["[object Object]"] = "object"; var ReadyObj = { //   DOM   ?   true,    . isReady: false, // ,    ,    . . #6781 readyWait: 1, //  ( )   holdReady: function(hold) { if (hold) { ReadyObj.readyWait++; } else { ReadyObj.ready(true); } }, // ,  DOM  ready: function(wait) { //    ,   DOMready/load     if ((wait === true && !--ReadyObj.readyWait) || (wait !== true && !ReadyObj.isReady)) { // ,   ,   ,  ,  IE  (ticket #5443). if (!document.body) { return setTimeout(ReadyObj.ready, 1); } //   DOM  ReadyObj.isReady = true; //    DOM Ready ,   ,  , if (wait !== true && --ReadyObj.readyWait > 0) { return; } //   ,  readyList.resolveWith(document, [ReadyObj]); //     //if ( ReadyObj.fn.trigger ) { // ReadyObj( document ).trigger( "ready" ).unbind( "ready" ); //} } }, bindReady: function() { if (readyList) { return; } readyList = ReadyObj._Deferred(); //  ,  $(document).ready()   //  ,   . if (document.readyState === "complete") { //    ,       return setTimeout(ReadyObj.ready, 1); } // Mozilla, Opera  webkit nightlies       if (document.addEventListener) { //   callback  document.addEventListener("DOMContentLoaded", DOMContentLoaded, false); //   window.onload,     window.addEventListener("load", ReadyObj.ready, false); //     IE } else if (document.attachEvent) { //    , // , ,     iframes document.attachEvent("onreadystatechange", DOMContentLoaded); //   window.onload,     window.attachEvent("onload", ReadyObj.ready); //  IE,   frame //  ,    var toplevel = false; try { toplevel = window.frameElement == null; } catch (e) {} if (document.documentElement.doScroll && toplevel) { doScrollCheck(); } } }, _Deferred: function() { var //  callback callbacks = [], // stored [ context , args ] fired, //   ,     firing, //  ,    cancelled, //  deferred = { // done( f1, f2, ...) done: function() { if (!cancelled) { var args = arguments, i, length, elem, type, _fired; if (fired) { _fired = fired; fired = 0; } for (i = 0, length = args.length; i < length; i++) { elem = args[i]; type = ReadyObj.type(elem); if (type === "array") { deferred.done.apply(deferred, elem); } else if (type === "function") { callbacks.push(elem); } } if (_fired) { deferred.resolveWith(_fired[0], _fired[1]); } } return this; }, //       resolveWith: function(context, args) { if (!cancelled && !fired && !firing) { // ,    (#8421) args = args || []; firing = 1; try { while (callbacks[0]) { callbacks.shift().apply(context, args); //shifts a callback, and applies it to document } } finally { fired = [context, args]; firing = 0; } } return this; }, //          resolve: function() { deferred.resolveWith(this, arguments); return this; }, //    ? isResolved: function() { return !!(firing || fired); }, //  cancel: function() { cancelled = 1; callbacks = []; return this; } }; return deferred; }, type: function(obj) { return obj == null ? String(obj) : class2type[Object.prototype.toString.call(obj)] || "object"; } } //   DOM  Internet Explorer function doScrollCheck() { if (ReadyObj.isReady) { return; } try { //   IE,      // http://javascript.nwbox.com/IEContentLoaded/ document.documentElement.doScroll("left"); } catch (e) { setTimeout(doScrollCheck, 1); return; } //     ReadyObj.ready(); } //    document ready if (document.addEventListener) { DOMContentLoaded = function() { document.removeEventListener("DOMContentLoaded", DOMContentLoaded, false); ReadyObj.ready(); }; } else if (document.attachEvent) { DOMContentLoaded = function() { // ,   ,   ,  ,  IE  (ticket #5443). if (document.readyState === "complete") { document.detachEvent("onreadystatechange", DOMContentLoaded); ReadyObj.ready(); } }; } function ready(fn) { //   ReadyObj.bindReady(); var type = ReadyObj.type(fn); //  callback' readyList.done(fn); // ReadyList   _Deferred() } return ready; })(); 

    The launch of the function happens this way:

     ready(function() { //   }); 

  2. $ .ajax (Object);


    For those who do not know, this function performs an asynchronous HTTP (Ajax) request.

    No matter how trite it is, the alternative to Jquery.ajax () is XMLHttpRequest

    A little bit about using:

    To begin with, we should create a cross-browser function to send, because In different browsers, the sending function may be different. It is created this way:

     function getXmlHttp(){ var xmlhttp; try { xmlhttp = new ActiveXObject('Msxml2.XMLHTTP'); } catch (e) { try { xmlhttp = new ActiveXObject('Microsoft.XMLHTTP'); } catch (E) { xmlhttp = false; } } if (!xmlhttp && typeof XMLHttpRequest !== 'undefined') { xmlhttp = new XMLHttpRequest(); } return xmlhttp; } 

    And here is an example of a standard POST error-handling request:

     var xmlhttp = getXmlHttp(); //    xmlhttp.open('POST', '/someurl', true); //  POST    "/someurl" //       xmlhttp.onreadystatechange = function(){ if (xmlhttp.readyState !== 4) return; //    ,     //   : //  0 β€”  XMLHttpRequest  ,   open()   . //  1 β€”    open().     setRequestHeader()      (request headers),  ,    ,     send() . //  2 β€”    send()     (response headers) . //  3 β€”   .  responseType       "text", responseText      . //  4 β€”    .     ,      ,   ,   . clearTimeout(timeout); //  Timeout,    if (xmlhttp.status == 200) { //         ,    console.log(xmlhttp.responseText); } else { //     ,      handleError(xmlhttp.statusText); } } //  ,     xmlhttp.send("a=5&b=4"); //    10 .    , ,      ,   var timeout = setTimeout( function(){ xmlhttp.abort(); handleError('Time over') }, 10000); //     function handleError(message) { //           console.log(': ' + message); } 

    JQuery AJAX function is made using the same technology.
  3. The global function $ (...);


    If anyone does not know, this function creates a global jQuery object.

    Here I will not describe the full functionality of this function, since it will take at least a week for me, but I will just write how this thing is created following the example of JQuery.

    To begin with, we will create an ordinary function, for example, Library with arguments (selector and context).

     var Library = function (selector, context) {}; 

    Further we write the general function. In jQuery, the values ​​that fall into a function are iterated using conditions and the result is displayed.

     var init = function (selector, context) { //     , //      var array = []; /**    , *     *  HTML     */ if (typeof selector === 'string' ) { /**    HTML  *      . *    JQuery  *   : * /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/ */ if (/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/.exec(selector)) { //     var DOM = new DOMParser().parseFromString(selector, 'text/html'); var DOMList = DOM.body.childNodes; //      context      if (!context || {}.toString.call(context) !== '[object Object]') { context = null; }; //       for (var i = 0; i < DOMList.length; i++) { if (context) { for (var attr in context) { DOMList[i].setAttribute(attr, context + ''); }; }; array[array.length] = DOMList[i]; }; return array; } else { //    //    // context , //     //  var DOMList = {}.toString.call(context) === '[object HTMLElement]' ? context.querySelectorAll(selector) : document.querySelectorAll(selector); //       //   for (var i = 0; i < DOMList.length; i++) { array[array.length] = DOMList[i]; }; return array; }; //   ,      } else if ({}.toString.call(selector) === '[object Array]') { //     for (var i = 0; i < selector.length; i++) { array[array.length] = selector[i]; }; return array; //   ,       } else if ({}.toString.call(selector) === '[object Object]' || {}.toString.call(selector) === '[object HTMLElement]') { //       array[0] = selector; return array; //  ,     ? } else if ({}.toString.call(selector) === '[object HTMLCollection]' || {}.toString.call(selector) === '[object NodeList]') { //     for (var i = 0; i < selector.length; i++) { array[array.length] = selector[i]; }; return array; //    ,     } else { return array; } }; 

    Now we can add the launch of this function through the main

     var Library = function (selector, context) { //      var array = new init(selector, context); /**    . *   proto  *   , *     *   *  */ var object = { __proto__: Library.prototype }; //     //       //  length,    //  ,   //   for (var i = 0; i < array.length; i++) { object[i] = array[i]; }; object.length = array.length; return object; }; 

    That's done. Now we can get an array of elements through the Library(...); function Library(...); and create additional functionality through such a construct Library.prototype.myFunction = function () {...};

For now. In time, I will publish articles about jQuery functions more specifically.

Source: https://habr.com/ru/post/335926/


All Articles