JavaScript Challenge: Make Me Blue!

You think you know JavaScript and jQuery? Prove it by taking our challenge! You will face enemies, bosses and more than enough divs to make a grown web developer cry. You will need mad JavaScript and jQuery skills, and a lunch break to finish them all. And the best part? It will look as if you're working!

$.fn.blue = function(){ 

    if(this.filter('.bomb').length) return _FAIL('You triggered a bomb!');

    for(var i=0; i < this.length; i++){
        if( this.eq(i).data('_BOMB') ) return _FAIL('You triggered a bomb!');
    }

    this.addClass('blue');
    _VALIDATE(this);
    return this;
}
var evil = {
    armBomb: function(el){ el.addClass('bomb'); el.data('_BOMB', true); },
    disarmBomb: function(el){ el.removeClass('bomb'); el.data('_BOMB', false); },
    unBlue: function(el){ el.removeClass('blue'); }
};

$('.bomb').each(function(){
    $(this).data('_BOMB', true);
});

body{background-color:#fcfcfc;padding:40px;text-align:center;}
ul {list-style:none;}
ul li, div{width:50px;height:50px;background-color:#ccc;display:inline-block;color:#fff; font-family:sans-serif; line-height:50px; text-align:center;}
.blue{background-color:#5babcd;}
.bomb{background-color:#df463f;}
span, i{display:inline-block;min-width:20px;min-height:10px;}
0%

The rules

The challenge consists of 10 missions that run in our awesome code editor. Each editor has a number of tabs with code, but all except one are locked. You will need to use your JavaScript skills and ingenuity to pass them.

  • You can use any jQuery function that you'd like.
  • Use our .blue() jQuery method to make elements blue.

And that's for the rules. Let's start with the first mission!

1. IDs are easy

Your challenge is to make the #me div blue. Since it's your first one, we went ahead and did it for you. Just uncomment the line in the JS tab and hit Run. Only if real programming was that easy!

<div id="me"></div>
// Write your JS code in this pane. The first one is on us:
// $('#me').blue();
_VALIDATE = function(){
    if($('#me').hasClass('blue')){
        _SUCCESS();
    }
    else _FAIL();
}
// Timeout failure:
setTimeout(_FAIL, 100);

And after that easy win, let's move to something more challenging.

2. So are classes..

So you've heard about these things called classes? Awesome! Make the element with the .wants-to-be-blue class name blue, like you did on the div in the first challenge.

<div></div>
<div></div>
<div class="wants-to-be-blue"></div>
<div></div>
// Write your JS here
_VALIDATE = function(){

    var blue = $('.blue');
    var shouldBe = $('div:eq(2)');

    if(blue.length == 1 && shouldBe.length == 1 && shouldBe.is('.blue')){
        _SUCCESS();
    }
    else _FAIL();
}
// Timeout failure:
setTimeout(_FAIL, 100);

3. The unordered list

There is no stopping you! How about this one? Make the LI element with the comment (but only that LI) blue!

<ul>
    <li></li>
    <li></li>
    <li></li>
    <li><!-- Make me blue! --></li>
    <li></li>
    <li></li>
</ul>
// Write your JS here
_VALIDATE = function(){

    var blue = $('.blue');
    var shouldBe = $('li:eq(3)');

    if(blue.length == 1 && shouldBe.length == 1 && shouldBe.is('.blue')){
        _SUCCESS();
    }
    else _FAIL();
}
// Timeout failure:
setTimeout(_FAIL, 100);

4. Treacherous HTML ahead!

Your jQuery-fu is strong. Maybe you need something a bit more difficult? The rules are the same as before - make the elements with comments blue.

<section>
    <p>Treacherous HTML ahead!</p>

    <div id="make-me-blue">
        <!-- Make me blue! -->
    </div>

    <div></div>

    <div><!-- Make me blue! --></div>
</section>

<section>

    <p>Can you make this span blue too? <span><!-- Make me blue! --></span></p>
    <p>But not <span>this one!</span></p>

    <div></div>

    <p>Yes, I know, HTML can be mean sometimes. But it is not on purpose! 
        <span>Or is <i>it?</i> <i><!-- Make me blue! --></i></span></p>

    <div><div><!-- Make me blue! --></div></div>
</section>
// Write your JS here
_VALIDATE = function(){

    if( $('.blue').length == 5 && $('section:first div:eq(0)').is('.blue') && $('section:first div:eq(2)').is('.blue') 
        && $('section:last p:eq(0) span').is('.blue') && $('section:last p:last span i:last').is('.blue') 
        && $('section:last div div').is('.blue') ){

        _SUCCESS();

    }
};
setTimeout(_FAIL, 100);

5. Mind the order!

This one is tricky. Turn the divs blue, but in the order of the numbers they contain.

<!-- Make all these divs blue in the correct order -->

<div>6</div>
<div>2</div>
<div>7</div>
<div>5</div>
<div>9</div>
<div>4</div>
<div>8</div>
<div>1</div>
<div>3</div>
// Write your JS here
_VALIDATE = function(elem){

    var num = parseInt(elem.text(), 10);

    if(isNaN(num)){
        return _FAIL();
    }

    for(var i = 0; i < num; i++){
        if( !$('div:contains(' + (i+1) + ')').is('.blue') ) return _FAIL('Wrong order!');
    }

    if( $('div.blue').length == 9 ){
        _SUCCESS();
    }
};
setTimeout(_FAIL, 1000);

6. Beware of the bombs!

Let's make things more interesting. Some divs are "bombs". Attempting to make them blue will result in them going off. So you have to think of a way to turn all :not bomb divs blue (got the hint? ;).

<!-- Make all divs blue *except* the bombs. -->

<div></div>
<div class="bomb"></div>
<div></div>
<div class="bomb"></div>
<div></div>
<div></div>
<div class="bomb"></div>
<div></div>
<div></div>
<div class="bomb"></div>
// Write your JS here
_VALIDATE = function(){

    if( $('.blue').length == 6 && $('div.blue').length == 6 ){

        _SUCCESS();

    }
};
setTimeout(_FAIL, 100);

7. You've got enemies!

But what is life without enemies? See the ENEMY tab in the editor? It holds JS code that you cannot edit. Read it carefully in order to pass this challenge. Tip: setTimeout is your friend!

// Your enemy's JS

var div = $('<div>'),
    container = $('section');

setTimeout(function(){
    container.append(div);
}, 1000);
<section>
    <!-- Your enemy will append a div here. Make it blue! -->
</section>
// Write your JS here
_VALIDATE = function(){

    if( $('.blue').length == 1 && $('section div').is('.blue') ){

        _SUCCESS();

    }
};
setTimeout(_FAIL, 2500);

8. Speed is everything

Enemies have access to a special object - evil. It contains all sorts of nefarious methods that are designed to make your life miserable. But every enemy has their weakness!

// Your enemy's JS

var div = $('div'),
    button = $('button');

// Only enemies have access to evil.* functions.
evil.armBomb(div);

button.on('click', function(){
    evil.disarmBomb(div);
});

setTimeout(function(){
    button.off('click');
}, 100);
<button>Click me, fast!</button>
<div><!-- Make me blue --></div>
// Write your JS here
_VALIDATE = function(){

    if( $('.blue').length == 1 && $('div').is('.blue') ){

        _SUCCESS();

    }
};
setTimeout(_FAIL, 1000);

9. Randomization

This time the enemy will choose 5 random ids and place them in the p element. Your job is to parse its contents, and turn those 5 elements blue.

// Your enemy's JS

var ids = 'edno dve tri chetiri pet shest sedem osem devet deset'.split(' ');

// Randomize the array (somewhat)
ids.sort(function() {
    return .5 - Math.random();
});

$('#map').text(ids.slice(0, 5).join(' '));
<p id="map">
    <!-- This paragraph will be populated with randomly generated IDs -->
</p>

<div id="edno"></div>
<div id="dve"></div>
<div id="tri"></div>
<div id="chetiri"></div>
<div id="pet"></div>
<div id="shest"></div>
<div id="sedem"></div>
<div id="osem"></div>
<div id="devet"></div>
<div id="deset"></div>
// Write your JS here
_VALIDATE = function(){

    var ids = $('#map').text().split(' ');

    if(ids.length !== 5) return _FAIL();

    var selected = $('div.blue').filter( function(id){ return ids.indexOf(this.id) != -1 });

    if( $('.blue').length == 5 && selected.length == 5 ){
        _SUCCESS();
    }
};
setTimeout(_FAIL, 1000);

10. Boss fight

Great job, soldier! We're impressed. You've reached the level that turns men into heroes. Your mission is to make all divs on the page blue, but beware - there are two bosses that move bombs around. Can you defeat them?

// Boss 1

var delay = 0,
    position = 0,
    divs = $('div');

setTimeout(moveBomb, delay);

function moveBomb(){

    evil.disarmBomb(divs.eq(position));

    setTimeout(function(){

        position++;

        if(position >= divs.length){
            position = 0;
        }

        evil.unBlue(divs.eq(position));
        evil.armBomb(divs.eq(position));

        setTimeout(moveBomb, 500);

    }, 100);

};
// Boss 2

var delay = 50,
    position = 5,
    divs = $('div');

setTimeout(moveBomb, delay);

function moveBomb(){

    evil.disarmBomb(divs.eq(position));

    setTimeout(function(){

        position++;

        if(position >= divs.length){
            position = 0;
        }

        evil.unBlue(divs.eq(position));
        evil.armBomb(divs.eq(position));

        setTimeout(moveBomb, 500);

    }, 100);

};
<!-- Make all divs blue! -->

<div class="bomb"></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div class="bomb"></div>
<div></div>
<div></div>
<div></div>
<div></div>
// Write your JS here
_VALIDATE = function(){

    if( $('.blue').length == 10 && $('div.blue').length == 10 ){

        // hackerishly clear all timeouts
        var t = setTimeout(function(){}, 10);
        for(var i = 0; i < t; i++) clearTimeout(i);

        _SUCCESS();
    }
};
setTimeout(_FAIL, 10000);
Bootstrap Studio

The revolutionary web design tool for creating responsive websites and apps.

Learn more

Related Articles

Georgi Dyulgerov

Great challenge. I really enjoyed :))

It was damn funny! :D
Thank you Martin, I did it while having lunch!

Rachasak Ragkamnerd

Some question easy. Some question very hard. Orz...

Trong Le

Thank you Martin,

It's funny. Anyone want to compare result ? http://pastebin.com/3Cy7zuLt

Martin Angelov

Great job! I like how you are brute forcing your way through #10 :D. Also you might want to try the :contains selector on #5, it will save you the each().

http://pastebin.com/RSNgTeVs

These are my results ;)

Alberto Restifo

Your solution to #10 is brutally genial! Loved it!

My solutions are less about the jQuery.

http://pastebin.com/mCrUci8k

boomshanka

What a fun challenge! But I'm kinda stuck on 4 even though I believe I made a correct solution at <a href="http://jsfiddle.net/mDTr7/&quot; rel="nofollow">jsfiddle</a>

For the sake of the challenge I'm only interested to know if that is how the result should look? I've also added some quick text to verify the solution.

Martin Angelov

You are over-thinking it :) I meant that challenge to exercise the reader's knowledge of the various jQuery selectors. You could match the comment inside the HTML, but it is easier (at least for me) to write a few separate .blue() calls (or a single monstrous selector like Trong Le has done :).

