SitePoint Sponsor

User Tag List

Page 2 of 2 FirstFirst 12
Results 26 to 30 of 30
  1. #26
    Under Construction silver trophybronze trophy AussieJohn's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, Australia
    Posts
    776
    Mentioned
    11 Post(s)
    Tagged
    0 Thread(s)
    Nice work Paul W. and Pullo - excellent series of posts.

    While I'd agree with Paul O'B that the non-jQuery version doesn't look simpler/shorter, it is definitely worth noting that the bespoke code here will have a few benefits to it. It will perform better and be easy to maintain even by someone who doesn't have any knowledge of jQuery. It would also be quite trivial to turn it in to it's own little extendible library that can be included in other places.

    Looking forward to seeing more of these quiz/competition things
    var details = {
    . . web: "afterlight.com.au",
    . . photos: "jvdl.id.au",
    . . psa: "usethelatestversion.com"
    }

  2. #27
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,873
    Mentioned
    208 Post(s)
    Tagged
    12 Thread(s)
    Hey Paul,

    Quote Originally Posted by paul_wilkins View Post
    Here's a fairly condensed version of the above code in just 23 lines. All it needs is the microAjax library.

    Code javascript:
    Array.prototype.forEach.call(document.querySelectorAll('.tab a'), function (el) {
        el.onclick = function (evt) {
            var link = this, content = document.querySelector('#content');
            if (!link.classList.contains('active')) {
                content.classList.remove('fade-in');
                content.classList.add('fade-out');
     
                window.setTimeout(function () {
                    Array.prototype.forEach.call(document.querySelectorAll(".tab a"), function (el) {
                        el.classList.remove('active');
                    });
                    link.classList.add('active');
     
                    microAjax(link.href, function (response) {
                        content.innerHTML = response;
                    });
     
                    content.classList.remove('fade-out');
                    content.classList.add('fade-in');
                }, 800);
            }
            return false;
        };
    });
    document.querySelector('.tab a').click();
    Could you take a second to explain (in high level terms) what is going on with this:

    Code:
    Array.prototype.forEach.call(document.querySelectorAll('.tab a'), function (el) { ... }
    I get the general idea, but my understanding of call() is a little fuzzy.

  3. #28
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,682
    Mentioned
    99 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by Pullo View Post
    Hey Paul,



    Could you take a second to explain (in high level terms) what is going on with this:

    Code:
    Array.prototype.forEach.call(document.querySelectorAll('.tab a'), function (el) { ... }
    I get the general idea, but my understanding of call() is a little fuzzy.
    Sure thing - the MDN for nodeList provides some useful code snippets for handling nodeLists, such as this one which iterates over them without extending the DOM

    Code javascript:
    var forEach = Array.prototype.forEach;
     
    var divs = document.getElementsByTagName( 'div' );
    var firstDiv = divs[ 0 ];
     
    forEach.call(firstDiv.childNodes, function( divChild ){
      divChild.parentNode.style.color = '#0F0';
    });

    What it does is to use the array forEach iterator to loop over each of the items in the nodeList. So long as that nodeList is not having changes made to it, such as nodes added or removed, that is a reliable solution.

    The most reliable of course is to use a normal for loop to iterate over the nodeList, but using the array forEach can be a suitable alternative too.

    While I did initially have the forEach variable declared in that condensed code that you quoted above, but to save another line of code, the Array.prototype.forEach was taken down in to the code where forEach.call is used, resulting in Array.prototype.forEach.call
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  4. #29
    Gre aus'm Pott gold trophysilver trophybronze trophy
    Pullo's Avatar
    Join Date
    Jun 2007
    Location
    Germany
    Posts
    5,873
    Mentioned
    208 Post(s)
    Tagged
    12 Thread(s)
    Ah ok, the simplified example makes it easier to understand. Thanks.

    So, expanding on what you said, say I had a bunch of div elements and I wanted to hide those with a class name of "invisible".

    What won't work is this:

    Code JavaScript:
    var divs = document.getElementsByTagName( 'div' );
     
    divs.foreach(function(div){
      if (div.className === "invisible"){
        div.style.display = 'none';
      }
    });

    because divs is a NodeList, we can't use Array methods on it.

    So, to get this to work, we need to get a reference to the Array.prototype.foreach method:

    Code JavaScript:
    var forEach = Array.prototype.forEach;

    Then, we can use call on that method passing it a given this value and the callback function that it is expecting:

    Code:
    var forEach = Array.prototype.forEach,
        divs = document.getElementsByTagName( 'div' );
     
    forEach.call(divs, function( div ){
      if (div.className === "invisible"){
        div.style.display = 'none';
      }
    });
    This can then be condensed to this (which is what I think confused me in the first place):

    Code:
    Array.prototype.forEach.call(document.getElementsByTagName('div'), function( div ){
      if (div.className === "invisible"){
        div.style.display = 'none';
      }
    });
    Did I get that right?

  5. #30
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,682
    Mentioned
    99 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by Pullo View Post
    Code:
    Array.prototype.forEach.call(document.getElementsByTagName('div'), function( div ){
      if (div.className === "invisible"){
        div.style.display = 'none';
      }
    });
    Did I get that right?
    Yes indeed - although due to normally preferring understandability over compactness, a standard for loop is the preferred way to handling node lists.

    Code:
    var els = document.getElementsByTagName('div'),
        i;
    for (i = 0; i < els.length; i += 1) {
      if (els[i].className === "invisible"){
        els[i].style.display = 'none';
      }
    });
    which if you prefer can be condensed down in to a dedicated function call:

    Code javascript:
    function forEach(els, callback) {
      var i;
      for (i = 0; i < els.length; i += 1) {
        // standard Array.forEach parameters are el, index, array
        callback(els[i], i, els);
      }
    }
     
    forEach(document.getElementsByTagName('div'), function (div) {

    Ultimately though in this particular situation, the best solution involves writing no JavaScript code at all

    Code css:
    div.invisible {
        display: none;
    }
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript


Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •