How I know I need to take a break



  • I just wrote this:

    onclick="this.parentNode.parentNode.parentNode.parentNode.deleteRow(this.parentNode.parentNode.rowIndex);"
    


  • Why on earth don't you use a framework like jQuery or Prototype?



  • @bezking said:

    I just wrote this:

    onclick="this.parentNode.parentNode.parentNode.parentNode.deleteRow(this.parentNode.parentNode.rowIndex);"
    

    Whoa, this has got to violate the Grandfather Paradox somehow.



  • I feel your pain. "Proper" OO design techniques (note that I don't imply "well-executed", at least in my case) bumping up against the real world data usage. When your design documents have a family tree in them, look out!



  • @RichP said:

    I feel your pain. "Proper" OO design techniques (note that I don't imply "well-executed", at least in my case) bumping up against the real world data usage. When your design documents have a family tree in them, look out!
    Seeing as this is HTML, I don't think he has much choice in the matter.

    Other than using JQuery, the lack of which is TRWTF*.

     

    *As pointed out by RHWyden



  • @hoodaticus said:

    Other than using JQuery, which is TRWTF*.

    FTFY.



  • @kilroo said:

    @hoodaticus said:
    Other than using JQuery, which is TRWTF*.

    FTFY.

    Wouldst thou be so kind as to enlighten us as to why this particular framework fails to meet thine standards, o wise one?



    Or do I have to file this under "unsubstantiated trollcrap"?


  • ♿ (Parody)

    @Rhywden said:

    @kilroo said:
    @hoodaticus said:
    Other than using JQuery, which is TRWTF*.

    FTFY.

    Wouldst thou be so kind as to enlighten us as to why this particular framework fails to meet thine standards, o wise one?



    Or do I have to file this under "unsubstantiated trollcrap"?


    I thought it made as much sense as your advocacy, personally.



  • @boomzilla said:

    I thought it made as much sense as your advocacy, personally.

    This is what I wrote: "Why on earth don't you use a framework like jQuery or Prototype?"

    Notice the "like"? Do I now need to mention each and every framework out there? Those were the two which I remembered from top of my head. I know there's also YUI, MooTools, ExtJS and others I'd probably need to google for in order to remember them.

    So, take your comment and shove it. And next time, read the thread first.



    There's a reason those frameworks exist. They make traversal and manipulation of the DOM much easier and the code much more readable.


  • ♿ (Parody)

    @Rhywden said:

    So, take your comment and shove it. And next time, read the thread first.

    I did read the thread, so fuck off. How else would I have known about your original comment? How about reading the comment before you reply to it?

    @Rhywden said:

    There's a reason those frameworks exist. They make traversal and manipulation of the DOM much easier and the code much more readable.

    Ah, now some substantiation (hey, you're the one who brought it up)! So, as I said, since I don't generally do anything with javascript, and definitely nothing that would require a framework, what might an equivalent jQuery or Prototype statement look like?



  • @boomzilla said:

    Ah, now some substantiation (hey, you're the one who brought it up)! So, as I said, since I don't generally do anything with javascript, and definitely nothing that would require a framework, what might an equivalent jQuery or Prototype statement look like?

    Depends on what he actually wants to do. Seems as if he wants to remove a row if someone clicks on something inside said row.

    Using jQuery, you'd firstly design your table to look like this:



    <table>

    <tr>

       <td>Some data</td><td><a class="delete_row">Delete this row</a></td>

    </tr>
      .... more of the same structure here ...

    </table>
     

    Then you could write a simple Javascript routine like this:
     

    $(".delete_row").click(function() {

      $(this).closest("tr").remove();

    }



    Which would apply the function's click action to every object which carries the "delete_row"-class. Using the OP's "onclick"-Method, you'd have to copy&paste that one into every single row of the table. Said function then takes the event's target (in this case the hyperlink) as a source and then propagates upwards (using the closest()-function) until it finds the first hit (in this case the <tr>-tag) and removes it and its children out of the DOM completely.

    The advantage becomes more apparent the more complicated your document's structure is.


  • ♿ (Parody)

    @Rhywden said:

    Which would apply the function's click action to every object which carries the "delete_row"-class.

    That's interesting (to someone who's never needed to do anything like that, anyways). Though actually, I wouldn't be too surprised to find out that the OP actually was using something similar in his project, which would only emphasize that he really needed that break.



  • @boomzilla said:

    @Rhywden said:
    Which would apply the function's click action to every object which carries the "delete_row"-class.

    That's interesting (to someone who's never needed to do anything like that, anyways). Though actually, I wouldn't be too surprised to find out that the OP actually was using something similar in his project, which would only emphasize that he really needed that break.


    What I forgot: My approach works always, no matter what you're doing to the contents inside the table (okay, unless they're nesting a table inside a table - but that should land them in the 6th circle of Hell anyway).

    His approach breaks as soon as his action-tags become more nested (thus moving down one level in the DOM) or less nested (thus moving up one level). Which means that rewriting the design also requires a rewrite of the code.

    Maybe less dependency between code and design is a better argument, yes? :)



  • xpath would be a bit cleaner, but not  less typing.



  • @Rhywden said:

    What I forgot: My approach works always, no matter what you're doing to the contents inside the table (okay, unless they're nesting a table inside a table - but that should land them in the 6th circle of Hell anyway).

    His approach breaks as soon as his action-tags become more nested (thus moving down one level in the DOM) or less nested (thus moving up one level). Which means that rewriting the design also requires a rewrite of the code.

    Maybe less dependency between code and design is a better argument, yes? :)

    You're still potentially binding a ton of separate event handlers and you have to take care that they're also bound to the delete action whenever a fresh row is added. Better to solve both problems at once by tapping into more of the framework's power and using delegated events:

    <table id="datatable">
      <tr>
        <td>...</td>
        <td>...</td>
        <td><input value="delete" class="action-delete" type="button"></td>
      </tr>
    </table>
    
    <script>
      $( document ).ready( function() {
        $( "#datatable" ).delegate( ".action-delete", "click", function( event ) {
          event.preventDefault();
          $( this ).closest( "tr" ).remove();
        });
      });
    </script>
    

    Imho this nicely illustrates why frameworks like jQuery are practically a necessity if you want to produce well-written, well-behaving, and efficient JavaScript DOM manipulation code. Writing the equivalent in the raw DOM API is nowhere near as readable or maintainable.



  • Makes sense. Thanks, you learn something new every day ;)



  •  We are using YUI - and unless you use their shitty datatable control there is no support for HTML table manipulation as far as I can tell. So, in order to make it work, we end up with this. Coincidentally, it takes about 6 lines to make an async AJAX call, which you can do with one line of jQuery.



  • @Ragnax said:

    @Rhywden said:
    What I forgot: My approach works always, no matter what you're doing to the contents inside the table (okay, unless they're nesting a table inside a table - but that should land them in the 6th circle of Hell anyway).

    His approach breaks as soon as his action-tags become more nested (thus moving down one level in the DOM) or less nested (thus moving up one level). Which means that rewriting the design also requires a rewrite of the code.

    Maybe less dependency between code and design is a better argument, yes? :)

    You're still potentially binding a ton of separate event handlers and you have to take care that they're also bound to the delete action whenever a fresh row is added. Better to solve both problems at once by tapping into more of the framework's power and using delegated events:

    <table id="datatable">
      <tr>
        <td>...</td>
        <td>...</td>
        <td><input value="delete" class="action-delete" type="button"></td>
      </tr>
    </table>
    
    <script>
      $( document ).ready( function() {
        $( "#datatable" ).delegate( ".action-delete", "click", function( event ) {
          event.preventDefault();
          $( this ).closest( "tr" ).remove();
        });
      });
    </script>
    

    Imho this nicely illustrates why frameworks like jQuery are practically a necessity if you want to produce well-written, well-behaving, and efficient JavaScript DOM manipulation code. Writing the equivalent in the raw DOM API is nowhere near as readable or maintainable.

    This also illustrates one of my biggest problems with jQuery, which is not so much a problem with the framework itself as it is a problem with its effect on people who learn jQuery instead of javascript...especially those who haven't bothered to learn any new features since 1.4.1. It's so darn easy to use $(selector).click() that .delegate gets overlooked a lot.

    The jQuery documentation is good enough, and they've introduced enough features I like in the last .3 versions or so, that the only objection I have to the framework itself is that I personally prefer choosing my tools per need over having one package provide me with everything it thinks I'll ever need (for example, .delegate and sizzle are okay, but I personally like NWMatcher and NWEvents better). But I still think of it as the PHP or VB (both of which I use, by the way, because they're what get me paid) of the Javascript world in terms of the stereotype resulting from its low barrier to entry.

    That said, jQuery has progressed to the point now where if I were working on web projects again, I might pick it over whatever combination of more specialized libraries I might otherwise use just because of how many visitors would probably already have the latest google cdn version in cache.



  • Oh, and by the way...maintainability I'll readily grant, because you don't have to maintain your own home-rolled library for things like event management and .closest and .remove...but if one were doing this without the benefit of a prebuilt library (or a framework, if I have to settle for one), it wouldn't necessarily turn out much less readable, if at all. At least, if one bothered to refactor it. Shoot, I actually wrote something remarkably similar several years ago that was arguably more readable...not to be conflated with good or maintainable. If I remember correctly, it used DOM 0 events. Which is both why it might have been more readable, and the main reason it was less maintainable. As soon as we needed two events delegated to the same parent it would have gotten ugly.



  • @Ragnax said:

    You're still potentially binding a ton of separate event handlers and you have to take care that they're also bound to the delete action whenever a fresh row is added. Better to solve both problems at once by tapping into more of the framework's power and using delegated events:

    <table id="datatable">
      <tr>
        <td>...</td>
        <td>...</td>
        <td><input value="delete" class="action-delete" type="button"></td>
      </tr>
    </table>
    
    <script>
      $( document ).ready( function() {
        $( "#datatable" ).delegate( ".action-delete", "click", function( event ) {
          event.preventDefault();
          $( this ).closest( "tr" ).remove();
        });
      });
    </script>
    

    Imho this nicely illustrates why frameworks like jQuery are practically a necessity if you want to produce well-written, well-behaving, and efficient JavaScript DOM manipulation code. Writing the equivalent in the raw DOM API is nowhere near as readable or maintainable.

    Thanks for the tip on .delegate; never knew it was there, or if I did, I never gave it any thought. But, it definitely sounds a lot cleaner than my current paradigm:

    function doSomething() {
        $(this).hide().show().whatever();
    }
    
    $('div', '#my-parent').click(doSomething);
    
    $('<div>≪/div>').click(doSomething).appendTo('#my-parent');
    

    Granted, that may not be the best example, but I think it demonstrates my point. I think that I will have to give the .delegate a whirl from now on, as I'd prefer not to write random functions and then pass them as callbacks. It tends to get messier as you go.

    As for the argument about depending on .click() and friends, I'm not typically a front-end guy, and only write Javascript (jQuery) on rare occasions. As such, I don't usually spend too much time in the docs, unless I have a specific problem and need a reference. Thankfully jQuery is so easy to learn, you don't have to memorize the entire API (which can be good, and bad).



  •  You do realize that you can use anonymous functions with click() too?

    $('<div>≪/div>').click(function() {
        $(this).hide().show().whatever();
    }).appendTo('#my-parent');
    

    Granted, delegate() is more elegant if you're going to be messing with the DOM. 



  • @sprained said:

     You do realize that you can use anonymous functions with click() too?
    I'm pretty sure we all knew that, yes.



  • The function can't be anonymous when you need to reuse it.  I like jQuery's .live() myself.



  • @jamesn said:

    I like jQuery's .live() myself.

    jQuery.fn.live is pretty much an inefficient jQuery.fn.delegate. If you're using live, then you most likely should be using delegate instead.

    With live have some unintuitive (and unchainable) syntax for specifying context, using the selector's second argument. (You should always specify the scope. If you don't, then the live handler attaches to the document root and monitors the entire DOM. That can end up being quite costly.)

    Delegate offers a much cleaner (and chainable) syntax. Just compare:

    $( ".bar", $( ".foo" )[0] ).live( "click", function(){ /* ... */ });
    $( ".foo" ).delegate( ".bar", "click", function(){ /* ... */ });

    Also note that live is wasteful. The results of the initial selector are never actually used, since the live handler only needs the initial jQuery selector's unparsed string form. In contrast, delegate does not waste resources computing result sets that are never used.

    Check the jsPerf reference, if you want.


Log in to reply