Skip to content

Latest commit

 

History

History
277 lines (189 loc) · 9.31 KB

jquery.md

File metadata and controls

277 lines (189 loc) · 9.31 KB

Porting from jQuery

UmbrellaJS offers some advantages over jQuery:

  • Speed: using native methods makes it faster.
  • Size: UmbrellaJS is 3kb in total.
  • Clean: making new plugins and reading the code base is easy.

But it has some tradeoffs, mainly the lack of support for IE10- and SVG on IE11.

If you like the easy and readable syntax, but don't like how fat and slow jQuery is, you should:

UmbrellaJS is small (3kb gzipped) and has a similar syntax as jQuery. it use native DOM elements instead of objects, this makes it fast. you can simply replace $(...) with u(...) in most cases.

Before porting to UmbrellaJS

UmbrellaJS does not support jQuery extensions! If your scripts make heavy use of extensions it's probably better you stick to jQuery.

Before porting an existing script to a jQuery alternative I strongly recommend to check your jQuery code to be correct.

Check for usage of $('.subclass', $('.myclass'))

Even $('.subclass', $('.myclass')) and $('.myclass').find('.subclass') are equivalent, you should use the latter. it's more readable and easier to port.

Check for correct $(element) selection

Even if your script work, there are some pitfalls where jQuery works when you are using it in the wrong way.

example: you need exactly one element by class

$('#myID') always returns one element, more exactly the first matching element. all other selectors return ALL elements. If you want to select ONE element of $('.myclass') you must use $('.myclass').first(), $('.myclass').last() or $('.myclass').eq(n). You must not use of $('.myclass')[0]

Avoid advanced non-standard CSS selectors

Instead of $('.myclass:not(div, a)') I strongly suggest to use $('.myclass').not('div, a') instead. It's more readable, faster and works with all CSS standard selectors.

jQuery extends the :not() selector such that you can pass any selector to it, no matter how complex it may be. the :not() pseudo-class in CSS only accepts a single simple selector as an argument to :not(). for more Information see explanation on Stackoverflow

First steps

UmbrellaJS can be used in parallel with jQuery, so you can start porting to UmbrellaJs step by step. simply include <script src="https://unpkg.com/Umbrellajs"></script> in your HMTL file or // @require https://unpkg.com/Umbrellajs in your script, if you are writing a userscript.

Then you can start changing your statements one by one from jQuery to UmbrellaJS by replacing $(...) with u(...).

Porting tips

While porting my enstlyer script from jQuery (more precise from zepto.js) to UmbrellaJS I discoverd some pitfalls I want to share with you. Nevertheless it was easy and it's always helpfull to have the excellent UmbrellaJS documentation in a browser tab.

Why does .replaceWith() not exist in UmbrellaJS?

This should be very simple, use the UmbrellaJS .replace() method instead. It has nothing to do with the native javascript .replace() method for arrays though, so make sure not to mix them up.

If you wants to stay with .replaceWith like in jQuery and does not care about an extra function call, adding this to your script may help:

u.prototype.replaceWith = function(replace){
  return this.replace(replace);
};

Why does .css() not exist in UmbrellaJS?

I generaly avoid to set CSS properties with JavaScript, because it's better and faster handled by CSS rules. To do something similar as jQuery .css() get method with UmbrellaJS you can use this getStyle() function:

// alternative for jQuery .css() get method
function getStyle(oElm, css3Prop){
  // FF, Chrome etc.
  if(window.getComputedStyle){
    try { return getComputedStyle(oElm).getPropertyValue(css3Prop); }
    catch (e) {}
  } else {
    // IE
    if (oElm.currentStyle){
      try { return oElm.currentStyle[css3Prop]; }
      catch (e) {}
    }
  }
  return "";
}
// usage examples
// Umbrella: use one node
getStyle(u('.myClass').nodes[n], "border-radius");

// use one native DOM node
getStyle(getElementsByClassName('myClass')[n], "border-radius");
getStyle(getElementById('myID'), "border-radius");

see: https://www.htmlgoodies.com/html5/css/referencing-css3-properties-using-javascript.html#fbid=b2-TgWC-yGY

$(this)should be replaced by u(el)

UmbrellaJS follows the native Javascript callback structure for iterative methods. Your jQuery .each() loops might look like this now:

