Giter Site home page Giter Site logo

you-dont-need-jquery's Introduction

You (Might) Don't Need jQuery

Frontend environments evolve rapidly nowadays and modern browsers have already implemented a great deal of DOM/BOM APIs which are good enough for production use. We don't have to learn jQuery from scratch for DOM manipulation or event handling. In the meantime, thanks to the spread of frontend libraries such as React, Angular and Vue, manipulating the DOM directly becomes anti-pattern, so that jQuery usage has never been less important. This project summarizes most of the alternatives in native Javascript implementation to jQuery methods, with IE 10+ support.

ℹ️ Notice:

  1. jQuery is still a great library and has many valid use cases. Don’t migrate away if you don’t want to!
  2. The alternatives are not completely equivalent in all scenarios, and it is recommended that you test it before using it.

Table of Contents

  1. Translations
  2. Query Selector
  3. CSS & Style
  4. DOM Manipulation
  5. Ajax
  6. Events
  7. Utilities
  8. Promises
  9. Animation
  10. Alternatives
  11. Browser Support

Translations

Query Selector

In place of common selectors like class, id or attribute we can use document.querySelector or document.querySelectorAll for substitution. The differences lie in:

  • document.querySelector returns the first matched element
  • document.querySelectorAll returns all matched elements as NodeList. It can be converted to Array using Array.prototype.slice.call(document.querySelectorAll(selector)); or any of the methods outlined in makeArray
  • If there are no elements matched, jQuery and document.querySelectorAll will return [], whereas document.querySelector will return null.

Notice: document.querySelector and document.querySelectorAll are quite SLOW, thus try to use document.getElementById, document.getElementsByClassName or document.getElementsByTagName if you want to get a performance bonus.

  • 1.0 Query by selector

    // jQuery
    $('selector');
    
    // Native
    document.querySelectorAll('selector');
  • 1.1 Query by class

    // jQuery
    $('.class');
    
    // Native
    document.querySelectorAll('.class');
    
    // or
    document.getElementsByClassName('class');
  • 1.2 Query by id

    // jQuery
    $('#id');
    
    // Native
    document.querySelector('#id');
    
    // or
    document.getElementById('id');
    
    // or
    window['id']
  • 1.3 Query by attribute

    // jQuery
    $('a[target=_blank]');
    
    // Native
    document.querySelectorAll('a[target=_blank]');
  • 1.4 Query in descendants

    // jQuery
    $el.find('li');
    
    // Native
    el.querySelectorAll('li');
  • 1.5 Sibling/Previous/Next Elements

    • All siblings

      // jQuery
      $el.siblings();
      
      // Native - latest, Edge13+
      [...el.parentNode.children].filter((child) =>
        child !== el
      );
      // Native (alternative) - latest, Edge13+
      Array.from(el.parentNode.children).filter((child) =>
        child !== el
      );
      // Native - IE10+
      Array.prototype.filter.call(el.parentNode.children, (child) =>
        child !== el
      );
    • Previous sibling

      // jQuery
      $el.prev();
      
      // Native
      el.previousElementSibling;
    • Next sibling

      // jQuery
      $el.next();
      
      // Native
      el.nextElementSibling;
    • All previous siblings

      // jQuery (optional filter selector)
      $el.prevAll($filter);
      
      // Native (optional filter function)
      function getPreviousSiblings(elem, filter) {
        var sibs = [];
        while (elem = elem.previousSibling) {
            if (elem.nodeType === 3) continue; // ignore text nodes
            if (!filter || filter(elem)) sibs.push(elem);
        }
        return sibs;
      }
    • All next siblings

      // jQuery (optional selector filter)
      $el.nextAll($filter);
      
      // Native (optional filter function)
      function getNextSiblings(elem, filter) {
              var sibs = [];
              var nextElem = elem.parentNode.firstChild;
              do {
                  if (nextElem.nodeType === 3) continue; // ignore text nodes
                  if (nextElem === elem) continue; // ignore elem of target
                  if (nextElem === elem.nextElementSibling) {
                      if (!filter || filter(elem)) {
                          sibs.push(nextElem);
                          elem = nextElem;
                      }
                  }
              } while(nextElem = nextElem.nextSibling)
              return sibs;
          }

An example of filter function:

