I made an etch-a-sketch with jQuery/Javascript

I took a look at one of the basic challenges in The Odin Project website and thought the etch-a-sketch project was fun.

Here are some of my other pens if you are interested.

http://codepen.io/DevMaterial/

6 Likes

@DevMaterial, this is really cool!

This is great! I would only add a ‘reset’ or ‘erase’ button, maybe on the phisical buttons. =D

1 Like

Yeah this is awesome, great job.

Thanks for the feedback!

This is really well done. I’m currently doing this project and am struggling with it.

This is really cool ! I had a peek at the js, expecting something horrible and mean, but not at all ! And I like the design too ( I look your other pens too).

That’s fun!

(Please take the following in the spirit of help, not criticism).

Just a quick question … Is there a reason you are not caching your jQuery selectors? Re-selecting inside of a loop (whether with jQuery or using something like document.getElementsByClassName() is very in-efficient, as it has to be re-done with each iteration off the loop.,

For example:

 for(var i = 0 ; i < 63 ; i++){
   $('.canvas').append('<ul></ul>');
 }
 for(var i = 0 ; i < 57 ; i++){
   $('ul').append('<li></li>');
 }
  

Inside of every loop iteration, you are re-selecting the same elements. No only that, but in the ul example, you are selecting all uls on the page, adding just one element to each one, then repeating the process … 57 times!

That’s a classic jQuery issue, but easily solved:

// SELECT IT ONCE, THEN MODIFY IT IN THE LOOP.
const $canvas = $( '.canvas' );
 for(var i = 0 ; i < 63 ; i++){
   $canvas.append('<ul></ul>');
 }

That way you aren’t re-selecting the element 63 times in that loop.

However, even that is not “best practice”. Because you are also updating the DOM 63 times as well (not to mention all of the li updates in the next loop). Updating the DOM is slow and calculation intensive (triggering layout reflows and such). What you usually want to do is build your DOM fragments or HTLM string and then update the DOM only one time.

const $canvas = $( '.canvas' );
const $parent = $canvas.parent();

$canvas
  .detach()
  .append( new Array( 64 ).join( '<ul></ul>' ) )
   .find( 'ul' ).append( new Array( 58 ).join( '<li></li>' ) )
  .end()
.appendTo( $parent );

Above, you select the .canvas element one time. You also get a reference to its parent container so that you can remember where it was in the DOM (we’ll need this later).

Next we use a bit of jQuery method chaining to keep things simple and clear and not have to keep re-typing $canvas. (Method chaining is actually a Javascript feature that jQuery makes good use of). Most methods in jQuery return this, which is the jQuery object/collection you are working with. That way you can simply add another method call onto the end of the last.

After you select $canvas and save reference to its parent in the DOM, then you .detach() the $canvas from the DOM. This allows you to work on it without updating the DOM on every change. It’s much faster than working directly in the DOM.

Then you use the .append() method to insert a string of HTML into the $canvas. In this case, we’re using the new Array() syntax to supply a length of the array and then the join method with a separator string of an empty list. The join method then builds the list for us with no loop needed! (The new Array() trick is one that I’d completely forgotten about and re-learned doing exercises on Code Warrior the other night).

Next we find all of the uls we just appended to the $canvas and repeat the new Array() trick with the number of lis needed. One thing to know about jQuery is that, when you make a selection, such as $( 'ul' ) or $canvas.find( 'ul' ) and then use a method like .append(), jQuery will perform the operation on all elements selected. So there is no need for us to create a loop here or to use jQuery’s .each() method. The library does that for us.

Finally, we use .appendTo() to put the $canvas back in the DOM.

The result is the same, but now we did only one DOM selection for $canvas. We then detached it from the DOM and worked on it where it is much faster and efficient to update and finally re-inserted it into its parent - again only one DOM update, instead of …at least 64*57 updates previously!

Anyway, like I said, this is meant in the spirit of help - and I hope it did!

jQuery is quite powerful (although perhaps not currently as “en vogue” as it once was), and it’s good to know fundamentals so that it can be used efficiently. The things mentioned about updating the DOM, selecting elements, etc. apply to all Javascript, not just jQuery.

Regards,
Micheal

2 Likes

I wish there was a category where we could put put Useful Posts or Best Advice.

This is information I’d love to be able to find again. In the meantime, it’s copy paste for me !

1 Like

Yeah, ive been told once about that on reddit, but didn’t exactly know what he meant. I didnt cache the jQuery selectors because I didn’t know what caching exactly was. After reading your explanation, I now understand what he meant when he said “the JS from your etch-a-sketch was making my computer run hard!”. Thanks for the info.

Great! I’m glad it was helpful.