Or, you know, use the Javascript DOM APIs? They're really not at all that bad.
var d = document.createElement("div");
d.className = "new";
d.innerHTML = "<p>Hi Sprint</p>";
Skimming through the code I'm not sure the authors really grok Javascript anyway, which might explain why they need a (pretty thin) custom API for the standard APIs. toArray should be simply this:
function toArray(o) { return Array.prototype.slice.call(o) }
Instead it's:
var toArray = function(obj) {
var arr = []
var i = obj.length
while (i--) {
arr[i] = obj[i]
}
return arr
}
This is just silly:
prepend: function() {
insertHTML.call(this, "afterbegin", arguments)
return this
},
var insertHTML = function(position, args) {
var argsLen = args.length
var contents = args
[...]
var domMethods = {
afterbegin: function(el) {
this.insertBefore(el, this.firstChild)
},
Perhaps this isn't so constructive and I should fork the library and annotate every method with its vanilla Javascript equivalent. I'm sure this post is non-constructive in some respects but I like Javascript, I just wish people would learn how to work with the language it instead of replacing the API wholesale.
DOM inconsistencies aside, a big advantage jQuery has over native API is that it is just as easy to work with multiple elements as it is single elements.
Modifying your example:
var d = document.querySelectorAll('div');
d = Array.prototype.slice.call(d);
d.forEach(function(el){ el.classList.add('new') });
There is a lot of uses of innerHTML in this code which causes browser reflow; might get better performance creating all of the HTML components via document.createElement() and using document.createTextNode() for all text within a tag itself.
But yeah cherry-picking may not be the most constructive thing however you do have good points. The DOM API is kinda funky (I wish it did some things like chaining) but it's very simple. Half the times I write a very thin wrapper around it JUST to provide some chaining.
See, that's why I end up using these libraries. If I found myself doing the three statements for creating a div in your parent's comment, I'd pull that out into a function that does it, then I'd start finding other things to pull out as well, then I'd think "surely somebody has made a library that has these things pulled out nicely", and I'd find one of these libraries. Since I know that would happen, I just start with a library from the beginning.
But I suppose I'd love one that is thinner, like your "very thin wrapper", if anybody has pointers.
I find it interesting that, because some design decisions seem odd to you at first sight, you immediately conclude that the reason is a poor understanding of JavaScript. The `toArray` function, for example, is just performance optimization:
http://jsperf.com/toarray-slice-call-vs-loop
A tiny, lightning fast jQuery-like library for modern browsers.
Respectfully, this entire description is an oxymoron. Every time someone mentions a jQuery-like microlibrary, they just mean a jQuery without wide browser(-quirk) support.
Browser support is a big part of what makes jQuery jQuery, and without it, you definitely get a much smaller library, but it is also very un-jQuery-like. :)
Now for some praise! It makes me really happy to see a comparison - benchmark! - with competitors, which is something everyone should be required to do, when they create software with 40,000 similar offerings. Looking at you, Markdown editors!
jQuery 1.x is recommended over 2.x due to lack of IE8 support in the latter. If you don't have IE8 traffic on your site, you can safely go with 2.x (which isn't that much smaller to begin with).
I thought that was true, but checked a few months back and the advice seemed a bit more equivocal than that:
> So, here’s the TL;DR for version 3.0 of the jQuery API:
> * If you need support for the widest variety of browsers including IE8, Opera 12, Safari 5, and the like, use the jQuery-Compat 3.0.0 package. We recommend this version for most web sites, since it provides the best compatibility for all website visitors.
> * If your web site is built only for evergreen leading-edge browsers, or is an HTML-based app contained in a webview (for example PhoneGap or Cordova) where you know which browser engines are in use, go for the jQuery 3.0.0 package.
I personally currently need to support IE9 which I wouldn't class as an "evergreen leading-edge browser". I was hoping for a more in depth compatibility chart that named specific versions.
I'd love to have a streamlined but otherwise version of JQuery which I can serve to known modern web browsers. And serve the 'full' version to non-modern browsers.
Sounds like Zepto is pretty close to what you're looking for: http://zeptojs.com/. Otherwise, jQuery 2.x is just jQuery without support for IE 6, 7 and 8. I'm not sure what kind of performance improvements it offers, but it shaves off a few kb.
In a horrendously framgented mobile internet, one of the few blessings we do have is that the vast majority of mobile web browsers are WebKit variants so this kind of makes a lot of sense if, say, you're only targeting iOS and Android default browsers.
I'm curious if it will take jQuery plugins though. Will try later.
The default Android browser is no longer supported, and the embedded Chrome is blink-based and less and less webkit-ish.
(And even the different Webkit ports can't be thrown into the same bag.
Compare e.g. Safari on OSX, Safari on Windows, Midori on Windows and Midori on Linux. Two webkit browsers, crass rendering and behavioural differences between them and on each platform.)
It would be better to say that mobile benefits from modern browsers, not just WebKit ones. I've gone without jQuery on a bunch of mobile only projects and run into zero issues.
Not supporting the selector for .on() and .off() is a pretty serious limitation; catching bubbled events on child DOM elements is a super-common jQuery pattern, and makes event-handling over a DOM that's having stuff added to it much more pleasant to write. It's also pretty fundamental to some third-party libraries that run on top of jQuery, like Backbone (at least if you use its View event handling).
Yeah, its great that there are libraries like this that try to do better than the status quo.
But, with every new library there's always the question about support.
And so since there is no involvement perceptible on its Github page (no PRs, no issues and 3months without a commit), I wouldn't want to use this in production.
That's the problem with all these JS libraries and frameworks. They are being written just to be written; only a handful have been vetted in production.
Not the author, but the API still sucks to write using vanilla JS. There are also still plenty of inconsistencies in modern browsers (per an article floating around here in the last day or two).
If you want syntactic sugar, a better alternative to a client-side library (which has overhead) is to use something like TypeScript (or one of the other compile-to-JavaScript options).
I just assumed the person I was replying to was complaining about document.getElementById('whatever') (etc.) vs $('#whatever').
In response to your comment, polyfills are more future-proof solutions to browser compatibility, which is the only remaining problem that I see jQuery as solving well.
> I just assumed the person I was replying to was complaining about document.getElementById('whatever') (etc.) vs $('#whatever')
Actually that is what I was referring to. I must not have given TypeScript enough of a shake. I couldn't find the section in the early tutorial that showed me that sugar, and I also couldn't figure out how the typing stuff would help me working with a bunch of network-y type apps. Obviously this is my own failing. Inspired now to give it another shot, so thanks.
It's entirely my own fault, but this has been a really muddled conversation.
When I mentioned TypeScript, I only meant that it (and other languages that compile to JavaScript, like Go) is a better syntax overall. I didn't actually mean that it helps with DOM selection/manipulation.
So if you want short DOM syntax, I'd suggest using vanilla ES6[1] with polyfills, and then figure out what's really wasting your time. Then, you can write your own sugar for it.
In my opinion, document.getElementById is something that you end up writing a lot and is really long, but with autocomplete in a good IDE, it's not a big deal. Plus, any JS developer who sees it will know exactly what it does and what it returns.
Do you have any examples? In my opinion the DOM API only sucked pre-IE9 because of all the inconsistencies and incompatibilities.
I have dropped jQuery completely except for when I need some of its plugins because I end up having to access the internal DOM objects too often and using $el.get(0) all over the place is ugly and a PITA.
> I would argue that the second half is a little unfair, since that style of coding is entirely influenced by jQuery. You usually don't actually need to trigger a real DOM event there, you just want to execute some callback as if the element was clicked.
Maybe I'm missing something, but the second half is adding an event handler (`somethingClicked` is presumably a function). That seems like a _very_ common thing to do regardless of jQuery.
> This does get a little uglier if the intent is that you have multiple '.something' elements, though. That part of the DOM API will always be pretty gross compared to jQuery, I think.
Well yeah hence my remark. Working on a single node in a single modern browser, the snippet will turn into
var node = document.querySelector('.something');
node.classList.toggle('collapsed')
node.addEventListener('click', somethingClicked);
but if you need multiple nodes, now you have to manually loop and beware your closures.
And that's a best-case scenario, then you start traversing the DOM tree, adding elements, using events delegation and changing attributes and things go south fast.
> And that's a best-case scenario, then you start traversing the DOM tree, adding elements, using events delegation and changing attributes and things go south fast.
Why would things so south? The DOM API, while not very elegant, is very simple and straight forward. So you need some loops because jQuery hides that for you, so what? Why does using the DOM API make you think things go south fast?
> Why would things so south? The DOM API, while not very elegant
It's not just "not very elegant", it's highly inconvenient and horrendously verbose, and generally fails to take advantage of or correctly integrate with the host language as it's originally expressed in a restrictive and alien IDL.
> is very simple and straight forward
I completely disagree on both count, the API is neither simple nor straightforward, many tasks remain convoluted even with HTML5's additions of a number of long-awaited APIs (e.g.: repeatedly adding children at the start of a possibly child-less element) and the userland code is made unnecessarily complex not by a simple API but by an insufficient one (e.g. enjoy handrolling element-relative events delegation Element#matches is a pointless waste of API space).
And then there's the truly idiotic stuff added on top, such as the live nodelists which serve no other purpose than making implementations slower, more complex and event less integrable with the host language. Thank god the WhatWG managed to keep that garbage out of the new APIs they introduced.
> So you need some loops because jQuery hides that for you, so what?
So that means overly complex user code for no good reason but the base API being garbage. And jQuery does not "hide loops", that's just a side-effect of jQuery working at a higher conceptual level of manipulating nodesets.
There are plenty of reasons to not like the DOM API but you're not doing a good job stating your case.
> It's not just "not very elegant", it's highly inconvenient and horrendously verbose, and generally fails to take advantage of or correctly integrate with the host language as it's originally expressed in a restrictive and alien IDL.
This is kinda what you already said before but haven't really clarified. What doesn't integrate correctly with the host language? It's certainly inelegant but "horrendously verbose" seems quite extreme. Creating, deleting and modifying elements is easy and straightforward, adding and removing event handlers is easy and straightforward; you rarely need more features than that. Could you provide some insights here?
> repeatedly adding children at the start of a possibly child-less element
What are you referring to here? insertChild has let you do this and has been part of the standard since 1997. Are you referring to something else or a specific issue?
What are you referring to when you say "handrolling"? Are you referring to jQuery's ability to set, say, a click event on a parent to target the children so the children can be removed without changing it? I hope that's not all you're referring to because that's dead simple to deal with and using jQuery's event bubbling isn't always very speedy. If you're creating these elements why can't you attach and detact event handlers?
> Element#matches is a pointless waste of API space
Matches allows you to look to see if a match exists without returning the data. This may provide slightly better performance if all you need to do is a check for something. I agree it's not entirely useful but a "waste of space" is a bit extreme; it can serve a purpose and it's a very small addition. Nit-picking on single methods isn't exactly helpful.
> such as the live nodelists which serve no other purpose than making implementations slower, more complex and event less integrable with the host language
First you complain the DOM API doesn't integrate into the host language and now you complain about live NodeLists when this is using a JavaScript semantic. You need to pick one and not conflate the two. JavaScript passes objects by copy of reference (meaning you can modify the original but not replace). Implementing NodeList to be live makes perfect sense here. Would you prefer the DOM API actually NOT follow standard JavaScript and do something...funny?
> So that means overly complex user code for no good reason but the base API being garbage. And jQuery does not "hide loops", that's just a side-effect of jQuery working at a higher conceptual level of manipulating nodesets.
The features you sighted previously allow you to act on multiple NodeList items without iterating through them directly. jQuery is still iterating through them in the background. How a loop is "overly complex" for "no good reason" I do not understand.
I like this approach. I generally tend not to use jQuery, because native DOM API is often good enough for my needs, but it's not fun to write and read code using that API. jQuery for me is shortcuts and wrappers for this code.
I ran the first benchmark linked in the readme on my mobile phone (2013 Moto G, i.e. old mid-end phone) and on my laptop (Thinkpad X230 i5-3320M), both on Firefox:
I get 12+ million operation (a true master race class) vs advertised 800,000 and peasantry of jQuery's 300,000.
Not sure if I want to sacrifice performance for aesthetically better looking (debatable ofc) syntax and bother investing time learning how to do something slower.
function toArray(o) { return Array.prototype.slice.call(o) }
Instead it's:
This is just silly: [...] Perhaps this isn't so constructive and I should fork the library and annotate every method with its vanilla Javascript equivalent. I'm sure this post is non-constructive in some respects but I like Javascript, I just wish people would learn how to work with the language it instead of replacing the API wholesale.