function exampleFilter(elem) {
  switch (elem.nodeName.toUpperCase()) {
    case 'DIV':
      return true;
    case 'SPAN':
      return true;
    default:
      return false;
  }
}
  • 1.6 Closest

    Return the first matched element by provided selector, traversing from current element up through its ancestors in the DOM tree.

    // jQuery
    $el.closest(selector);
    
    // Native - Only latest, NO IE
    el.closest(selector);
    
    // Native - IE10+
    function closest(el, selector) {
      const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
    
      while (el) {
        if (matchesSelector.call(el, selector)) {
          return el;
        } else {
          el = el.parentElement;
        }
      }
      return null;
    }
  • 1.7 Parents Until

    Get the ancestors of each element in the current set of matched elements, up to but not including the element matched by the selector, DOM node, or jQuery object.

    // jQuery
    $el.parentsUntil(selector, filter);
    
    // Native
    function parentsUntil(el, selector, filter) {
      const result = [];
      const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;
    
      // match start from parent
      el = el.parentElement;
      while (el && !matchesSelector.call(el, selector)) {
        if (!filter) {
          result.push(el);
        } else {
          if (matchesSelector.call(el, filter)) {
            result.push(el);
          }
        }
        el = el.parentElement;
      }
      return result;
    }
  • 1.8 Form

    • Input/Textarea

      // jQuery
      $('#my-input').val();
      
      // Native
      document.querySelector('#my-input').value;
    • Get index of e.currentTarget between .radio

      // jQuery
      $('.radio').index(e.currentTarget);
      
      // Native
      Array.from(document.querySelectorAll('.radio')).indexOf(e.currentTarget);
      or
      Array.prototype.indexOf.call(document.querySelectorAll('.radio'), e.currentTarget);
  • 1.9 Iframe Contents

    $('iframe').contents() returns contentDocument for this specific iframe

    • Iframe contents

      // jQuery
      $iframe.contents();
      
      // Native
      iframe.contentDocument;
    • Iframe Query

      // jQuery
      $iframe.contents().find('.css');
      
      // Native
      iframe.contentDocument.querySelectorAll('.css');
  • 1.10 Get body

    // jQuery
    $('body');
    
    // Native
    document.body;
  • 1.11 Attribute getter and setter

    • Get an attribute

      // jQuery
      $el.attr('foo');
      
      // Native
      el.getAttribute('foo');
    • Set an attribute

      // jQuery
      $el.attr('foo', 'bar');
      
      // Native
      el.setAttribute('foo', 'bar');
    • Get a data- attribute

      // jQuery
      $el.data('foo');
      
      // Native (use `getAttribute`)
      el.getAttribute('data-foo');
      
      // Native (use `dataset` if only need to support IE 11+)
      el.dataset['foo'];
  • 1.12 Selector containing string (case-sensitive)

    // jQuery
    $("selector:contains('text')");
    
    // Native
    function contains(selector, text) {
      var elements = document.querySelectorAll(selector);
      return Array.from(elements).filter(function(element) {
        return RegExp(text).test(element.textContent);
      });
    }

⬆ back to top

