JavaScript Challenge: Make Me Blue!

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);

Presenting Bootstrap Studio

a revolutionary tool that developers and designers use to create
beautiful interfaces using the Bootstrap Framework.

Learn more
Web Browser Frame DevKit Box Mouse Cursor
by Martin Angelov

Martin is a web developer with an eye for design from Bulgaria. He founded Tutorialzine in 2009 and it still is his favorite side project.

1Share this post
2Read one more article
3Get your free book
Book Cover
jQuery Trickshots

Tutorialzine's advanced jQuery techniques book.

Download

45 Comments

  1. Georgi Dyulgerov says:

    Great challenge. I really enjoyed :))

  2. MaxArt says:

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

  3. Rachasak Ragkamnerd says:

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

  4. Trong Le says:

    Thank you Martin,

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

    1. Martin Angelov says:

      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().

      1. Mensur says:

        http://pastebin.com/RSNgTeVs

        These are my results ;)

    2. Alberto Restifo says:

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

    3. extempl says:

      http://pastebin.com/cqskeXPZ

    4. Jason M says:

      My solutions are less about the jQuery.

      http://pastebin.com/mCrUci8k

  5. boomshanka says:

    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/" 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.

    1. Martin Angelov says:

      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 :).

    2. Ganesh says:

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

  6. NotWithiPad says:

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

    1. Martin Angelov says:

      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.

  7. Gil says:

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

    http://pastebin.com/YyTrY7WG

  8. Kevron says:

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

  9. Mark says:

    My solutions (some are intentionally ridiculous):

    http://pastebin.com/KMGnLzkp

    1. Martin Angelov says:

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

    2. KrishCdbry says:

      Awesome dude !! You are have some extraordinary JS Skills

  10. samliew says:

    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();

    1. MaxArt says:

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

  11. Allot says:

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

  12. MaxArt says:

    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).

    1. Mark says:

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

      1. MaxArt says:

        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.)

  13. Dmitry Gusev says:

    Funny, thanks

    http://pastebin.com/qaeVzcpx

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

  14. Exwar says:

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

  15. lampwins says:

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

  16. Alex says:

    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).

  17. DarkChowder says:

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

  18. Daisy Ontas says:

    Great Challenge ..!

  19. Victor Schröder says:

    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

  20. Robin says:

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

  21. Azaro says:

    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.

  22. João Beno says:

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

  23. Mariano says:

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

  24. Adam says:

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

  25. Mas Nguyen says:

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

  26. Vishal Arora says:

    Thanks Martin.

    The quiz was supercool and interesting. Loved it.

  27. little bird says:

    Thanks very much, I really love it ~

  28. Gregory says:

    Top challenge, really got my thinking :)

  29. Stephanie Q says:

    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 :)

  30. Suresh kumar says:

    Its fun!!
    http://pastebin.com/4YKZB9j8

  31. Aadam Ishmael says:

    How the hell did anyone get past number 4?

  32. Luke Flego says:

    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();

Add Comment

Add a Reply

HTML is escaped automatically. Surround code blocks with <pre></pre> for readability.
Perks:   **bold**   __italics__   [some text](http://example.com) for links