-1

I have functlion which is working perfactly. Now the client’s requirement is that he doesn’t want to use any other file for js, so I have change this function to be pure JavaScript, i.e. without jQuery. I am confused where to start.

Can you guys tell me a JavaScript function similar to jQuery’s .size method?

http://jsfiddle.net/CgDS6/8/

    <div class="wrap">
        <ul>
            <li>
                <div class="first">
                    <div class="second"></div>
                </div>
            </li>
            <li>
                <div class="first">
                    <div class="active"></div>
                </div>
            </li>
            <li>
                <div class="first">
                    <div class="second"></div>
                </div>
            </li>
        </ul>
        <a href="#" id="next">Next</a>
    </div>

var $firstSecond = $('.second').eq(0);
$('#next').click(function() {
    var $active = $('.active');
    var $nextSecond = $active.closest('li').next().find('.second');
    $active.toggleClass('active second');
    if ($nextSecond.size() != 0) {
        $nextSecond.toggleClass('second active');
    } else {
        $firstSecond.toggleClass('second active');
    }
});
Paul D. Waite
  • 96,640
  • 56
  • 199
  • 270
Jitender
  • 7,593
  • 30
  • 104
  • 210
  • 4
    Before people start with the *"jQuery is JavaScript!"* comments, I'm certain OP means jQuery API to DOM API. –  Jul 17 '12 at 15:14
  • 2
    What browsers are being supported? –  Jul 17 '12 at 15:14
  • 10
    My inclination is to tell you to copy the minified jQuery source into the same JS file. – zzzzBov Jul 17 '12 at 15:15
  • Is the client technical? Why does she care about using libraries? – Matt Ball Jul 17 '12 at 15:16
  • 2
    It kills me when people prefix all their JS variables with `$` signs... – Sam Dufel Jul 17 '12 at 15:16
  • 4
    @SamDufel it's a useful naming convention for identifying which variables refer to jQuery objects. – Matt Ball Jul 17 '12 at 15:17
  • 5
    @SamDufel, I prefix jQuery collections with `$` to distinguish them from my standard objects. It looks like the same is being done here. – zzzzBov Jul 17 '12 at 15:17
  • 2
    i dont why she want me to do this with javascript but i have to do i cant aregu with the client – Jitender Jul 17 '12 at 15:17
  • @Rocket: sure, although this chap’s used the `$` prefix for a DOM element too: `var $firstSecond = $('.second').eq(0);`. Wait, does `$().eq` return a DOM element? I may have made a fool out of myself. – Paul D. Waite Jul 17 '12 at 15:17
  • 1
    Upvoted all the comments about prefixing jQuery objects with `$`, but it really bothers me when people miss the point of this and prefix everything with `$`... so im kinda with @SamDufel – Jamiec Jul 17 '12 at 15:18
  • There's nothing difficult to translate in the code above. Is somebody already doing it in a didactic way (I don't feel like doing it) ? – Denys Séguret Jul 17 '12 at 15:18
  • 4
    @PaulD.Waite `.eq()` does not return a bare DOM element. http://api.jquery.com/eq/ ...but boy, are we **way** off-topic. – Matt Ball Jul 17 '12 at 15:18
  • 1
    Alright, this has become too chatty. Enough is enough. – zzzzBov Jul 17 '12 at 15:18
  • 2
    Can we please stop with the off topic discussion about variable naming. It makes it difficult to communicate with OP about the issue at hand. –  Jul 17 '12 at 15:19
  • what is the similer to .size in javaScript – Jitender Jul 17 '12 at 15:19
  • 1
    @amit: `.length` (which works in jQuery too). – gen_Eric Jul 17 '12 at 15:20
  • @amit, `var collection = document.getElementsByTagName('div'); collection.length` – zzzzBov Jul 17 '12 at 15:20
  • and what about the .next, what is alternative of .next in javaScript – Jitender Jul 17 '12 at 15:22
  • 1
    @amit: This is going to be a little too tedious. If you're going to be a software developer for hire, you need to learn the language and the API. If you have an over dependence on jQuery, then that's going to be a problem in general. –  Jul 17 '12 at 15:23
  • 1
    Why is hungarian notation suddenly cool when it comes to jQuery? Do you prefix your variables with `s` `b` etc too? – Esailija Jul 17 '12 at 15:40

5 Answers5

2

This is supported in IE6+. You could also do this with event handlers, but I didn't want to implement a cross-browser event handler and decided to do this quick and dirty with onclick:

function getElementsByClassName(cn, rootNode) {
  if (!rootNode) {
    rootNode = document;
  } 
  for (var r=[], e=rootNode.getElementsByTagName('*'), i=e.length; i--;) {
    if ((' '+e[i].className+' ').indexOf(' '+cn+' ')>-1) {
      r.push(e[i]); 
    }
  }
  return r;  
}

document.getElementById('next').onclick = function(){
    var active = getElementsByClassName('active')[0],
        lis = getElementsByClassName('wrap')[0].getElementsByTagName('li'),
        nextSecond;

    for (var i = 0, il = lis.length; i < il; i++) {
        if (getElementsByClassName('active', lis[i]).length) {
            nextSecond = i + 1 < il ?
                         getElementsByClassName('second', lis[i + 1])[0] :
                         getElementsByClassName('second', lis[0])[0]
        }
    }

    active.className = 'second';
    nextSecond.className = 'active';
};

