DOM Manipulation with put-selector

By  on  

DOM node manipulation is a big part of the web today; just look at how popular the jQuery JavaScript framework has gotten. The ability to easily work with the DOM allows us to do a lot of work in a little bit of code. Thanks to a new JavaScript module by Dojo Toolkit developer Kris Zyp, working with the DOM just got a lot more compact. With a name as short as the syntax itself, put could make you change the way you work with the DOM.

Creating DOM Nodes

Creating new nodes is just about as simple as it gets:

// Create an empty DIV
var div = put("div");

Boom, there's your new DIV element! And if you want your new code to have a few CSS classes:

// Create a DIV with some CSS classes
var div2 = put("div.classOne.classTwo");

How about creating nodes with attributes?

// Create a DIV with some CSS classes and attributes
var div3 = put("div.classOne.classTwo[title=Hover over me][style=display:inline-block]");

The syntax for inserting the DOM node is a bit different because the parent then becomes the first argument in the put signature:

// Create an INPUT with an ID and an attribute, place it into the body
// The body text goes into the third argument;  not(!) innerHTML, just text
var div4 = put(document.body, "input[type=text]#myInput", "This is inner html");

Manipulating Existing DOM Nodes

Manipulating DOM nodes is actually very much like creating the nodes themselves:

var myInput = document.getElementById("myInput");
put(myInput, ".anotherClass");

// Add CSS classes attributes to the element
put(myInput, "[placeholder=first name][required=true][title=first name element].yetAnotherClass");

Just remove the tagName and you can modify the node.

Node, Class, and Attribute Deletion

The "!" character is meaningful in that it represents deletion within put. Let's remove a few classes and attributes from a given node, then let's remove the node itself:

// Remove a CSS class from the INPUT element
put(myInput, "!anotherClass");

// Remove attributes from the INPUT element
put(myInput, "[!required][!title]");

// Delete a node!
put(myInput, "!");

The syntax for deletion is short but sweet. The only criticism I have is that if this could create a maintenance problem if developers are not experience with put.

Creating and Managing Child Nodes

Creating childNodes for an existing node is another functionality made easier by put:

// Create a base node so we can add nodes around it
var baseNode = put(document.body, "div#baseNode");

// Add two DIVs *after* the baseNode
put(baseNode, "+div +div");

// Add a SPAN element *before* the baseNode
put(baseNode, "-span");

// Create the parent list element 
var ul = put(document.body, "ul");

// Create a child list item
var firstItem = put(ul, "li");

Moving and ReParenting Nodes

Reparenting and moving elements within the DOM is another basic task that, when you use JavaScript's native functions, takes far too much code. Let's have a look at moving nodes around with put:

// Move one node to another parent
// parent > child
put(ul, ">", firstItem);

// Put one element after the first
put(div1, "+", div2);

A simple series of symbols designates where within the node try an element should go!

More Traditional Node Property Management

For those who prefer a more verbose element creation syntax, put-selector provides that as well:

var span = put(parent, "span", {
	title: "Hover over me!",
	style: "font-style: italic;"
});

Kris' tool is great in that it's ultra-efficient, modular, and easy to learn. On the other side, it's possible that the syntax may be a bit too compact for persons try to maintain an application that they didn't write. What do you think of put? An easy to use utility or a "simple but complicated" resource? If I'm honest, I'm teetering on the fence -- maybe you can convince me?

Recent Features

  • By
    7 Essential JavaScript Functions

    I remember the early days of JavaScript where you needed a simple function for just about everything because the browser vendors implemented features differently, and not just edge features, basic features, like addEventListener and attachEvent.  Times have changed but there are still a few functions each developer should...

  • By
    CSS @supports

    Feature detection via JavaScript is a client side best practice and for all the right reasons, but unfortunately that same functionality hasn't been available within CSS.  What we end up doing is repeating the same properties multiple times with each browser prefix.  Yuck.  Another thing we...

Incredible Demos

  • By
    Get Slick with MooTools Kwicks

    When I first saw MooTools graphical navigation, I was impressed. I thought it was a very simple yet creative way of using Flash. When I right-clicked and saw that it was JavaScript, I was floored. How could they achieve such...

  • By
    Hot Effect: MooTools Drag Opacity

    As you should already know, the best visual features of a website are usually held within the most subtle of details. One simple trick that usually makes a big different is the use of opacity and fading. Another awesome MooTools functionality is...