CSS & Style

  • 2.1 CSS

    • Get style

      // jQuery
      $el.css('color');
      
      // Native
      // NOTE: Known bug, will return 'auto' if style value is 'auto'
      const win = el.ownerDocument.defaultView;
      
      // null means not to return pseudo styles
      win.getComputedStyle(el, null).color;
    • Set style

      // jQuery
      $el.css({ color: '#f01' });
      
      // Native
      el.style.color = '#f01';
    • Get/Set Styles

      // jQuery
      $el.css({ color: '#f01', 'border-color': '#f02' })
      
      // Native
      Object.assign(el.style, { color: '#f01', borderColor: '#f02' }) 
    • Add class

      // jQuery
      $el.addClass(className);
      
      // Native
      el.classList.add(className);
    • Remove class

      // jQuery
      $el.removeClass(className);
      
      // Native
      el.classList.remove(className);
    • has class

      // jQuery
      $el.hasClass(className);
      
      // Native
      el.classList.contains(className);
    • Toggle class

      // jQuery
      $el.toggleClass(className);
      
      // Native
      el.classList.toggle(className);
  • 2.2 Width & Height

    Width and Height are theoretically identical, take Height as example:

    • Window height

      // window height
      $(window).height();
      
      // without scrollbar, behaves like jQuery
      window.document.documentElement.clientHeight;
      
      // with scrollbar
      window.innerHeight;
    • Document height

      // jQuery
      $(document).height();
      
      // Native
      const body = document.body;
      const html = document.documentElement;
      const height = Math.max(
        body.offsetHeight,
        body.scrollHeight,
        html.clientHeight,
        html.offsetHeight,
        html.scrollHeight
      );
    • Element height

      // jQuery
      $el.height();
      
      // Native
      function getHeight(el) {
        const styles = window.getComputedStyle(el);
        const height = el.offsetHeight;
        const borderTopWidth = parseFloat(styles.borderTopWidth);
        const borderBottomWidth = parseFloat(styles.borderBottomWidth);
        const paddingTop = parseFloat(styles.paddingTop);
        const paddingBottom = parseFloat(styles.paddingBottom);
        return height - borderBottomWidth - borderTopWidth - paddingTop - paddingBottom;
      }
      
      // accurate to integer(when `border-box`, it's `height - border`; when `content-box`, it's `height + padding`)
      el.clientHeight;
      
      // accurate to decimal(when `border-box`, it's `height`; when `content-box`, it's `height + padding + border`)
      el.getBoundingClientRect().height;
  • 2.3 Position & Offset

    • Position

      Get the current coordinates of the element relative to the offset parent.

      // jQuery
      $el.position();
      
      // Native
      { left: el.offsetLeft, top: el.offsetTop }
    • Offset

      Get the current coordinates of the element relative to the document.

      // jQuery
      $el.offset();
      
      // Native
      function getOffset (el) {
        const box = el.getBoundingClientRect();
      
        return {
          top: box.top + window.pageYOffset - document.documentElement.clientTop,
          left: box.left + window.pageXOffset - document.documentElement.clientLeft
        };
      }
  • 2.4 Scroll Top

    Get the current vertical position of the scroll bar for the element.

    // jQuery
    $(window).scrollTop();
    
    // Native
    (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;

⬆ back to top

DOM Manipulation

  • 3.1 Remove

    Remove the element from the DOM.

    // jQuery
    $el.remove();
    
    // Native
    el.parentNode.removeChild(el);
  • 3.2 Text

    • Get text

      Get the combined text contents of the element including their descendants,

      // jQuery
      $el.text();
      
      // Native
      el.textContent;
    • Set text

      Set the content of the element to the specified text.

      // jQuery
      $el.text(string);
      
      // Native
      el.textContent = string;
  • 3.3 HTML

    • Get HTML

      // jQuery
      $el.html();
      
      // Native
      el.innerHTML;
    • Set HTML

      // jQuery
      $el.html(htmlString);
      
      // Native
      el.innerHTML = htmlString;
  • 3.4 Append

    Append child element after the last child of parent element

    // jQuery: unified syntax for DOMString and Node objects
    $parent.append(newEl | '<div id="container">Hello World</div>');
    
    // Native: different syntax
    parent.insertAdjacentHTML('beforeend', '<div id="container">Hello World</div>');
    parent.appendChild(newEl);
    
    // Native (ES6-way): unified syntax
    parent.append(newEl | '<div id="container">Hello World</div>');
  • 3.5 Prepend

    // jQuery: unified syntax for DOMString and Node objects
    $parent.prepend(newEl | '<div id="container">Hello World</div>');
    
    // Native: different syntax
    parent.insertAdjacentHTML('afterbegin', '<div id="container">Hello World</div>');
    parent.insertBefore(newEl, parent.firstChild);
    
    // Native (ES6-way): unified syntax
    parent.prepend(newEl | '<div id="container">Hello World</div>');
  • 3.6 insertBefore

    Insert a new node before the selected elements

    // jQuery
    $newEl.insertBefore(selector);
    
    // Native (HTML string)
    el.insertAdjacentHTML('beforebegin ', '<div id="container">Hello World</div>');
    
    // Native (Element)
    const el = document.querySelector(selector);
    if (el.parentNode) {
      el.parentNode.insertBefore(newEl, el);
    }
  • 3.7 insertAfter

    Insert a new node after the selected elements

    // jQuery
    $newEl.insertAfter(selector);
    
    // Native (HTML string)
    el.insertAdjacentHTML('afterend', '<div id="container">Hello World</div>');
    
    // Native (Element)
    const el = document.querySelector(selector);
    if (el.parentNode) {
      el.parentNode.insertBefore(newEl, el.nextSibling);
    }
  • 3.8 is

    Return true if it matches the query selector

    // jQuery - Notice `is` also works with a function, an existing jQuery object or a DOM element, which are not of concern here
    $el.is(selector);
    
    // Native
    el.matches(selector);
  • 3.9 clone

    Create a deep copy of an element: it copies the matched element as well as all of its descendant elements and text nodes.

    // jQuery. Sets parameter as `true` to indicate that event handlers should be copied along with the element.
    $el.clone();
    
    // Native
    el.cloneNode();
  • 3.10 empty

    Remove all child nodes

    // jQuery
    $el.empty();
    
    // Native
    el.innerHTML = null;
  • 3.11 wrap

    Wrap an HTML structure around each element

    // jQuery
    $('.inner').wrap('<div class="wrapper"></div>');
    
    // Native
    Array.from(document.querySelectorAll('.inner')).forEach((el) => {
      const wrapper = document.createElement('div');
      wrapper.className = 'wrapper';
      el.parentNode.insertBefore(wrapper, el);
      wrapper.appendChild(el);
    });
  • 3.12 unwrap

    Remove the parents of the set of matched elements from the DOM

    // jQuery
    $('.inner').unwrap();
    
    // Native
    Array.from(document.querySelectorAll('.inner')).forEach((el) => {
      let elParentNode = el.parentNode;
    
      if(elParentNode !== document.body) {
          elParentNode.parentNode.insertBefore(el, elParentNode);
          elParentNode.parentNode.removeChild(elParentNode);
      }
    });
  • 3.13 replaceWith

    Replace each element in the set of matched elements with the provided new content

    // jQuery
    $('.inner').replaceWith('<div class="outer"></div>');
    
    // Native (alternative) - latest, Edge17+
    Array.from(document.querySelectorAll('.inner')).forEach((el) => {
      const outer = document.createElement('div');
      outer.className = 'outer';
      el.replaceWith(outer);
    });
    
    // Native
    Array.from(document.querySelectorAll('.inner')).forEach((el) => {
      const outer = document.createElement('div');
      outer.className = 'outer';
      el.parentNode.replaceChild(outer, el);
    });
  • 3.14 simple parse

    Parse a string into HTML/SVG/XML

    // jQuery
    $(`<ol>
      <li>a</li>
      <li>b</li>
    </ol>
    <ol>
      <li>c</li>
      <li>d</li>
    </ol>`);
    
    // Native
    range = document.createRange();
    parse = range.createContextualFragment.bind(range);
    
    parse(`<ol>
      <li>a</li>
      <li>b</li>
    </ol>
    <ol>
      <li>c</li>
      <li>d</li>
    </ol>`);

⬆ back to top

Ajax

Fetch API is the new standard to replace XMLHttpRequest to do ajax. It works on Chrome and Firefox, you can use polyfills to make it work on legacy browsers.

Try github/fetch on IE9+ or fetch-ie8 on IE8+, fetch-jsonp to make JSONP requests.

  • 4.1 Load data from the server and place the returned HTML into the matched element.

    // jQuery
    $(selector).load(url, completeCallback)
    
    // Native
    fetch(url).then(data => data.text()).then(data => {
      document.querySelector(selector).innerHTML = data
    }).then(completeCallback)

⬆ back to top

Events

For a complete replacement with namespace and delegation, refer to https://github.com/oneuijs/oui-dom-events

  • 5.0 Document ready by DOMContentLoaded

      // jQuery
      $(document).ready(eventHandler);
    
      // Native
      // Check if the DOMContentLoaded has already been completed
      if (document.readyState !== 'loading') {
        eventHandler();
      } else {
        document.addEventListener('DOMContentLoaded', eventHandler);
      }
    
      // Native 
      // Example 2 - Ternary Operator - Async
      // Check if the DOMContentLoaded has already been completed
      (async function() {
        (document.readyState !== 'loading') ?
          eventHandler() : document.addEventListener('DOMContentLoaded',
            function() {
              eventHandler(); // EventHandler
            });
      })();
    
      // Native
      // Example 3 - Ternary Operator - Non Async
      // Check if the DOMContentLoaded has already been completed
      (function() {
        (document.readyState !== 'loading') ?
          eventHandler() : document.addEventListener('DOMContentLoaded',
            function() {
              eventHandler(); // EventHandler
            });
      })();
  • 5.1 Bind an event with on

    // jQuery
    $el.on(eventName, eventHandler);
    
    // Native
    el.addEventListener(eventName, eventHandler);
  • 5.2 Unbind an event with off

    // jQuery
    $el.off(eventName, eventHandler);
    
    // Native
    el.removeEventListener(eventName, eventHandler);
  • 5.3 Trigger

    // jQuery
    $(el).trigger('custom-event', {key1: 'data'});
    
    // Native
    if (window.CustomEvent) {
      const event = new CustomEvent('custom-event', {detail: {key1: 'data'}});
    } else {
      const event = document.createEvent('CustomEvent');
      event.initCustomEvent('custom-event', true, true, {key1: 'data'});
    }
    
    el.dispatchEvent(event);

⬆ back to top

Utilities

Most of jQuery utilities are also found in the native API. Other advanced functions could be chosen from better utilities libraries, focusing on consistency and performance. Lodash is a recommended replacement.

  • 6.1 Basic utilities

    • isArray

    Determine whether the argument is an array.

    // jQuery
    $.isArray(array);
    
    // Native
    Array.isArray(array);
    • isWindow

    Determine whether the argument is a window.

    // jQuery
    $.isWindow(obj);
    
    // Native
    function isWindow(obj) {
      return obj !== null && obj !== undefined && obj === obj.window;
    }
    • inArray

    Search for a specified value within an array and return its index (or -1 if not found).

    // jQuery
    $.inArray(item, array);
    
    // Native
    array.indexOf(item) > -1;
    
    // ES6-way
    array.includes(item);
    • isNumeric

    Determine if the argument passed is numerical. Use typeof to decide the type or the type example for better accuracy.

    // jQuery
    $.isNumeric(item);
    
    // Native
    function isNumeric(n) {
      return !isNaN(parseFloat(n)) && isFinite(n);
    }
    • isFunction

    Determine if the argument passed is a JavaScript function object.

    // jQuery
    $.isFunction(item);
    
    // Native
    function isFunction(item) {
      if (typeof item === 'function') {
        return true;
      }
      var type = Object.prototype.toString.call(item);
      return type === '[object Function]' || type === '[object GeneratorFunction]';
    }
    • isEmptyObject

    Check to see if an object is empty (contains no enumerable properties).

    // jQuery
    $.isEmptyObject(obj);
    
    // Native
    function isEmptyObject(obj) {
      return Object.keys(obj).length === 0;
    }
    • isPlainObject

    Check to see if an object is a plain object (created using “{}” or “new Object”).

    // jQuery
    $.isPlainObject(obj);
    
    // Native
    function isPlainObject(obj) {
      if (typeof (obj) !== 'object' || obj.nodeType || obj !== null && obj !== undefined && obj === obj.window) {
        return false;
      }
    
      if (obj.constructor &&
          !Object.prototype.hasOwnProperty.call(obj.constructor.prototype, 'isPrototypeOf')) {
        return false;
      }
    
      return true;
    }
    • extend

    Merge the contents of two or more objects together into a new object, without modifying either argument. object.assign is part of ES6 API, and you could also use a polyfill.

    // jQuery
    $.extend({}, object1, object2);
    
    // Native
    Object.assign({}, object1, object2);
    • trim

    Remove the white-space from the beginning and end of a string.

    // jQuery
    $.trim(string);
    
    // Native
    string.trim();
    • map

    Translate all items in an array or object to new array of items.

    // jQuery
    $.map(array, (value, index) => {
    });
    
    // Native
    array.map((value, index) => {
    });
    • each

    A generic iterator function, which can be used to seamlessly iterate over both objects and arrays.

    // jQuery
    $.each(array, (index, value) => {
    });
    
    // Native
    array.forEach((value, index) => {
    });
    • grep

    Finds the elements of an array which satisfy a filter function.

    // jQuery
    $.grep(array, (value, index) => {
    });
    
    // Native
    array.filter((value, index) => {
    });
    • type

    Determine the internal JavaScript [Class] of an object.

    // jQuery
    $.type(obj);
    
    // Native
    function type(item) {
      const reTypeOf = /(?:^\[object\s(.*?)\]$)/;
      return Object.prototype.toString.call(item)
        .replace(reTypeOf, '$1')
        .toLowerCase();
    }
    • merge

    Merge the contents of two arrays together into the first array.

    // jQuery, doesn't remove duplicate items
    $.merge(array1, array2);
    
    // Native, doesn't remove duplicate items
    function merge(...args) {
      return [].concat(...args)
    }
    
    // ES6-way, doesn't remove duplicate items
    array1 = [...array1, ...array2]
    
    // Set version, does remove duplicate items
    function merge(...args) {
      return Array.from(new Set([].concat(...args)))
    }
    • now

    Return a number representing the current time.

    // jQuery
    $.now();
    
    // Native
    Date.now();
    • proxy

    Takes a function and returns a new one that will always have a particular context.

    // jQuery
    $.proxy(fn, context);
    
    // Native
    fn.bind(context);

    + makeArray

    Convert an array-like object into a true JavaScript array.

    // jQuery
    $.makeArray(arrayLike);
    
    // Native
    Array.prototype.slice.call(arrayLike);
    
    // ES6-way: Array.from() method
    Array.from(arrayLike);
    
    // ES6-way: spread operator
    [...arrayLike];
  • 6.2 Contains

    Check to see if a DOM element is a descendant of another DOM element.

    // jQuery
    $.contains(el, child);
    
    // Native
    el !== child && el.contains(child);
  • 6.3 Globaleval

    Execute some JavaScript code globally.

    // jQuery
    $.globaleval(code);
    
    // Native
    function Globaleval(code) {
      const script = document.createElement('script');
      script.text = code;
    
      document.head.appendChild(script).parentNode.removeChild(script);
    }
    
    // Use eval, but context of eval is current, context of $.Globaleval is global.
    eval(code);
  • 6.4 parse

    • parseHTML

    Parses a string into an array of DOM nodes.

    // jQuery
    $.parseHTML(htmlString);
    
    // Native
    function parseHTML(string) {
      const context = document.implementation.createHTMLDocument();
    
      // Set the base href for the created document so any parsed elements with URLs
      // are based on the document's URL
      const base = context.createElement('base');
      base.href = document.location.href;
      context.head.appendChild(base);
    
      context.body.innerHTML = string;
      return context.body.children;
    }
  • 6.5 exists

  • exists

    Check if an element exists in the DOM

    // jQuery
    if ($('selector').length) {
       // exists
    }
    
    // Native
    var element =  document.getElementById('elementId');
    if (typeof(element) != 'undefined' && element != null)
    {
       // exists
    }

⬆ back to top

Promises

A promise represents the eventual result of an asynchronous operation. jQuery has its own way to handle promises. Native JavaScript implements a thin and minimal API to handle promises according to the Promises/A+ specification.

  • 7.1 done, fail, always

    done is called when promise is resolved, fail is called when promise is rejected, always is called when promise is either resolved or rejected.

    // jQuery
    $promise.done(doneCallback).fail(failCallback).always(alwaysCallback)
    
    // Native
    promise.then(doneCallback, failCallback).then(alwaysCallback, alwaysCallback)
  • 7.2 when

    when is used to handle multiple promises. It will resolve when all promises are resolved, and reject if either one is rejected.

    // jQuery
    $.when($promise1, $promise2).done((promise1Result, promise2Result) => {
    });
    
    // Native
    Promise.all([$promise1, $promise2]).then([promise1Result, promise2Result] => {});
  • 7.3 Deferred

    Deferred is a way to create promises.

    // jQuery
    function asyncFunc() {
      const defer = new $.Deferred();
      setTimeout(() => {
        if(true) {
          defer.resolve('some_value_computed_asynchronously');
        } else {
          defer.reject('failed');
        }
      }, 1000);
    
      return defer.promise();
    }
    
    // Native
    function asyncFunc() {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          if (true) {
            resolve('some_value_computed_asynchronously');
          } else {
            reject('failed');
          }
        }, 1000);
      });
    }
    
    // Deferred way
    function defer() {
      const deferred = {};
      const promise = new Promise((resolve, reject) => {
        deferred.resolve = resolve;
        deferred.reject = reject;
      });
    
      deferred.promise = () => {
        return promise;
      };
    
      return deferred;
    }
    
    function asyncFunc() {
      const defer = defer();
      setTimeout(() => {
        if(true) {
          defer.resolve('some_value_computed_asynchronously');
        } else {
          defer.reject('failed');
        }
      }, 1000);
    
      return defer.promise();
    }