$('.myclass').each(function () {
    ...
    $(this).dosomething();
    ...
});

You should change them to look like this:

u('.myclass').each(function (el) {
    ...
    u(el).dosomething();
    ...
});

Note: Search for occurences of u(this) while/after porting, in almost all cases it's not correct!

UmbrellaJS provides the actually processed node as first argument to the called function, see the documentation for .each().

As a bonus you get the node index as second argument, so you don't have count it yourself in case you need it:

u('.myclass').each(function (el, i) {
    ...
    alert('This is iteration # ' + i + ' of myclass');
    ...
});

This resembles closely the native array forEach:

['a', 'b', 'c'].forEach(function (el, i) {
  alert(el);
});

Which is also really useful for using Arrow Functions:

u('.myClass').each(el => alert(el.innerHTML));
['a', 'b', 'c'].forEach(el => alert(el));

Using UmbrellaJS .first()/.last()/.eq() returns native DOM elements

In jQuery .first()/.last()/.eq() returns a jQuery object, but UmbrellaJS returns a native DOM element. this has pro and con:

  • pro: you can use native javascript DOM manipulation
  • con: you can't chain an other UmbrellaJS method like in jQuery
  • con: be careful to select the correct DOM property/method!

Wait, there is no .eq() in UmbrellaJS, but you can use .nodes[n] as a functional replacment.

power tip from UmbrellaJS creator: You can wrap the whole thing into another u(...) and use UmbrellaJS functions conveniently.

example: how to get inner html of first element:

// jQuery:
$('.myclass').first().html();

// Umbrella: direct access to DOM property innerHTML
u('.myclass').first().innerHTML;

// Umbrella: wrapping it in u(...) again
u( u('.myclass').first() ).html();

example: how to add html before last element:

// jQuery:
$('.myclass').last().before('<div>this is inserted before</div>');

// Umbrella: direct use of .insertAdjacentHTML() method
u('.myclass').last().insertAdjacentHTML('beforebegin', '<div>this is inserted before</div>');

// Umbrella wrapping it in u(...) again
u( u('.myclass').last() ).before('<div>this is inserted before</div>');

// wrong: do not mix it up with DOM method .before()!
// insert TEXT => "&lt;div&gt,this is inserted before&lt;/div&gt,"
$('.myclass').last().before('<div>this is inserted before</div>');

See also documentation of .insertAdjacentHTML()

example: add a DOM node after n'th element:

// create a native DOM node
var myBbutton = document.createElement('input');
myButton.type = 'button';
myButton.setAttribute(enID, 'myID');
myButton.onclick = showConfig;
myButton.value = 'Config ';

// append native DOM node befre n'th element
u('.subNavMenu').nodes[n].after(enMenuButton);

If you want to have an UmbrellaJS .eq() method and don't care about an extra function call, adding this to your script may help:

// get the nth of the nodes
u.prototype.eq = function (index) {
  return this.nodes[index || 0] || false;
}

How to break out of UmbrellaJS .each() loop?

In jQuery you can use return false; to stop the iteration of an .each() loop. this is diffrent in UmbrellaJS, the loop always processes all given elememnts!

Depending on your use case you can mimic the jQuery logic in different ways:

example: stop after 5'th iterration

u('article').each(function (el,i) {
  if (i>5) return;
  dosometing(el);
})

example: abort after something failed

var abort=false;
u('article').each(function (el,i) {
  if(abort) return;
  if (! dosometing_ok(el)) abort=true; ;
})

You miss some jQuery features in UmbrellaJS?

A good source of inspiration is You Might Not Need jQuery. You can also search on stackoverflow for jQuery alternatives in pure JavaScript

You can apply most tips from there to single UmbrellaJS node directly:

// jQuery
$('#hide').hide();
$('.myclass').hide();

// Umbrella: apply "You Might Not Need jQuery" tips to one Umbrella nodes[n]
$('#hide').nodes[0].style.display = 'none';
$('.myclass').nodes[n].style.display = 'none';

If you have to apply to all nodes returned from UmbrellaJS, you can use an .each() loop to apply to every node

// jQuery
$('.myclass').empty();

// Umbrella: apply "You Might Not Need jQuery" tips to all Umbrella nodes
$('.myclass').each(function (el) {
  el.innerHTML = '';
});