Your solution is correct. Just change this:
$(this).css('background-color', 'blue') to $(this).blue()

NotWithiPad

Your editor doesn't work with iPad, can't go to 2nd line.

Martin Angelov

Sorry about that! The Ace editor component that I use doesn't work well with touch devices. I will investigate if there is a fix.

After seeing some of the other approaches, I could enhance some of them...

http://pastebin.com/YyTrY7WG

This was great! Can't wait for the next one!

My solutions (some are intentionally ridiculous):

http://pastebin.com/KMGnLzkp

Martin Angelov

Oh no, you have discovered my _SUCCESS function! I can't guarantee it will work next time :D

KrishCdbry

Awesome dude !! You are have some extraordinary JS Skills

My solutions are simply just to pass the level, and may not be the model answer:
http://pastebin.com/PZ9Jdem5

For example, for #9 I did this:
$('#' + $('#map').text().split(' ').join(',#')).blue();

Don't worry, I think that's what most of us did.

I think I brutally murdered the last boss: setInterval(function() {$('div:not(.bomb)').blue();}, 25);
))))

It's disappointing we couldn't take the test without jQuery (I haven't checked, but blue() does more than just adding the class &quot;blue&quot;), but I tried my best to do everything with pure Javascript, relegating the call to blue() at the very end:

http://pastebin.com/iHbsxD5n

I think answers #3 and #4 may surprise some of you... The best part? They work on IE9 too.
This is the IE compatibility list (I think... I actually used Chrome):
6, 8, 9, 9, 9, 9, 8, 8, 9, 9
Using a common for loop can make answers #6 and #9 compatible with IE6 (for #9, use innerHTML instead of textContent).

I basically did the same thing for #3, #4 (just using jQuery to get all elements). See my answers above.

Similar, but not exactly the same thing.
A TreeWalker is basically an iterator, while .contents() returns a snapshot of the child nodes, which you can filter.

It's similar in the sense that we both searched for comment nodes, took their parents and made them blue. I'm actually surprised nobody else did the same (among those who posted their solutions, of course).

(Also, erratum corrigo for my post above: it's #5 that can be rendered IE6-compatible, using for and innerHTML too.)

Dmitry Gusev

Funny, thanks

http://pastebin.com/qaeVzcpx

It'd be great to have a button that does "pastebin" of successful results for you

Create different approach for 4th: http://jsfiddle.net/nFJPd/
It use recursive node type detection.

lampwins

I like this for #9
$("#" + $('p').text().split(' ').join(", #")).blue();

All questions are really too easy. For like 20 or 30 chars for each.
10-th questions with two bosses was like

setInterval(function(){$('div[class!=bomb]').blue();},50);

I'd like to see something more aggressive, like google XSS game (that actually was easy too).

DarkChowder

I killed the bosses in level 10 : )
http://pastebin.com/LYzdK1GV

Daisy Ontas

Great Challenge ..!

Victor Schröder

Hey, that was fun! For those struggling with question 10, why not just refactor the attacking function?
<b> Warning </b>: this link contains my solution. Don't visit if you are still trying.
http://pastebin.com/tpJKBsYc

Nice challenge. I really enjoyed it. #10 was too easy :p
Here are my solutions: http://pastebin.com/TvhHns2G

Ok, what i do wrong? num4 -
$('#make-me-blue').blue();
$('section div:last-child').blue();
$('section p:first-child span').blue();
$('i:last-child').blue();
$('div div').blue();

I see the right result, but the test tells me smth is wrong.

João Beno

Do more of these! Thanks for this awesome test to spend my Friday time... =]

Muy Muy GENIAL todo esto. Gracias! ( It was great! Thanks! )

That was great fun... love a bit of practice... struggled on a few though! :)

Mas Nguyen

This is really fun, I enjoy it much. Clear 9 the levels but not the 4th, lolzzz

Vishal Arora

Thanks Martin.

The quiz was supercool and interesting. Loved it.

little bird

Thanks very much, I really love it ~

Top challenge, really got my thinking :)

Stephanie Q

I'm sort of a jQuery newbie, but I managed the first 7 :D Pretty stoked about that actually. (Though I did use the jQuery API documentation page a bunch) #8 seems to be beyond what I know at the moment, but still, it was really fun to get a sense of where my jQuery skills are!

Thank you for taking the time to set these up! I find challenges like these really help me learn, I wish there were more of them :)

Aadam Ishmael

How the hell did anyone get past number 4?

Luke Flego

LOL. Thoroughly enjoyed this all. Thanks.

Number 10 I was like... omg! Bosses! Then read over it all and was like... er... too much math. Time to bring out the big guns.

$('div').replaceWith('<div></div>');
$('div').blue();

Pradeep Yadav

Awesome exercise. Please add more. :)