Here's a fiddle

mVChr
  • 49,587
  • 11
  • 107
  • 104
  • You might want to use my my `getElementsByClassName` with @rsplak's clean solution. I don't know of any books to learn this crappy old-way of writing Javascript, I've just been writing it since the crappy old-way was the only way. – mVChr Jul 17 '12 at 15:41
  • @amit: You can start at [MDN's DOM overview](https://developer.mozilla.org/en/DOM/), but to learn Javascript [this](https://developer.mozilla.org/en-US/learn/javascript) is a good entrance. – Bergi Jul 17 '12 at 16:23
1

Here is a solution in pure javascript:

document.getElementById('next').onclick =  function() {
   var divs = document.getElementsByClassName('second');
   var active = document.getElementsByClassName('active')[0];

   for(var i = 0; i < divs.length; i++) {
     if(divs[i]==active) divs[i].className = 'second';
     if(divs[(i)%divs.length] == active) divs[(i+1)%divs.length].className = 'second active';
   }    
}

JSFIDDLE

  • @amnotiam what isn't compatible with IE8 (that's a question) ? – Denys Séguret Jul 17 '12 at 15:30
  • @dystroy: `getElementsByClassName` didn't show up until IE9. :( –  Jul 17 '12 at 15:30
  • Oh yes... just to help : http://stackoverflow.com/questions/7410949/javascript-document-getelementsbyclassname-compatibility-with-ie – Denys Séguret Jul 17 '12 at 15:32
  • @am not i am: Ah, didn't think of that. And thanks @ dystroy for adding the link –  Jul 17 '12 at 15:33
  • With the borrowed getElementsByClassName (that you should include), this seems to me to be the most compatible and above all the clearest answer. – Denys Séguret Jul 17 '12 at 15:34
  • `.querySelectorAll` can be a nice substitute for IE8 as long as you don't need a "live list" –  Jul 17 '12 at 15:34
  • but needs quite a shim for IE7 ;D – Esailija Jul 17 '12 at 15:37
  • @rsplak: Your script does not really do what the OP's one does, regarding the classes. Also note that the if-conditions in your loop are equal and should be merged. – Bergi Jul 17 '12 at 15:52
0

To start with, the equivalent for the size method in your specific case to size a jQuery Object in Javascript is length, because jQuery DOM selected objects are arrays.

You can have a look at the jQuery source code to see what they are doing in javascript to make jQuery work. Command-F will find you all the different commands and all.

If it's just about the size of files the client wants to be reduced, copy the jQuery source code in your file. You could also keep different files in your development environment and copy them all together and minify them for production use, which is a common practice, so you have the best of both worlds.

Beat Richartz
  • 9,474
  • 1
  • 33
  • 50
0

http://jsfiddle.net/DQSna/3/

var firstSecond = document.querySelector(".second");

document.querySelector("#next").addEventListener("click", function() {


    function toggleClasses( node ) {
        node.classList.toggle("active");
        node.classList.toggle("second");    
    }

    var active = document.querySelectorAll(".active"),
        nextSecond = [].map.call( active, function( node ) {
            while (node && node.nodeName.toLowerCase() !== "li") {
                 node = node.parentNode;   
            }
            return node && node.nextElementSibling && node.nextElementSibling.querySelector( ".second" ) || null;
        }).filter(Boolean);

        [].forEach.call( active, toggleClasses );

        if( nextSecond.length ) {
            [].forEach.call( nextSecond, toggleClasses );
        }
        else {
            toggleClasses( firstSecond );
        }
}, false );​
Esailija
  • 138,174
  • 23
  • 272
  • 326
0

Your jQuery in plain DOM-methods (note that most of them will not be supported by IE):

var firstSecond = document.querySelector(".second'");
document.getElementById("next").addEventListener("click", function(e) {
    var active = document.querySelector(".active"),
        nextSecond = active.parentNode.parentNode.nextElementSibling.querySelector(".second");
    active.classList.remove("active");
    active.classList.add("second");
    (nextSecond || firstSecond).classList.remove("second");
    (nextSecond || firstSecond).classList.add("active");
}, false);

Note that this requires that the elements firstSecond, #next and active are always found - if not, you need to add a check for them being not null.

Your DOM might be cleaner (and the JS simpler) when you:

  • would use active as an id, I guess it is unique (which only would make selecting the element easier)
  • would set the lis themselves as active, I guess that state counts for the whole branch (and therefore allows more styling)
  • would not remove the second class from the divs - they're still second (and active)
  • would not use first and second classes at all - you can select those divs with normal CSS selectors (li > div and li > div > div)
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 1
    the `.toggle` cannot take multiple classes like jQuery. The code is also not the same, where's `closest("li")` etc? – Esailija Jul 17 '12 at 15:26
  • Ah, that's true. The `closest("li")` was transformed into a single `nextElementSibling` - I thought the `li` itself had the active class. Wait, I'll correct that. – Bergi Jul 17 '12 at 15:38
  • Yeah I suppose those are the only mistakes as long as it behaves the same – Esailija Jul 17 '12 at 15:38