⬆ back to top

Animation

  • 8.1 Show & Hide

    // jQuery
    $el.show();
    $el.hide();
    
    // Native
    // More detail about show method, please refer to https://github.com/oneuijs/oui-dom-utils/blob/master/src/index.js#L363
    el.style.display = ''|'inline'|'inline-block'|'inline-table'|'block';
    el.style.display = 'none';
  • 8.2 Toggle

    Display or hide the element.

    // jQuery
    $el.toggle();
    
    // Native
    if (el.ownerDocument.defaultView.getComputedStyle(el, null).display === 'none') {
      el.style.display = ''|'inline'|'inline-block'|'inline-table'|'block';
    } else {
      el.style.display = 'none';
    }
  • 8.3 FadeIn & FadeOut

    // jQuery
    $el.fadeIn(3000);
    $el.fadeOut(3000);
    
    // Native fadeOut
    function fadeOut(el, ms) {
      if (ms) {
        el.style.transition = `opacity ${ms} ms`;
        el.addEventListener(
          'transitionend',
          function(event) {
            el.style.display = 'none';
          },
          false
        );
      }
      el.style.opacity = '0';
    }
    
    // Native fadeIn
    function fadeIn(elem, ms) {
      elem.style.opacity = 0;
    
      if (ms) {
        let opacity = 0;
        const timer = setInterval(function() {
          opacity += 50 / ms;
          if (opacity >= 1) {
            clearInterval(timer);
            opacity = 1;
          }
          elem.style.opacity = opacity;
        }, 50);
      } else {
        elem.style.opacity = 1;
      }
    }
  • 8.4 FadeTo

    Adjust the opacity of the element.

    // jQuery
    $el.fadeTo('slow',0.15);
    // Native
    el.style.transition = 'opacity 3s'; // assume 'slow' equals 3 seconds
    el.style.opacity = '0.15';
  • 8.5 FadeToggle

    Display or hide the element by animating their opacity.

    // jQuery
    $el.fadeToggle();
    
    // Native
    el.style.transition = 'opacity 3s';
    const { opacity } = el.ownerDocument.defaultView.getComputedStyle(el, null);
    if (opacity === '1') {
      el.style.opacity = '0';
    } else {
      el.style.opacity = '1';
    }
  • 8.6 SlideUp & SlideDown

    // jQuery
    $el.slideUp();
    $el.slideDown();
    
    // Native
    const originHeight = '100px';
    el.style.transition = 'height 3s';
    // slideUp
    el.style.height = '0px';
    // slideDown
    el.style.height = originHeight;
  • 8.7 SlideToggle

    Display or hide the element with a sliding motion.

    // jQuery
    $el.slideToggle();
    
    // Native
    const originHeight = '100px';
    el.style.transition = 'height 3s';
    const { height } = el.ownerDocument.defaultView.getComputedStyle(el, null);
    if (parseInt(height, 10) === 0) {
      el.style.height = originHeight;
    } else {
     el.style.height = '0px';
    }
  • 8.8 Animate

    Perform a custom animation of a set of CSS properties.

    // jQuery
    $el.animate({ params }, speed);
    
    // Native
    el.style.transition = 'all ' + speed;
    Object.keys(params).forEach((key) => {
      el.style[key] = params[key];
    });