Discussion

  1. Sam

    I’m all for improving DOM manipulation but I think in the interest of brevity there’s been a loss of clarity and intent.

    “put” to me implies that you are *actually* doing something, you are “putting” something somewhere.

    With only 1 parameter you aren’t putting anything, just creating something… only with 2 parameters are you setting something… or in some cases removing something… or even deleting something – wait… WTF?!

    We’ve just entered serious API FAILure as S.R.P. has gone out the window – big mistake.

    You’d be much, much better off with clear, simple, concise method names that actually explain what you are doing.

    var foo = make("div");
    set(parentNode, "li");
    

    etc…

    • definite +1 here. I think you are just losing too much of what you are trying to accomplish. Developing with modules takes a fine line IMHO because you do run the risk of others not knowing what you are/were trying to accomplish

    • I see what you both mean, and felt the same way you did initially. I eventually came around to appreciating its simplicity.

      I agree that “put” may not be the best name but since it’s just module, you can call it whatever you’d like. “make” and “set” are too simplistic, IMO. Maybe “DOM” would be better.

      Thanks for the input!

  2. Trevor

    I’m 100% dead-set against this kind of API… this is like using a Map for everything in a static typed language.

    But I also wanted to note that you’ve called it “put-selector” I’m not sure that “selector” has anything to do with this…. in fact I don’t see a single “get” usage in here (outside of native DOM API) and thus there is no “selectors” being used.

    IMHO its time to scrap this and head back to the drawing board.

    • Kris Zyp named it “put-selector”; this is not my creation.

  3. Readability naturally has a strong subjective element to it, and generally any new approach is going to be initially less readable due to relearning. However, some attempts at an objective defense of the (long-term) readability: It uses a syntax, CSS selectors, that is consistent with the syntax we use to query/retrieve elements, both in CSS and in JS query selectors. This means that the same syntax can be used to create an element and then later retrieve or style that element. Brevity is not the enemy of readability, in fact brevity benefits readability since it does not require as much visual bandwidth and mental parsing. Of course one can use techniques to achieve brevity that obscure meaning and thus reduce readability, but that isn’t due to brevity, and of course I don’t believe CSS selectors obscure meaning.

    Now the removal syntax doesn’t have a precedence in CSS standards, and could be seen as more obscure. However, I have found that using this library is just so enjoyable, fast, and addictive that being able to include removal in the supported functions provided a satisfyingly complete set of DOM functionality. The more I use this, the more I never want to go back to long clunky complex DOM apis (even with the help of libraries), just as I don’t ever want to go back to querying for elements by using separate functions for each type of query.

    As far as the name, it is called put-selector because it uses CSS selector syntax (that’s the distinguishing design point). It doesn’t query, that’s why it is called put-selector as opposed to query-selector. As far as the choosing “put” over other verbs, it is difficult to come up with a name that is sufficiently generic.

    Of course, this is all highly subjective, I certainly don’t think I am going to change anyone’s opinion. There are plenty of people on both sides of the fence on this library, so I suppose it does really come down to personal taste.

  4. Mark

    Joining the conversation a little late… but I want to add my two cents for anyone else reading this in the future.

    I’ve been playing with this a little for the last few months. Mostly I was “meh”, jquery was good enough, and I had some of the legibility issues people complain about.

    But recently I had to clean our legacy code all sorts of script injection due to building html from html fragments and string concatenation. Now I __LOVE__ the put selector, because it’s basically immune to
    this problem.

    Jquery has .html() and $(htmlfragment) which make it very easy to accidently pass “text” as html. I had a lot legacy code where people were generated bits of html by going
    obj.html(”+unsafeUserContent+”);
    even new code where devs are warned to be careful this shows up sometimes, jquery is unsafe by default.

    put-selector on the other hand is SAFE BY DEFAULT.
    put('span#user-comment',unsafeUserContent)
    

    escapes correctly.

    About the only dangerous thing I’ve come accros is:

    var dangerousContent='alert("Uh-oh")';
    put(document.body,'div#user-comment[onclick=$] $', dangerousContent, 'Click me')
    

    But the “on*” should never be added this should never be done, so it’s relatively easy for us to do code scans (even automated ones) for this mistake.

    As for the brevity issues, I’ve found that like most languages you just need to find the appropriate balance between brevity and legibility. You can use the “put-selector” one item at a time just like direct dom manipulation.

    Finally, while cleaning up legacy code, I’m finding I really hate jquerys wrappers: get a large enough system it gets hard to figure out what is supposed to be what, I appreciate that put-selector uses standard dom elements.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!