13 ms·
HTML.js – Befriend the DOM
- dccoolgai 13y agoSo I guess I'll be the first to ask the obvious question. How is this different or better than jQuery?
- CmonDev 13y agoThere is a small FAQ in the bottom.
- jhh 13y ago"Not so much. This doesn't wrap or hide the DOM for you. It exposes and enhances it, making it your ally instead of trying to protect you from it. Old IE versions are fading; it's time to go native!" This seems like a pretty poetic way of describing differences between software packages. And I mean that in a non-charming way.
- dccoolgai 13y agoI red the faq... didn't really answer my question... from the examples I saw, there was nothing there that ouldn't be achieved with JQ...which is why I brought it here...thought maybe I was missing something.
- smanuel 13y agoWell... everything could be achieved with JQ. Usually with 1 line of code. But that library is 2.7k and you're working directly with the DOM elements and not with wrappers. So I guess it could come handy for smaller projects where you wouldn't need the full JQ power and 10 JQ widgets.
- grey-area 13y agoIt doesn't wrap and extend dom elements, just finds them, so there's no $(this) etc just to be sure all your objects behave the same way, no .attr('id') to get attributes etc. It also has a nicer syntax I think, like the idea of doing HTML.body.ul.li.a So it looks interesting, though I wish they had included Ajax. This doesn't do everything jquery does, and is not intended as a drop-in replacement, more as a different way of doing things which is simpler, smaller and more intuitive.
- maxhowell 13y agoWhat does Hacker News recommend as a standalone AJAX solution nowadays?
- grey-area 13y agoNot sure if it is a complete replacement, but I needed to remove a dependency on jquery recently and used this code: https://github.com/inkling/backbone.native/blob/master/backbone.native.js https://github.com/inkling/backbone.native/blob/master/backb... The $.ajax function was all I needed.
- jonahx 13y agoJust using the native XMLHttpRequest has pretty good support: http://en.wikipedia.org/wiki/XMLHttpRequest#History_and_support http://en.wikipedia.org/wiki/XMLHttpRequest#History_and_supp...
- jenius 13y agoI've used superagent (https://github.com/visionmedia/superagent https://github.com/visionmedia/superagent) a number of times and it's wonderful, but beware if you're trying to make it work with old IE.
- prezjordan 13y agoGeez, has he made everything?
- phpnode 13y agoyes, he has. as has substack. basically everything. but part of the reason they are so prolific is that they focus on very small, single use modules that do one thing well. So they have hundreds of repos, but many of them are 10 - 15 lines of code.
- prezjordan 13y ago
- CmonDev 13y agoShould be called DOM(.js) instead.
- martin-adams 13y agoMaybe, but the notation is in the context of HTML rather than a DOM Model. It would seem weird to have a DOM.js have it's root library referenced as HTML. DOM.body.div doesn't quite seem as nice to me.
- catmanjan 13y agoHTML.find("#element") is longer than $("#element") so I doubt it'll catch on
- hawleyal 13y agoWow, what an in-depth comparison with JQuery.
- deleted 13y ago[deleted]
- casiotone 13y agovar $ = HTML.find.bind(HTML); Enjoy.
- ianstormtaylor 13y agoBetter yet: var $ = require('HTML');
- deleted 13y ago[deleted]
- pothibo 13y agoDoes the DOM Traversal performance issue has been solved from voyeur.js? (library this is forked from has documented performance hit: https://github.com/dunxrion/voyeur.js/issues/20 https://github.com/dunxrion/voyeur.js/issues/20)
- adamb_ 13y agoThanks for including a link to this issue... Without it I would have assumed the was just a needless fork of Voyeur.js
- pothibo 13y agoActually, I'm not certain of what are the differences between the two. Maybe OP can explain.
- nadabu 13y agoYes, the performance has been fixed. Further improvements are possible (prototype extension), but come with tradeoffs so i'm hesitant. Apart from the dot-traversal technique (both fixed and enhanced), everything is different in HTML (see the FAQ): each(), only(), extensibility, emmet abbreviations, and the upcoming event support.
- halisaurus 13y agoAt first glance, this does seem a little lighter and more elegant for light projects than jQuery. I do see the chains could get long, but they might well match CSS selector chains I already wrote, so it's type-heavy but not brain-heavy. It's also such a light file that I might prefer it on a one-pager if the interactions are few and simple. That said, any jQuery plugin is lost with this option, so if have to decide against using any/all before I begin and if the possibility exists I'd probably err on the jQuery side.
- grey-area 13y agoDownload link is currently broken, it should be: https://rawgithub.com/nbubna/HTML/master/dist/HTML.min.js.gz https://rawgithub.com/nbubna/HTML/master/dist/HTML.min.js.gz To those asking why you'd use this in place of jquery, the only reasons to use it are that it is smaller, vastly simpler, and yet does the things which many people use jquery for with a neat syntax. One of the main attractions for me is that it seems to get out of the way far more than jquery - elements aren't wrapped, behaviour is as you'd expect from the DOM, so you don't have to learn a new API just to manipulate objects in the way that you do with jquery. Re speed issues, if you're using this enough or on documents where speed of selection is an issue, you could simply optimise the particular selector and just use the DOM to get a speed bump. I've not often seen a case in real-life where this matters though, does anyone have any examples we could look at? If you want to use jquery plugins, cater for IE < 9, or use things like jquery animations or UI obviously you wouldn't want to switch.
- magoon 13y agoNeat idea, but you're going to have to refactor many lines of code each time you wrap elements in a new parent element. In other words, this is a ball & chain for your markup.
- grey-area 13y agoIn what way is this different from jquery? You can do this too: HTML.find('body section .identity') which is just like jquery's $('body section .identity') and both depend on the structure of your document, so if the doc changes, the code must change.
- magoon 13y agoI thought the whole point was to be able to access a DOM element hierarchy as an object hierarchy? My point is that this convenience comes at a cost, and so I would also not use jQuery in that way. Conservative targeting of selectors negates the very cool benefits of this library, at least for my use.
- janjongboom 13y agoWhich is just like `document.querySelectorAll('body section .identity')` which also works in IE8+, FF, Chrome.
- grey-area 13y agoI think it passes through to that with the find method, so yes, exactly like that. Whatever you use to query though, if you use CSS selectors, your code will be dependent on the structure of the HTML document. You can't really escape that if you're using the DOM, and I don't see why any of these methods is any different in that regard. So it's the same as jquery in that sense.
- camus 13y agoOn how much browsers has this stuff been tested ? because that's the point of jQuery , you can trash it all you want jQuery has been battle tested on a large number of browsers and plateforms. Other DOM frameworks not so much, that's why they fail.
- bachback 13y agothe very point of this is to lose some the old painful browsers (IE6/7/8) to make code much better. almost all work in cross-browser stuff is IE6-8. think of jQuery mainly as a bugfix for old IE's.
- esailija 13y agoThat is a really gross exaggeration. jQuery only lost 10% of its size on full builds when it eliminated IE6-8. There is still plenty of stuff left to handle. Naive code that only handles common success case is of course going to be small. Even if the modern browsers didn't have bugs and behaved exactly the same, you would still have most of the stuff there. jQuery features amazing event model with endless corner cases and optimizations* handled, powerful ajax library (Think of stuff like prefilters and transports) and so on. * For example your typical delegation implementation traverses the propagation path over and over again for each handler, while probably not even checking for simple selectors.
- wingspan 13y agoI don't think this is true: "jQuery Core has more lines of fixes and patches for WebKit than any other browser." [1] [1] http://blog.methvin.com/2013/02/tragedy-of-webkit-commons.html http://blog.methvin.com/2013/02/tragedy-of-webkit-commons.ht...
- grey-area 13y agoThere is a test suite, you could easily test it yourself by downloading: https://github.com/nbubna/HTML/tree/master/test https://github.com/nbubna/HTML/tree/master/test Looks like it passes on the latest FF and Safari, though I saw a couple of fails on the latest Chrome. Haven't tried IE, and it definitely won't work on older IE.
- bachback 13y agogreat idea. there is so much in jquery, which we can lose. having thin layers on top of the standards is the way to go. what about events?
- nadabu 13y agoThat is the question: https://github.com/nbubna/HTML/issues/1 https://github.com/nbubna/HTML/issues/1
- lhorie 13y ago2 thoughts of the top of my head: 1 - is there no equivalent for .closest()? Traversal from relative paths is kind of a big deal for a jQuery-like tool 2 - what is the type of `HTML.body.div`? HTMLDivElement or Array? If it depends on your markup, then that's a recipe for easy breakage
- emn13 13y agoYeah, this api is totally borked - they should always be returning a conceptual set, regardless of its cardinality.
- nadabu 13y agoIf you don't know, use each() and only() to act on the results. They're always available and don't care if it is an element or array of elements.
- lhorie 13y ago2 more thoughts :) 1 - you cannot be sure that return types will not change in the future (e.g. markup changes in maintenance phase), especially in large projects with lots of devs, hence my comment about brittleness. 2 - each() is verbose and encourages procedural style, which can cause redraw performance hits (i.e. someElements.readDOM().writeDOM() redraws much faster than someElements.each(function(el) {el.readDOM().writeDOM()}) since the browser's engine doesn't need to recalculate layout at every iteration re: closest() - I've seen people do things like $("li ul").closest("li").addClass("has-children") for things like dynamic expandable tree initialization. Granted, it's not a very common use case though.
- nadabu 13y ago1) i can reliably assume HTML.find('#foo') is a node, and HTML.find('.foo') must use each(). These things get even easier as web components and shadow DOM become widely available. I'm aiming at the future here, not the past. 2) elements.each('readDom').each('writeDom', 'value') 3) HTML.find('li ul').each('parentNode.classList.add', 'has-children')
- deleted 13y ago
- sequoia 13y agoIf you are making another dom traversal library, you must (imho): * Explain why someone should use it over the standard: jQuery * Clearly explain the stance toward browser compatibility (not hand-waving & "oh who uses ie8 anyway?") * Come up with something better than "It's smaller than jQuery!" Without these points hit I don't even bother looking at DOM library. :/
- rquantz 13y agoNot to say that their argument is sufficient to abandon jQuery, but it looks like what they're offering is working directly with the DOM, instead of jQuery's wrapper. Again, I can't say I'm convinced, but at the same time, at some point, won't it be time to move to the native DOM? jQuery itself is abandoning support for old IEs, and once that happens (are they really going to still be supporting 1.9 in five years?) then the main reason to use jQuery, cross browser compatibility, will be gone, and it will be time to reassess what should be the standard JS standard library. Edit: on the other hand, I feel like DOM traversal is becoming a smaller and smaller part of the JS I write. Maybe we'll find in five years that we don't need a DOM wrapper at all.
- reflectiv 13y agoThis isn't letting you work with the DOM directly...it is yet another library which encompasses the DOM API...just like jQuery. It only feels a bit more natural since the style it uses feels more direct...this is just another javascript wrapper for the DOM...a problem we (basically) solved with jQuery. I also find myself rarely using jQuery for much these days when I use various MV* javascript libraries. This library looks neat, but I don't need to replace a library I use less and less...and has no real benefits other than size and API differences (that can basically be mapped to each other 1:1).
- nadabu 13y agoEh, not a wrapper, sorry. It's a helper that directly extends the DOM to provide syntax sugar. Yes, it is not pure DOM interface, but if it were, then the library would be a whopping 0KB. :)
- hk__2 13y agoPlease stop the demo if I start typing something in the box.
- nadabu 13y agoGood idea! I'll do that.
- SapphireSun 13y agoAlso, the flash on the left hand side occurs too quickly. If I pay attention to it, then I can't read the code. If I read the code, I can't look at the flash. Pretty slick though. :)
- h3ll0w0rld 13y agoyass.js ftw - http://yass.webo.in/ http://yass.webo.in/
- adregan 13y agoForgive me for my naiveté, but as this library is so small and limited (in focus) and seems to not worry with older browsers, why not use plain old JavaScript? EDIT: I should add—I am legitimately curious. I've only been learning plain JS for the last few months, and I'm wondering what pitfalls I might uncover.
- nadabu 13y agoBy all means, use the plain old DOM interface! That's kinda the point i'm driving at with this library. We don't really need jQuery anymore (at least not all of it). Small components like HTML.js can still be handy when you want a little sugar to save some typing though. :)
- nadabu 13y agoI appreciate all the attention. Just FYI, i was not ready to start publicizing this, someone randomly found it and started that ball rolling without me. There are a bunch of changes in the pipeline for the near future. (see the github source for what's happening)
- prezjordan 13y agoPretty cool, but please rethink using that example :) It's a little slow and doesn't immediately show off your hard work. A few (static) independent sections would do a much better job of promoting yourself.
- nadabu 13y agoThose are below the jump. I've not had time to polish that demo further. The library went viral a bit earlier than i'd hoped. Work is in progress.
- jdonaldson 13y agoDid the author ever look at d3? It seems to offer the same thing, with the added benefit of being able to bind data to the dom elements. http://d3js.org/ http://d3js.org/
- indubitably 13y agoThis is a very different API from d3’s.
- jdonaldson 13y agoNot really. HTML.find('#empty li').only(function(el, i) { return i % 2; }).each('className','odd') d3.selectAll("#empty li').filter(function(x,i) { return i %2; }).attr("class", "odd")
- jayferd 13y agoIf multiple elements of the same tag exist, a proper array of elements is returned otherwise an Element is returned. STAHP. Please don't make the type of the return value dependent on runtime state. This is exactly why jQuery created its own array-like wrapper (which subclasses Array, fwiw).
- nadabu 13y agoIn cases where the return value type is actually unknowable, you can reliably use each() on the results. The whole point here is to use the DOM, not a wrapper. I'm open to pull requests if you have a way to have consistent interface and return types without a wrapper.
- jayferd 13y agoI'm not sure what you mean by "cases where the return value type is actually unknowable". Does that mean you only return an Element when it's something for which there can be only one on the page (like document.body)? As far as APIs go, one way would just be to return a list always. The DOM, afaik, returns a special NodeList thing that isn't even an array. ( https://developer.mozilla.org/en-US/docs/Web/API/NodeList?redirectlocale=en-US&redirectslug=DOM%2FNodeList https://developer.mozilla.org/en-US/docs/Web/API/NodeList?re... ). What's the actual issue with using wrappers?
- nadabu 13y agoWrappers actually have their share of subtle problems, we've just gotten used to the jQuery way of coping. Hmm, i sense another blog post coming... :) At root, the issue is that without widely available Proxy implementations (wildcard property intercept), wrappers must duplicate the entire underlying (and widely varying) API of the wrapped elements. You could do this by slavishly copying the DOM or by creating an entirely separate API (like jQuery). Back when the DOM was a mess (3-4 years ago), the wrapper was the only sane approach (witness jQuery crushing Prototype). I'd argue things have changed: https://github.com/nbubna/mind-hacking/blob/gh-pages/extending-the-dom.md https://github.com/nbubna/mind-hacking/blob/gh-pages/extendi... Returning a list for all operations is returning a wrapper, not the path i'm on. I would never argue that variable return types is ideal, but i currently prefer its problems to the problem introduced by using a wrapper API. :)
- badclient 13y agoBoo at naming libraries by adding .js to otherwise common names. It risks making library building kind of a domain name-like landgrab.
- itsbits 13y agofor a second i thought this came up with direct DOM approach...but i found this is just another Jquery type library with different syntax...In this case, good job but i am happy with Jquery or Zepto..
- Tloewald 13y agoI'm curious as to why HTML.ify is necessary. Shouldn't HTML itself be a function? If passed a string it then that's HTML.find and if passed a dom node or one of the weird collections of DOM nodes the native APIs provide then it HTML.ify's them. I like the idea if not so much the execution. It needs a partner for smoothing over event handling.
- nadabu 13y agoEvent handling is in the works, either bundled or separate: https://github.com/nbubna/HTML/issues/1 https://github.com/nbubna/HTML/issues/1 HTML is the root element (<html>), so it cannot be a function. HTML.ify() is only needed if you have a different library/interface that hands you an element, not retrieved via find() or dot-traversal.
- psychometry 13y agoReminds me of zen-coding: https://code.google.com/p/zen-coding/ https://code.google.com/p/zen-coding/ zen-coding is designed for use in a text editor, though, and is a quick way of generating a ton of properly-indented, well-formed HTML.
- SimHacker 13y agoReminds me of the regrettable mistake that was E4X. I used it when developing TomTom Home on xulrunner, and its helpful "blurring" of XML and XMLList was no help at all, a misguided attempt to oversimplify something that just ain't that simple. I couldn't believe they designed it that way on purpose. It made JavaScript seem more like PHP. http://www.morearty.com/blog/2007/03/13/common-e4x-pitfalls/ http://www.morearty.com/blog/2007/03/13/common-e4x-pitfalls/ 5. E4X intentionally blurs the distinction between XML and XMLList When you begin to learn E4X, you learn that there are two main data types, XML and XMLList. That seems simple enough. But then after a while, you start to notice places where it seems like the “wrong” type is being used, or where impossible things are happening. var mydocument = <root> <rabbit name="Brownster Johansson McGee" /> </root>; // 'mydocument.rabbit' means to get a list of ALL <rabbit> // nodes, so myPetRabbit must be an XMLList, right? But // I'll call my variable 'myPetRabbit', not 'myPetRabbits', // because I happen to know that I have only one pet // rabbit. var myPetRabbit:XMLList = mydocument.rabbit; // What's her name? Hey wait a minute, "her" name? // Why does this next line work? Isn't myPetRabbit an XMLList? // What does it mean to get an attribute of a list?? trace(myPetRabbit.@name); The reason this works is that E4X intentionally blurs the distinction between XML and XMLList. Any XMLList that contains exactly one element can be treated as if it were an XML. (Furthermore, in this example, even if ‘myPetRabbit’ held a list of more than one node, myPetRabbit.@name is still a legal expression; it simply returns a list of all “name” attribute nodes of all of those elements.) In fact, if you search the E4X spec (PDF) for “blur”, you will find 15 usages of the phrase “… intentionally blurs the distinction between….” For example, another place where this blurring is evident is in the behavior of XMLList.toString(). As the Flex docs say: If the XML object has simple content, toString() returns the string contents of the XML object with the following stripped out: the start tag, attributes, namespace declarations, and end tag. If the XML object has complex content, toString() returns an XML encoded string representing the entire XML object, including the start tag, attributes, namespace declarations, and end tag. So if an XMLList contains <node>hello</node>, then toString() will return "hello"; but if the list contains <node>hello</node><node>goodbye</node>, then toString() will return "<node>hello</node><node>goodbye</node>" (not "hellogoodbye"). Presumably this decision was made in an effort to achieve “do what I mean” behavior, where the output would match what developers most often intended; but personally I find it a little confusing. If you really need the full XML version of an XMLList that contains simple content, use toXMLString() instead of toString().
- joesb 13y agoLooks like someone rediscovers Prototype.js. jQuery does not extends DOM because it does not work. Library before jQuery choose extending the DOM approach and chaos happens, that's why jQuery got popular. In the end the author said "DOM extension is no longer to be feared". So what's the argument when you read the linked article? "Just choose non-conflicting name!" Really? That's your suggestion?