Alternatives

Browser Support

Chrome Firefox IE Opera Safari
Latest ✔ Latest ✔ 10+ ✔ Latest ✔ 6.1+ ✔

License

MIT

you-dont-need-jquery's People

Contributors

andersonaguiar avatar angt avatar antonk52 avatar arcthur avatar camsong avatar carlomartini avatar chocanto avatar cs09g avatar gaulatti avatar gladkih avatar hhy5277 avatar infacq avatar item4 avatar jasonslyvia avatar jsgv avatar kidonng avatar kucherenkovova avatar lemondkel avatar moshihuang avatar mrcrjs avatar naprirfan avatar nguyenvanduocit avatar raymondpittman avatar riseledger avatar rodrigoalviani avatar softwarespot avatar tatesuke avatar vovanr avatar welksonramos avatar woneob avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

you-dont-need-jquery's Issues

Ajax?

Why is the document referring to using a 3rd party library instead of using native javascript?

COC?

Hi,

I'm just wondering what your code of conduct is for this project?

Thanks,
Alison

npm-dom

You can mention the npm-dom organization as an alternative to jQuery. People can find individual modules with good testing and documentation coverage there.

Seriously?

Guys, your comprehensive list of equivalent codes in native JS (and I believe it's the best equivalent that possible for native JS) for the most useful functions of jQuery--actually it's the best demonstration, why I shouldn't move from jQuery. Many of native examples are much longer, some of them determinately brain-blowing ($el.height() equivalent makes my day!), and absolutely all of them are less laconic and readable.

Why on Earth should I write el.classList.add(className); if I could do simply $el.addClass(className);? Does anybody here read about Law of Demeter?

jQuery provides the finest Facade for all this native stuff. It will be great if in some future standard of ES will be included all jQuery functions with efficient native implementation in browsers. Till then I will use jQuery, because I consider code elegance and maintainability is the first priority.

If I found in my application a crucial performance issue with some jQuery function I can use instead of it an equivalent native code from your list (and great thanks for you for this!) and hide its ugliness under some jQuery-like wrapper function.

I hope that I do not offend anybody and not overreacted, just proportional for your overconfident title.

Complete the Utilities for jQuery

Some utilities api will be complete for conversion.

  • Type related functions: type, inArray, isEmptyObject, isNumbic, isPlanObject, isWindow, isXMLDoc
  • FP functions: grep, each, map, merge, unique
  • Date function: now
  • Parse structures functions: parseHTML, parseJSON, parseXML
  • Others: globalEval, makeArray, proxy, support

Browser Support in Mobiles?

Basically this very nice list covers all modern desktop browsers: .i.e. IE10+!
What about Mobile Browser. Any formal list of "supported browser"?

CSS && Style part has a error

// Native
function getHeight(el) {
  const styles = this.getComputedStyles(el);
  const height = el.offsetHeight;
  const borderTopWidth = parseFloat(styles.borderTopWidth);
  const borderBottomWidth = parseFloat(styles.borderBottomWidth);
  const paddingTop = parseFloat(styles.paddingTop);
  const paddingBottom = parseFloat(styles.paddingBottom);
  return height - borderBottomWidth - borderTopWidth - paddingTop - paddingBottom;
}

getComputedStyles probably is getComputedStyle

Missing closest for IE9+

The alternatives provided for closest are quite limited to new Browsers.

$(element).closest('.selector')

I propose to add something around these lines to support IE 9 +

var demo = closest(document.querySelector('#test'), '.parent');

console.log(demo)

//inspired from https://stackoverflow.com/a/22101242/1081396
function closest(el, selector) {
    return el && el.nodeType ===1 && (
        el.matches(selector) ? el : closest(el.parentNode, selector)
    );
}

Demo here: https://jsfiddle.net/t8pjdt5q/13/

Put translation links on the top of the .md

Hey !

Now that this documentation is big (and well written), I think it would be a good idea to put translation links on the top of each readme instead of at the end.

It is easy for us to click on the readme file corresponding to the selected language in the respository files viewer, but for someone not familiar with it...

8.3 FadeIn and FadeOut JS equivalents will not work as intended

// jQuery
$el.fadeIn(3000);
$el.fadeOut(3000);

// Native
el.style.transition = 'opacity 3s';
// fadeIn
el.style.opacity = '1';
el.style.display = ''|'inline'|'inline-block'|'inline-table'|'block';
// fadeOut
el.style.opacity = '0';
el.style.display = 'none';

The JS equivalents will not actually work as intended because the el.style.display line will execute right after the el.style.opacity line without any delay. (as seen here: https://codepen.io/anon/pen/BYEpJV).

The correct way to do this is by wrapping the el.style.display around a setTimeout() function:

// fadeOut
el.style.opacity = 0;
setTimeout(function() {
  el.style.display = 'none';
}, 3000);

a mistake in 1.8 Form

1.8 Form -> Get index of e.currentTarget between .radio

// jQuery
$(e.currentTarget).index('.radio');

// Native
[].indexOf.call(document.querySelectorAll('.radio'), e.currentTarget);

I think jQuery code is :

$('.radio').index(e.currentTarget);

Keep translations list synchronized

I'm not really sure if more translations are coming, but it would be great to have a way to keep all translations list synchronized.

Maybe a test with travis should be possible.

Missing .index() and .index(type);

The index() function of jQuery is missing.

$('#demo').index(); // 2
$('#demo').index('a'); // 3
$('#demo').index('.pepe a'); // 1

Perhaps something like this?

//inspired from https://stackoverflow.com/a/9132575/1081396
function index(item, context){
    var siblings = $(context) || $(item).parentNode.children;
    return Array.prototype.indexOf.call( siblings, $(item));
}

To use this way:

console.log(index('#demo')); //2
console.log(index('#demo', 'a')); //3
console.log(index('#demo', '.pepe a')); // 1

Having

<div>
    <a href="">Text 1</a>
    <b>Text bold</b>
    <a href="">Text 2</a>
</div>
<div class="pepe">
    <a href="">Text 1</a>
    <b>Text bold</b>
    <a href="" id="demo">Text 2</a>
</div>

Working with querySelector()'s null return.

Something that's used often on our end is the || operator for querySelector() and querySelectorAll(). May be useful to include it as a possibility. It removes an if check or a ternary operator + double assignment.

This single thing helped a movement to remove jQuery from our agency's toolbelt at one point in time.

var elements = [].slice.call(document.querySelectorAll('*') || []);

ES6 Array.from

Array.prototype.xxx.call(document.querySelectorAll(selector), args)

==>

Array.from(document.querySelectorAll(selector)).xxx(args)

isNumeric is not completely equal to $.isNumeric

This article is very helpful to understand native Javascript
But I found some issues to be fixed

$.isNumeric(new Number(1)) // true

function isNumeric(value) {
  var type = typeof value;

  return (type === 'number' || type === 'string') && !Number.isNaN(value - Number.parseFloat(value));
}

isNumeric(new Number(1)) // false

I found another way to check numeric in
https://gist.github.com/pinalbhatt/9672790

function isNumeric(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

this function passed all cases in jquery public document:
http://api.jquery.com/jQuery.isNumeric/

Missing siblings()

The siblings() function of jQuery is missing here.

I suggest something like this:

//inspired from http://youmightnotneedjquery.com/#siblings
function siblings(el) {
    return Array.prototype.filter.call(el.parentNode.children, function(child){
        return child !== el;
    });
}

Convert jquery to native Javascript

Hi, I would like to convert a piece of jquery code into pure javascript. Can anybody help me.? Thanks.

    var mobileItems = jQuery( '#slide-out .nav-mobile .main-menu' );
    mobileItems.find( 'li.menu-item-has-children' ).append( '<i class="mobile-arrows fa fa-chevron-down"></i>' );
    jQuery("li.menu-item-has-children i.mobile-arrows").click(function() {
        if( jQuery( this ).hasClass( "fa-chevron-down" ) )
            jQuery( this ).removeClass( "fa-chevron-down" ).addClass( "fa-chevron-up" );
        else
            jQuery( this ).removeClass( "fa-chevron-up" ).addClass( "fa-chevron-down" );

        jQuery( this ).parent().find('ul:first').toggle();
    });

    var mobileItems = jQuery( '#slide-out .st-nav-mobile .main-menu' );
    mobileItems.find( 'div.penci-mega-latest-posts' ).remove();
    mobileItems.find( 'div.mega-cat-content-tab' ).remove();
    mobileItems.find( 'div.mega-recent-post' ).remove();
    mobileItems.find('.mega-cat-wrapper').unwrap();
    mobileItems.find('.mega-cat-sub-categories').unwrap();

function merge can remove duplicate items by set

// jQuery
$.merge(array1, array2);
// Native
// But concat function doesn't remove duplicate items.
function merge(...args) {
  return [].concat(...args)
}

// Set edition

function merge(...args) {
  return Array.from(new Set([].concat(...args)))
}
merge([1,2,3], [3,4,5]) // [1,2,3,4,5]

Keeping same source in all translation

Some PR update only some lang translation.

I think all source source code must be same.

How do you think about building readme with some script and seperated translation files?

For example..

// en.js
{
util: {
title: "Utilities",
description: "",
contents: {
  isArray: { title: "isArray", description: "" }
}
...
}

and

// isArray.js
// jQuery
$.isArray(range);

// Native
Array.isArray(range);

unwrap方法不太对

这个方法是将匹配元素集合的父级元素删除,保留自身(和兄弟元素,如果存在)在原来的位置。

但是在本文档中,它是将el的子元素放到el的父元素中,然后删除el。并不是删除el的父元素,与目的不一致

$(document).ready

Not really an issue, more of an addition or "feature request", but...

$(document).ready(function(){...});

can be replaced by

document.addEventListener("DOMContentLoaded", function(event) {...});

This is useful for making sure a DOM node is loaded before trying to access its elements or assign event listeners to it, etc.

Also, $(document).ready has more going on internally, but this could be considered a light replacement.

Missing prevUntil - $('#demo').prev('a');

Having:

<a href="#">Text</a>
<b>Text 2</b>
<a id="demo" href="#">Text 3</a>

We want to return the prev a, not the <b> element:

$('#demo').prev('a'); // <a href="#">Text</a>

In jQuery they call it internally prevUntil:

nextUntil: function(elem, i, until) {
    return dir(elem, "nextSibling", until);
},
prevUntil: function(elem, i, until) {
   return dir(elem, "previousSibling", until);
},

something wrong with el.clientHeight

image
I think it shouldn't contain border width.

I test it in chrome.

When border-box clientHeight means height - borderWidth
When content-box clientHeight means height + padding

It looks like el.getBoundingRect().height is equal to el.offsetHeight.

Making a jquery to native javascript compiler will be cool

Before:

$el.closest('p');

After:

// $ compiler foo.js --stage=morden
el.closest('p');

// $ compiler foo.js --stage=old
function closest(el, selector) {
  const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector;

  while (el) {
    if (matchesSelector.call(el, selector)) {
      return el;
    } else {
      el = el.parentElement;
    }
  }
  return null;
}

el.closest('p')

Simulate `.one()` without jQuery

Hi, thanks for making the repo. It helps a lot.

I didn't find a related topic of simulating .one() in the doc. I googled to find out rofrol's answer in Only fire an event once?, which works for me. Do you think it is something we need? I can make a PR on this.

function addEventListenerOnce(target, type, listener) {
    target.addEventListener(type, function fn(event) {
        target.removeEventListener(type, fn);
        listener(event);
    });
}

Best way for $("#foo .bar")

document.querySelector and document.querySelectorAll are quite SLOW,

What is better way if use $("#foo .bar") ?

1 - document.getElementById('foo').getElementsByClassName('bar') ?

or

2 - document.querySelector('#id .bar') ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.