Hacker News new | past | comments | ask | show | jobs | submit login
PlainJS – Vanilla JavaScript Repository (plainjs.com)
210 points by shakes on Sept 25, 2017 | hide | past | favorite | 156 comments



Yea, let's bury jQuery again and make more "helpers.js" [1]

    export function extend(src) {
      var obj, args = arguments
      
      for (let i = 1; i < args.length; ++i) {
        if (obj = args[i]) {
          for (let key in obj) {
            // check if this property of the source object could be overridden
            if (isWritable(src, key))
              src[key] = obj[key]
          }
        }
      }
     }
or just add super-unique stuff to our classes [2]

    DragSelect.prototype.removeClass = function( element, classname ) {    
      var cn = element.className;
      var rxp = new RegExp( classname + \'\\b\', \'g\' );
      cn = cn.replace( rxp, \'\' );
      element.className = cn;
      return element;    
    };
    
    DragSelect.prototype.hasClass = function( element, classname ) {    
      var cn = element.className;
      if( cn.indexOf( classname ) > -1 ) { return true; }
      else { return false; }    
    };
or write tons of boilerplate code like

    if (typeof element === 'string') {
        owner.element = document.querySelector(element);
    } else {
        owner.element = ((typeof element.length !== 'undefined') && element.length > 0) ? element[0] : element;
    }
(mmm, it's so vanilla)

[1] https://github.com/oncode/handorgel/blob/master/src/helpers....

[2] https://github.com/ThibaultJanBeyer/DragSelect/blob/master/s...


Your JS knowledge appears to be severely outdated. Instead of the first you can now write:

    Object.assign(target, object1, objectN);
The second:

    element.classList.add(className);
    element.classList.contains(className);
And the third has been fixed at a community level, as we've learned the value of API strictness, obviating such checks.

I don't think anybody was against jQuery back when the alternative was helper functions, I certainly wasn't. But that's five years ago at this point. Modern JavaScript looks nothing like the code you posted, it's actually been built up into a pretty good language.


You are ignoring browsers support. One of the main reasons I suggest using jQuery is browser support. Another solution is to use a transpiler like Bable.


> Another solution is to use a transpiler like Bable.

At this point in front-end development something like Babel is a must. If you aren't using Babel/Flow/Typescript in your workflow, you are putting yourself at disadvantage for no good reason.

For better or worse, transpiling is a fact of life.


If you're not using a framework that requires you to transpile, jQuery basically takes care of the most common bits.


"Five years ago" refers to across-the-board browser support, the spec is older. You can use caniuse.com, https://kangax.github.io/compat-table/es6/, and/or MDN compatibility tables to quickly check browser support. Browsers are now grinding away at new APIs constantly - don't let your memory of "not safe to use" last more than a year.


It may be hard to imagine, but even today not every user is running a browser built in the last year.


Corporate and government SOE machines are often running versions 7+ years out of date. I'm still EOL'ing XP machines for government clients. Seniors are another group who often run, well, senior versions.

If your Uber-for-toothpaste startup doesn't care then fine. But crusty old browsers are still a crucial factor in many markets.


Many companies and developers simply decide this group is insignificant and just don't care.


If you explore the first of the links you're replying to, you'll see that I make my conclusions about what people are using based on country-adjusted analytics from millions of websites, not imagination.

This situation is actually improving too. Chrome's "evergreen" development cycle has made a world of difference to feature adoption rate, and it's spread to every other major browser vendor. Once IE11 dies out, we'll have no non-evergreen browsers over 1% market share, and it makes me so happy to say that.


Babel on its own only addresses syntactic functionality and wouldn't cover this, but it is indeed extremely easily to polyfill `classList`.


Are you absolutely certain that everything that jQuery does can now be done in a clear and concise way using plain Javascript? I've written some fairly complex jQuery selector over the years, perhaps I'm wrong but I something tells me that while the simple use cases can be done with plain old js the more complex selectors might not be so easy.

I find this debate so aggravating. I'm glad you can do some of the stuff jQuery does using modern vanilla js. Perhaps jQuery is overkill for doing one hide/show (or toggle) action on the page. But what about the more complex stuff. What is primary motivation behind this nagging issue, of the load time of jQuery?

I suspect it is that many developers have some obsession over shaving a few milliseconds on their load time. For jQuery? One library? Is it that bad that you need to write vanilla js? So you can save a few milliseconds?

Can you have a sophisticated selector for Event Delegation without using jQuery but make the code concise and easy to read? What about child selectors ("ul.thisClass > li.thatClass" > span.otherClass").

I like jQuery because the syntax makes sense, its clear and concise, you can do complex things with less code. Maybe some of the new stuff can be clean and concise and easy to read, but all of it? I have my doubts.


> Are you absolutely certain that everything that jQuery does can now be done in a clear and concise way using plain Javascript?

Can you give us some examples of things that you're worried can't be written clearly using plain JS? Obviously everything you can do with jquery you can do without jquery. Its just a library.

> Can you have a sophisticated selector for Event Delegation without using jQuery but make the code concise and easy to read?

What do you mean by event delegation in this context?

> What about child selectors ("ul.thisClass > li.thatClass" > span.otherClass")

document.querySelector / querySelectorAll supports this. Its available in all browsers on all platforms if thats how you chose to make web apps: http://caniuse.com/#feat=queryselector


> Can you give us some examples of things that you're worried can't be written clearly using plain JS? Obviously everything you can do with jquery you can do without jquery. Its just a library.

The not() selector for jquery is one. The closest() is another that I have used multiple times.

> What do you mean by event delegation in this context?

This is what event delegation looks like in jQuery; $("ul#listid").( "click", "li.classThatMatters", function() { //do something });

How would event delegation look when selecting a child element with a specific class? Event delegation from scratch in vanilla js is longer than this.

I don't know much about query selectors. I'm going to read up on them. I suspect it handles most if not all the basic stuff jQuery does. However I suspect that are use cases that it might now.


If I understood your event delegation example correctly, I would use event.target.matches inside the event handler. Not the greatest support at the moment though.


Make an HTTP request. Parse the JSON body if a 200, otherwise log an error.


I haven't tested it but I think this should work:

fetch(url)

.then(res => res.status === 200 ? res.json() : Promise.reject(res))

.then(data => { ... })


And the Fetch API, has, according to caniuse[1], 76% support. I don't know that I can disregard 1 out of every 4 users, hence, jQuery.

For some things, like those mentioned by twhb, where support is >90%, sure, ditch the library and use the supported stuff. But I don't think all of jQuery is that well supported, yet, and/or has as decent an interface.

[1]: https://caniuse.com/#search=fetch


I suppose. Or just use a polyfill for old browsers. It increases your code size a little, but at least the bloat is temporary.

https://github.com/github/fetch or https://www.npmjs.com/package/fetch-ie8


Polyfills are a good option in some cases. I, personally, try to stay away from them as much as possible. Once you add a polyfill (e.g. fetch), you' soon realize that you need another one (e.g. Object.assign) and soon you will have a list of polyfills to take care of. The advantage of jQuery in this regard is that it has all these "polyfills" in one place.

I believe that jQuery is not "modular" enough for today's web development environment. The "light" version is a step in the right direction but it's not enough. If one could configure the "modules" needed and download/load a single file/library, it would be tremendous.


Yep, Fetch API would be fantastic....if it was widely supported.


You're right, some things are still shorter with jQuery, but one must weigh that against the rest.

Native selectors are nearly as powerful. Your example works as-is, "not" is there, full reference at https://www.w3.org/TR/css3-selectors/#selectors.

Event delegation isn't native, but is now possible in five simple lines. That's the pattern: even when there's no native equivalent, new language features facilitate shorter, simpler implementations.

jQuery's performance impact is orders of magnitude worse than "a few milliseconds". On semi-old laptops and on mobile I've seen 200ms in just the time it takes to execute jQuery after loading it. There's also runtime overhead. It's not unbearable, but it's a real hit on a page with high user experience goals.

Native alternatives are often better–thought-out and better-integrated. For example, native Promises have better exception handling (thrown errors can be caught to continue down the "then" chain), more reliable execution order ("then" always defers callbacks, jQuery sometimes executes them inline), and integrate with `await`, like `const data = (await fetch("data.json")).json();`. (Though you should still transpile that, some browsers that don't support it are still in use.)

Besides that, unnecessary abstraction resists novelty and efficiency in the use of underlying resources.


Perhaps the examples are just a reflection of having to support Internet Explorer?


Rather than using a library with a bunch of utility functions that you may or may not need, using individual utility functions indeed does seem like a better idea.

For example, I don't support browsers without classList, so I don't need your regexp stuff. Maybe you do, but my code shouldn't be larger because of that.


Problem now is that you get to write, test and maintain all this instead of using something that has a whole community backing it.


Most of these utility functions are fairly straightforward and will rarely require any changes or maintenance. Testing should therefore be straightforward as well. Having the whole community back something doesn't mean it's bug-free, and sometimes it makes it harder when their release cycle isn't as frequent as you'd like it to be.

Having said that, it's all about tradeoffs. Whether your project needs something as big as <insert JS framework or lib here> or if you can live with just needing a few utility functions, you make those choices, doesn't mean one is better than the other as it all depends on context and situation.

jQuery has become the defacto must-use library for javascript now which IMO is unfortunate, as a lot of sites and apps include it when they barely use most of what jQuery offers. I'm guessing most use jQuery for only a few things - Ajax, DOM querying, and events. I hope that sometime in the future jQuery would be more modular.


If you search for classList on npm you get a half dozen results. I disagree with your assessment here.


Dead code elimination (i.e. UglifyJS) should do away with most unused code from a library - so with a proper build system this shouldn't be a big concern...


I don't think you'll find UglifyJS's dead code elimination to do the type of tree shaking that'll remove jQuery's unused functions.


What if one wants to keep things simple with a minimal/nonexistent build system?

I haven’t done serious web work in ages but if I did I’m quite sure I’d find all of today’s “required” build tools quite frustrating.


And yet by "keeping it simple" you have to re-write and maintain a bunch of utility functions that are solved problems.


If they're solved problems, what difference does it make what form and package they arrive in?


You say that as those jQuery is the only place you can get a addClass function without writing it yourself. It isn't.


Not at all, OP said "if one wants to keep things simple with a minimal/nonexistent build system" which would exclude the easiest ways to get one-off utility functions.


Wouldn’t this be an argument for adding those solved problems to JavaScript as like a standard library? I’m not a web developer by day so forgive me if I don’t know all the nuance of JS but I feel like what you would consider it’s “standard” functions is quite small.


For what it's worth, it already is.

https://developer.mozilla.org/en-US/docs/Web/API/Element/cla...

Builtin functions for adding, removing, toggling and querying classes on elements.


That is generally the long term solution, and the reason this website is saying jQuery is no longer needed (because modern browsers offer a much better and more consistent foundation). The problem is the short term. While waiting for browsers to catch up and add new things, we usually have to polyfill, hence this debate.


If it's for some gain, then why not. It's a trade off decision.


It won't. UglifyJS's dead code elimination is snake oil and mirrors anywhere but in the most trivial of cases.

See:

- https://github.com/webpack/webpack/issues/2867

- https://github.com/webpack/webpack/issues/4784

(Note: webpack doesn't do any dead code elimination, it relies on UglifyJS to do so)


Those are good links to interesting discussions on the topic, I guess UglifyJS is better than nothing although you're right there.

Are you aware of any alternative that can do tree shaking? Reading those issues' comments there is a link to babel-webpack-tree-shaking [1] which seems to do it?

[1] https://github.com/Aladdin-ADD/babel-webpack-tree-shaking


Rollup [1] seems to be pretty good at tree-shaking and apparently babel's babili minifier [2] is better than UglifyJS (but I guess it's too early to tell)

But both come with their own tradeoffs: Rollup is ES6 only and doesn't support certain features from TC39's Stage 3. Babili is very very new :)

[1] https://rollupjs.org

[2] https://github.com/babel/minify


These utility functions and shims are "per" component. This means that functions like extend will be repeated many times in different idiosyncratic code across app.

Imagine your app uses, modals, dropdowns, multiselects, search autocompletes, sliders, rich text areas etc. Instead of having one cached utility library upfront you have many hidden utility libraries scattered around each component, which makes it difficult to say clearly that jQuery is always larger.

The other issue is maintainability. When you're working with third party components, hot-fixing an OS library can be fairly daunting if you need to also learn their own internal class structure, selector helpers, dom manip functions. Doing this in jQuery, it's fairly easy to fork the codebase and plop in a .clone() or .append() to fix a stale issue.


removeClass and hasClass are interesting choices considering browsers ship with these APIs


I don't think that burying jQuery is the best idea, too. It is a very well-designed library. What we really need is a library of functions to make the native APIs less awful and verbose - which exists: Zepto.js.

Ultimately mutating the DOM directly is just an awful job - it's solving problems that are ancillary to the problem that you are trying to solve (making great UIs). React and Vue feel like sensible abstractions, although there's still a far better but undiscovered solution to this problem.


Vanilla JS is more about being agnostic to the framework and framework version the developer is using. Not everyone uses jQuery, and if you library depends on it, you now require several tens more kilobytes of bloat to be loaded just for your thing to function.


The real problem is JQuery isn't modular and it is tightly coupled with your code.


I've thought a lot about this and honestly I'm curious if this would even be an advantage. Currently I can pull in jQuery from a CDN and it is likely used by many other sites. If I have a custom version of jQuery, now it is guaranteed to need to be loaded. Is it truly a win?


If you're using a build system like webpack you can use Babel/minify to get rid of unused code or pick and choose your modules directly from the npm package.


I still think jQuery/UI, libs maintained by a group that has a vision, organization, etc. Is a better solution than pulling in a ton of shitty half hearted components, functions, what have you from a bunch of random developers and repos scattered across the internet. Bootstrap works because it is built by a team, solves a specific problem and solves it well. jQuery is the same thing.

I grant that the things linked from this site are useful and novel, but I don't want to build a project sourcing things from 16 different developers when I could just bring in one library that does all of them, and might weigh a little more over the net.


Bootstrap at least provides a way to pull in only components that you need. I would argue for a more modular jQuery.

There are some projects that don't require all that jQuery provides, and sometimes you want to min-max performance and size of JS that gets downloaded.

Keep in mind that jQuery is maintained and contributed to by more than 16 developers so you are technically sourcing things from multiple developers, just so happens they are in a single library.

Again, it really depends on what you're doing with your project and what you need for your project. Most developers include jQuery by default because it's just the most common and most used library, and PlainJS offers an alternative which I think is great.


What I'm looking for: libraries instead of one-size-fits-all frameworks. Libraries annotated for Closure Compiler's advanced compilation mode, so I can automatically tree-shake all the code that I don't need.


Could you give a common example from jQuery core that could be left away? I'd hate if I find a documentation about a method for a jQuery object only to find out that I don't have that extension yet. IMO its size is just about right.


That's my problem with microlibraries in general. How rigorous is your vetting process when you're starting to pull in code like left-pad, really?


leftPad is a very simple example but the goal of these micro libraries is to keep every project from having a utils.js which contain slightly different variations of the same code.


But a "macrolibrary" would seem to serve that goal equally well and also help solve the problem where many of your libraries overlap because none of them do quite what you need.


Most cool! A couple notes.

Anyone maintaining a public-facing codebase should note that "All functions work properly in IE 9 and above - most of them are compatible with IE 8." jQuery has compatibility going back much, much further. Users in third world countries with older computers are better served by jQuery.

jQuery has an enormous test suite, tons of documentation with examples, and unparalleled third-party support.


This is cute and all, but JQuery is slightly more than just a framework for accessing the DOM.

My JS is a bit rusty, but I remember that in JQuery I could do:

$("some selector").do_things()

And "do_things" would be done on all matching elements. For example:

$("li").addClass("foo")

Would add the class "foo" to all "li". I could further refine the selector above to select only the "li"s I wanted of course.

With the "plain js" solution, you have to "querySelectorAll" and then iterate over each element.

Another example is "ajax" requests. In JQuery you have the general purpose "ajax" method, with simple "success" and "failure" callbacks, and configuration done via a standard JS object filled with all the necessary parameters (and this object could be reused for the most part, since most of the parameters don't change). You can also chain ajax requests together with deferred objects. Simple, straightforward and useful.

With their proposed solution here, you have to faff around with the XMLHttpRequest object every single time you want to make a POST or a GET. Ugh. And if you need to chain a bunch of those together? Uuuuugh.

Yeah, you can put all of these things inside helper functions to hide the ugliness, but if you are going through all that trouble, you are essentially rewriting JQuery (or similar libraries), badly. If it is a one off thing, I guess you don't need JQuery, but if you are rewriting most of these methods, you are crazy. Use a library, and trim it down to remove the stuff you don't need (JQuery allows this, IIRC).

A final aside. One oft overlooked advantage of JQuery is that the "$()" method can be applied to anything, not just the DOM. You can create a JQuery object that encapsulates, say, an array. Then you can iterate with "each", you can "filter", etc. Also, you can easily trigger events on your objects with "trigger" that other interested parties can listen to them by setting up event listener with "on". Useful to give your classes some Qt style signal/slot semantics.


The sizzle library that jQuery uses takes advantage of querySelectorAll.

https://github.com/jquery/jquery/blob/2d4f53416e5f74fa98e0c1...

...only with a ton of wrapper code around it in order to support IE9 and below. If you don't have to support ancient browsers, there's no reason you can't write QSA code.

var nodes = document.querySelectorAll("li"); for(var i=0; i<nodes.length; i++) { nodes[i].classList.add("foo"); }

Yes it's slightly more code. It's also going to run a hell of a lot faster on, eg, a mobile device.


I prefer:

    for (let node of document.querySelectorAll("li"))
        node.classList.add('foo');
or:

    Array.from(document.querySelectorAll("li")).forEach(node => node.classList.add('foo'))
And if any particular pattern repeats in the code I'm writing I'll just create a helper function for that pattern (most of the time locally). Like:

    let qsa => s => Array.from(document.querySelectorAll(s));
There's nothing to test about that.


You don't even need the `Array.from` anymore. `.forEach` on `NodeList` is standard https://developer.mozilla.org/en-US/docs/Web/API/NodeList/fo..., so all you need to do is load a polyfill for that.


You might want to do map or filter before you do forEach. In which case you would need to convert it to an array.


Lol. You beat me to it. Kudos.


>>> My JS is a bit rusty, but I remember that in JQuery I could do: $("some selector").do_things() And "do_things" would be done on all matching elements.

---

jQuery selectors were matched in native JS by `document.querySelector()` and `document.querySelectorAll()`

Pretty sure `querySelectorAll()` operates quite the same as jQuery's selector which returns an array of element objects that you can perform actions upon. The primary difference being that you'll have to run the actions in a loop over the array if you want to perform them over the entire selection. Eg:

   let elements = document.querySelectorAll('li');
   for(let i = 0; i < elements.length; i++) {
     elements[i].addEventListener('click', e => {
       console.log(`This element is ${elements[i]}`);
     });
   }
You could write a helper in a few lines to handle that throughout your codebase if it's commonly used.


You can wrap that in Array.from() to take advantage of foreach, filter, etc..


This is how i've been doing it:

  const elements = document.querySelectorAll('li');
  [...elements].forEach((element) => element.addEventListener('click', this.onClickHandler));


It's even easier now. `.forEach` on `NodeList` is standard https://developer.mozilla.org/en-US/docs/Web/API/NodeList/fo..., so all you need to do is load a polyfill for that.


This is a much more elegant solution. Thanks.


Why do you need the [ ... elements ] -- can't you call foreach off elements directly? Is it not an array?


It's not an array, but in recent versions of browser it does support `forEach` and some others.

https://developer.mozilla.org/en-US/docs/Web/API/NodeList


No, it returns a NodeList, not an array. But, forEach exists on NodeList, but map and reduce does not (together with all the rest of the array functions).


And this is why JavaScript is one of my least favorite languages.

Is there a website that stays up-to-date with a brief summary of all this nonsense? I haven't programmed in JavaScript in 4 years but am needing to relearn it again for a project, and searching Google for "iterating over elements" in JavaScript returns 57 different techniques, all considered "the best way" at some different point in time over the last few years, and all with varying levels of browser support.

Looping/filtering over things should just not be this convoluted of a process...


I think that the Mozilla Dev docs would probably be useful to you, or at least that's what I always end up going to -- https://developer.mozilla.org/en-US/


It makes sense because the DOM is like a huge global, mutable variable. Map and reduce are used in functional programming to create a new immutable variable. forEach allows to mutate each node from the nodeList.


Huh, TIL I guess. I've only barely messed with that, and it most have just been on "recent enough" versions to support array functions.


This works too:

    var elements = document.querySelectorAll('li');
    
    var arr_elements = [].slice.call(elements);


> jQuery selectors were matched in native JS by `document.querySelector()` and `document.querySelectorAll()`

Funny how the first words of your statement are completely negated by the last half of your statement.

jQuery:

   $(<any selector>).anyfunction
This will work regardless of the number of elements returned by the selector: 0, 1, or any number.

The so called matching `document.querySelector()` and `document.querySelectorAll()` cannot come even close to the ease of use of jQuery's selectors.

`document.querySelector` returns one element only. It will be the first element matched, even if you have more.

`document.querySelectorAll` returns a pseudo-array of elements (in reality a NodeList) that lacks most of functionality of arrays, and you cannot apply any DOM functions to it without iterating through the entire list.

jQuery came out in 2006. It took w3c several years after that to come up with something resembling jQuery's selection function. 11 years later there's still not a single method in the entire DOM API that comes even close to jQuery's simplicity and expressiveness.


I'm not sure how you took my remarks as a criticism of jQuery, as it's likely because of them that selectors were approached from said angle at all.

Anyway it's pretty simple to emulate the jQuery selectors' syntax elegance.

eg. from a link I posted below. This would produce similar results to jQuery selectors (minus backwards compatibility for older versions of IE).

-- Note if you try to use vanilla JS methods on a jQuery-selected element you will have to target which of the selected elements you want to act upon. It will return undefined for the selected element and throw an error if you try to, for instance `$('p').innerHTML = 'something';`:

  class DOM {
    constructor ( selector ) {
      let elements = document.querySelectorAll(selector);

      this.length = elements.length;
      Object.assign(this, elements);
    }

    each ( callback ) {
      for (let el of Array.from(this) ) {
        callback.call(el);
      }

      return this;
    }

    on( eventType, callback ) {
      this.each(function() {
        this.addEventListener( eventType, callback, false );
      });
    }

  }


  let $ = s => new DOM(s);

  $('#something').on('click', e => console.log(`Hello, event: ${e}`) );


> I'm not sure how you took my remarks as a criticism of jQuery

I was replying to this statement:

"jQuery selectors were matched in native JS by `document.querySelector()` and `document.querySelectorAll()`"

> it's likely because of them that selectors were approached from said angle at all.

This is true :)

> This would produce similar results to jQuery selectors (minus backwards compatibility for older versions of IE).

It doesn't though. There are many more useful methods in jQuery, and you will eventually need to re-implement many of them. (Even such simple once as `.class()` or `.toggleClass()`, or `.attr()`, or `append()`, and many others).

It's easier to just go with jQuery :)


It seems we're confounding the original question, then. My point more succinctly was, if you use only a select number of methods from jQuery, it would not be hard to emulate the syntax using modern JS methods and wrapping them in a small bit of logic in a much smaller file size than including jQuery itself. If size is an issue -- for some, it is. Current JS has made up for a lot of what jQuery originally was intended to fulfill (and again, most likely because of jQuery). And if it's just a syntactic reference, it's really easy to employ the same standard throughout your app with a pretty simple helper class.

edit: I extended the above example to include some of the methods you mentioned, just for kicks. The append() function was the most difficult, but only because I had to figure out how to grab the child function's selector argument. I just had to bind the initial argument to the object in the constructor. It was a fun little challenge. I'm likely missing some functionality of it, but I was going for quick and dirty implementation as simply as I could make it.

https://gist.github.com/Robert-Fairley/5e1ae9f84bf6072b70892...


> if you use only a select number of methods from jQuery, it would not be hard to emulate the syntax using modern JS methods and wrapping them in a small bit of logic in a much smaller file size than including jQuery itself.

Question is: but why? :) What you do is basically re-implemeting jQuery with an untested code which is largely an unknown quantity. Whereas jQuery has countless little snippets like "We can't cloneNode fragments that contain checked, in WebKit"[1] any "simple, quick, dirty implementation" will not have that.

It's better to use a "select number of methods from jQuery" directly from jQuery than spend any time re-implementing them anew and missing multiple details that jQuery has accumulated over the years. Even is size is an issue. If it really really is an issue, the best approach is to actually extract relevant code from jQuery and not re-implement it.

My original point was: nothing in DOM APIs matches jQuery functionality. All attempts to prove anything otherwise only reinforce my point.

[1] https://github.com/jquery/jquery/blob/master/src/manipulatio...


> You can create a JQuery object that encapsulates, say, an array. Then you can iterate with "each", you can "filter", etc.

each and filter are native functions on Array.


"each" and "filter" were used as examples of what you can do.

You don't have "on", "off" and "trigger", for example.


'each' is not. forEach is.


Or use fetch()


If you don't have VanillaJS you can get it here: http://vanilla-js.com


My problem with VanillaJS is that browser companies ship browsers with VanillaJS support already. This is a clear case of picking winners, regardless of VanillaJS's excellent benchmarks. Why should all these browsers ship with Vanilla? Why not Vue? Why not MooTools? Why not Moo.fx?


Not sure Vue falls in the same category, Vanilla lists "features" such as: "DOM (Traversal / Selectors), Prototype-based Object System, AJAX, Animations, Event System, Regular Expressions, Functions as first-class objects, Closures, Math Library, Array Library, String Library". Not "component-markup-to-JS transpilation" or SPA v-dom render loop


Maybe there should be a Vue+MooTools library called VueTools.


Like you said, VanillaJS isn't inherently faster than any of these frameworks, but the cost to the user (and the increased API surface) isn't worth that tiny improvement in code clarity.


I did not say that. VanillaJS is pretty much faster than all of those other frameworks. Can you point me to a library that has better benchmarks than VanillaJS?


Uh, inherently faster as in, there's nothing about the API design that makes it easier to optimize.


Huh, I have enjoyed this site in the past, but I forgot about the code comparisons including script tags for non-Vanilla and not for Vanilla. That seems a bit misleading. I get the extra script tag for jQuery, but the <script> { content } </script> would still be necessary for vanilla..


I looked at the page and I think the documentation is a little lacking.

I only understand what VanillaJS is supposed to do by implication, by looking at the PlainJS sight and then extrapolating that this must be competition.


I found the documentation link on VanillaJS on the bottom of the page. It seems VanillaJS is a project of Mozilla, or adopted by them. Very nice for a browser maker to spend time documenting a library so thoroughly. I would say the docs are almost better than jQuery's docs.

On the other hand, I like jQuery more for the support community :)


VanillaJS has a huge support community, it's even taught in universities.


Also I suggest they refactor the next version of VanillaJS to be less verbose. Perhaps they can get some inspiration from jQuery.


Or maybe from CoffeeScript?


jQuery has helped me tremendously in the past and continues to do so. Not everyone has to design a website like google.com and not everyone needs to take into consideration every byte that is loaded in a web page. A library that gives you a single way to do things that many browsers support in a less verbose form is just amazing tbh.

At the end of the day when you need to just get things done jQuery still shines. Does it produce spaghetti code? No, you are doing it. Does it become an enabler in spaghetti code? Yes. But not all the use cases are the same.


At my company we prefer using vanilla Javascript over all these (exhausting) frameworks! Especially many of the new features in Ecmascript 6 makes things much simpler. No more overusing bind(), template literals for building HTML and so on.

Recently I've missed the way you create DOM elements like you do with React.DOM so I created a simple proxy function like this:

let bai = {};

bai.DOM = function(){

    return new Proxy({}, {

        get: function(target, name){

            return function(args, body) {

                let newEle = document.createElement(name);

                if(args){
                    let keys = Object.keys(args);
                    for (let i = 0; i < keys.length; i++) {
                        newEle.setAttribute(keys[i], args[keys[i]]);
                    }
                }

                if(body){
                    if(typeof body === 'string'){
                        newEle.textContent = body;
                    } else {
                        newEle.appendChild(body);
                    }
                }
                return newEle;
            }
        }
    })
}();

With this you can create new DOM elements as following,

document.body.appendChild(

    bai.DOM.div(

        {"id": "message"}, 

        bai.DOM.p(null, "hello world")

    )
);


jQuery is really useful when it comes to DOM manipulation, obviously.

Without using any framework you'll find yourself iterating over NodeLists all over the place.

ie, it's much cleaner to write

$('p').css('color', 'blue');

Than

document.querySelectorAll('p').forEach(el => el.style.color = 'blue');

Also, Microsoft kinda screwed us by keeping IE 11 around until 2025.


You can create a trivial helper function such as:

    let $ = s => document.querySelectorAll(s);
And then use:

    for (let p of $('p'))
       p.style.color = 'blue';
And if you start doing anything more complex per iteration:

    $('p')
         .css('color', 'blue')
         .addClass('bla')
         .filter(function() { $(this).parent().is('article'); })
              .removeClass('qwe');
The code becomes much less magical and clearer (it's almost self explanatory):

    for (let p of $('p')) {
       p.style.color = 'blue';
       p.classList.add('ble');
       if (p.parentNode.matches('article'))
           p.classList.remove('qwe');
    }
Also much more debuggable in a debugger, and faster, as you're iterating only once and are not calling many needless functions.


Very true, nice codes :). Would be nice if we could write that without transpiling.


Code cleanliness matters more so in a compiled language. Having an interpreted language means, regardless of how long it takes you to write, everything has to be downloaded/processed on every single execution of the file.

Putting more effort into my code to remove unnecessary libraries allows the end user to load pages faster, and that's what I think matters most, because I hate having to wait, sometimes even twenty seconds for some simple pages to pass a loading screen


There is an unfortunate trend of people running down jQuery indiscriminately.

Given millions of people used jQuery for years without issue it's difficult to believe those who benefited are going to run it down publicly because they found something better.

The only people who would do this are those marketing something else. This is by far the worst part of tech forums, this kind of insidious marketing that seeks to 'force obsolence' on software and entire groups of people happily using it because some are promoting their own thing.


Or... just learn the DOM api. It is only about 2 hours of practice and study: http://prettydiff.com/guide/unrelated_dom.xhtml


jQuery is more than the DOM api.


I've found http://microjs.com/ useful quite a few times.


It took me less than 10 seconds to find an XSS on this website. Literally, the first place anybody would look worked.


This is such a great idea.

I have been a web developer for 18 years, and kicking the jQuery habit has been one of the toughest.

Frameworks also still rely on them. I'm a full time ember developer and last I checked they're trying pretty hard to drop the jQuery limitation (REALLY sorry to Ember devs if my info is outdated on this), but the ecosystem of ember/non-ember addons surrounding it will prolong things even longer I'm sure.


It is late in the day to try to replace jQuery. Does PlainJS have components? Does it have bootstrap like functionality (i.e. columns)?



It sounds like you didn't click through. This is not a framework. This is a repository of vanilla JS scripts that take the place of a lot of things that would have had a jQuery dependency in the past.


Yes, in fact it does. Components are created by `class MyEl extends HTMLElement`, and columns are included in the CSS module under the `grid` declaration.


Ironically jQuery doesn't have the things you ask for here, but plain JS indeed does (custom elements for components, CSS grid for columns).


Web Components


I'm so tired of this argument. There's no reason to drop jQuery for any of the reasons stated. Especially with modern JavaScript engines, the performance hit is negligible. Also, jQuery is especially optimized for complex DOM manipulation which Vanilla JS cannot do on its own. Sorry, but querySelectorAll is not the same as jQuery's powerful selector engine, and you can't chain thngs the same way either. Sure, it's less relevant now than it once was and for minor projects you could probably get away with a no-library approach, but who are we kidding here? Most modern web apps and sites are extremely library and framework heavy. It's complete bullshit to say otherwise. The only exception is of course for design-centric, static content web sites which tend to heavily lean on CSS for display logic. This article is just full of amateur and meaningless advice.


As someone who's written a lot of DOM code, i've tried dropping jquery (and do) but selectively. You cannot drop it completely without great pain.

It's true that the DOM interface has stabilised and is now mostly consistent cross browser, however the API is massively unwieldy in places, from excessively long method names to irritating asymmetric potholes.

TLDR; Jquery is not needed for cross browser now, it's needed to make using the DOM API not so ridiculously verbose and long winded. You need to use jQuery today because: you want your DOM code to be 1/5th the size, more legible, more debug-able.

I still use native methods where possible where there is little difference, especially when performance is a concern.


I agree jQuery isn't really needed but at the same time it's simpler for people who may not understand JavaScript fully of willing to look at boring web API docs to replicate some of the functionality.


See also https://svelte.technology/, the magical disappearing UI framework.


Can someone make a lite version of jQuery?

Angular did that.

I think Zepto was that for a while.

Isn't jQuery's lite version already there, which drops Android support etc.

Why not serve that to correct browsers?



How do I get jQ without <IE9 support?


Can't help you there specifically. However, depending on what you need from jQuery, you might consider writing your own DOM library so you can have some control over the size. If you have a look at some of the comments above, you'll see that many jQuery advantages are met with equivalent features in vanilla JS, just slightly more verbose. It isn't difficult to write a wrapper for some of the major jQuery features. That second link is a terse example of this.


Read this thread but replace every mention of jQuery with "table layouts", the parallels are striking.

jQuery has been a good friend for many years. It saved us from the drudgery of cross-browser support and gave us an enjoyable API for browser development.

Technology moves on, today's browser APIs and tooling are light years ahead of what we had 11 years. You might not need jQuery, and that's ok!


This is just a fork of http://vanilla-js.com/


I went to the site and I'm a little unclear of what its purpose is. Is it supposed to be a way to learn vanilla JS?


I mean when does it stop being "vanilla"? jQuery is written in "vanilla JS" too.


Completely counter to the author I would say everything is vanilla until you start compiling and pollyfilling. Once you start writing in idealized languages like TypeScript, CoffeeScript, or ES6 you're no longer writing vanilla JS.


I could see that, or else maybe it's not "vanilla" if you start using something like angularjs which expects to mediate basically the entire lifecycle of your application. But I think in general the concept is ill defined.


Are there any kinds of dead code elimination tools for JavaScript? If <link> tags can take additional attributes / query string parameters, the CDN be smart enough to only send down the required code.


Can you imagine any other language / ecosystem where you're encouraged NOT to use any libraries of any kind? The web is a weird place.


jQuery usually falls back to native methods if the browser supports it. Also build systems can easily remove unused code (webpack + babel-minify does great with ES6 on the whole bundle), and you can even pick and choose the exact components you need from the jQuery npm package.


the issue is that I need bootstrap which requires jquery


jQuery is here to stay. It will outlive react angular vue and whatever shiny framework you have been using.


With this article and these comments, I feel like I've been transported back in time 3-4 years.


DHTML, the framework!


who still uses jquery? to create usability mockups?


This is like asking "who still uses wordpress." Outside of the HN bubble, everyone still uses jQuery.


Even inside HN bubble people regularly drop into jQuery from inside their Reacts and Vues and Polymers. Just because it's super convenient


to do what with jQuery? It's not a good practice to mix them.


It isn't, that's true. Sometimes you need to integrate with some third-party things thoug. Ranging from ad networks to well established UI components like Select2 or DynaTables.


I'm not sure if this is a serious question or not, but about 75% of the top sites on the Internet use jQuery:

https://trends.builtwith.com/javascript/jQuery

Perhaps new projects shouldn't be using jQuery, but it's possible that some devs who just churn out code without watching the industry aren't aware of this. Increasing that awareness appears to be the point of this plainJS landing page.


>Perhaps new projects shouldn't be using jQuery, but it's possible that some devs who just churn out code without watching the industry aren't aware of this.

Or maybe those devs are watching the industry but don't care for the direction it's urging them to take, e.g. locking themselves into complex frameworks like React for simple crud pages that have the basically the same DOM each and every time they're loaded.


I'm going to shock you here, but jQuery is more popular than React. By several orders of magnitude.

https://w3techs.com/technologies/overview/javascript_library...


I will make the assertion that jQuery is only useful for lightweight DOM manipulating. Any more complex than that, one would use a JS framework to implement the client experience. In this case, you would not want to jQuery.

So essentially we are talking about server side apps that still leverages jQuery to achieve some level of dynamicity on the front-end.


I think you meant "who still starts new projects with jQuery?", and you got a bunch of replies to "who still maintains jQuery codebases?".


like, everyone.


Single reason why I should not use it?


Simple: You don't need React/Vue/Polymer for everything.

Personal anecdotal evidence: helping a friend create a very simple dashboard of running jobs returned by a REST service + stats returned by the same service etc. I've yet to find a reason to use jQuery, much less a bigger framework.


>much less a bigger framework

So do you primarily write server side web apps? Anything slightly more sophisticated on the front-end beyond imperative jQuery calls, requires a framework, to organize your logic, and to scale up to a team level where multiple devs can contribute to the same front-end codebase.


Nope. I'm a frontend developer :)

> Anything slightly more sophisticated on the front-end beyond imperative jQuery calls, requires a framework, to organize your logic, and to scale up to a team level where multiple devs can contribute to the same front-end codebase.

Yes. Often though, not a framework, but a library.


Someone on HN might make fun of you.


I think it's a pretty amusing observation about the JS dev community to see some of the responses to this here. Some people are here for Irony Club, some people have no clue there's an Irony Club meeting, and some people are opening up their jQuery wounds and bleeding all over the room.

One thing I'll say about jQuery vs doing POJS (Plain-ol' JavaScript, pronounced Poise, heh) is that jQuery comes from a world where browsers sucked and build processes for JS were virtually non-existent. The market share of sucky browsers is much smaller now, and we have sophisticated build systems for JS. All of the benefits of jQuery (normalization, removing boilerplate, etc) can be had with vanilla plugins that you can put in your project and forget about.

The lingering damage of jQuery is that we have a bunch of jQuery devs in the world now who simply cannot write JavaScript. We've got to move past that.


> We've got to move past that.

No, we've got to move past lazy generalizations.

You've boiled down multiple issues to 'people only know jQuery'. Meanwhile the rest of this thread is dealing with more interesting and accurate specifics.


I have not boiled down multiple issues to that, I'm indicating that the problem with jQuery in long-term adoption is that patterns meant to help devs avoid the untenable realm of JS yesterday keep them sheltered from good JS practice today. For that reason, we should move past jquery.


"We" should do whatever makes sense for the project at hand, be that vanilla, jquery, react, etc. There's a ton of different websites out there. jQuery might be a requirement of the codebase, or already loaded, or heavily used, etc. Or the developer might find it fastest to just drop jquery in for a simple site.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: