Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript jQuery Basics (2014) Creating a Simple Drawing Application Mouse Events

jQuery: canvas mini-project

Hello! I had a couple of questions regarding this project. One was, why did we choose background-color as the CSS attribute for defining the selected color? I thought it'd be color and when I looked at the CSS file for the project, I didn't notice anything labeled with background-color either.

//Problem: No user interaction
//Plan: User Interaction causes changes
//Perform:

//WHY NOT .css(color) ?
var color = $('.selected').css('background-color');

//When clicking on control list items
///.on ensures that this function will work for all li, original and newly added
$('.controls').on('click','li',function() {
  //Deselect siblings elements
  $(this).siblings().removeClass('selected');
  //Select clicked list item
  $(this).addClass('selected');     
  //cache current color
  //WHY NOT .css(color) ?
  color = $(this).css('background-color');
})

I also am confused about the point of one line of code ($("input[type=range]").change(changeColor); ). In this video it's said to be for when color sliders change, but I still don't understand in context to everything else...

//When add color is pressed
$('#revealColorSelect').click(function() {
  //Show or hide color selector
  changeColor()
  $('#colorSelect').toggle();
})

//update new color span
function changeColor() {
  //people will slide the sliders and give each id a new numerical value
  var r = $('#red').val();
  var g = $('#green').val();
  var b = $('#blue').val();
  //set attribute of new color to rgb mixture such that we have rbg(val, val, val) which translates into hexadecimal code
  $('#newColor').css('background-color','rgb('+r+','+g+','+b+')');
}                     

//When color sliders change
//CONFUSED ABOUT THIS LINE
$("input[type=range]").change(changeColor); 

// when 'add color' is pressed
$('#addNewColor').click(function() {
  var $newColor = $('<li></li>');
  $newColor.css('background-color', $('#newColor').css('background-color'));
  //append new color to controls ul
  $('.controls ul').append($newColor);
  //select new color and will use the code all the way up in line 8?
  $newColor.click();
})

//mouse events on canvas
  //draw lines
//here we select the actual HTML canvas elt b/c there's a special method we can call on it

//.getContext() returns obj that provides methods and prop for drawing on canvas

//we can select a plain old JavaScript representation of a DOM element with $('elt')[0] or document.getElementsbyTagName('canvas')[0]
var context = $('canvas')[0].getContext('2d');

//drawing square for practice
context.beginPath();
context.moveTo(10,10);
context.lineTo(20,10);
context.lineTo(20,20);
context.lineTo(10,20);
context.closePath();
//stroke actually draws path defined by moveTo and lineTo code
context.stroke();

And finally, I don't truly understand the difference between lastEvent and e in the following code. Why do we write lastEvent = e twice and use them to get different offset values if they're apparently set equal to each other?

//global variable
var lastEvent; 
var mouseDown = false;

var $canvas = $('canvas');
$canvas.mousedown(function(e){
  lastEvent = e;
  mouseDown = true;
}).mousemove(function(e){
  if (mouseDown){
    context.beginPath();
    //CONFUSED ABOUT DIFFERENCE BETWEEN lastEvent AND e!!
    context.moveTo(lastEvent.offsetX,lastEvent.offsetY);
    context.lineTo(e.offsetX,e.offsetY);
    context.strokeStyle = color;
    context.stroke();
    lastEvent = e;
  }
}).mouseup(function(){
  mouseDown = false;
}).mouseleave(function(){
  $canvas.mouseup();
});

Sorry for the really long post; just need to clarify these three things! Thank you :)

3 Answers

Hi mm4,

1)The colored circles that are below the canvas have that color set as a background-color which is why you have to retrieve the color selected from the background-color property. You start off with red, blue, and yellow already there. You can look in the css file for .red, .blue, .yellow selectors and you will see that those colors have been assigned in the background property.

Like this:

.red {
    background: none repeat scroll 0 0 #fc4c4f;
}

For newly added colors, the color is added as a background-color inline. You can see it if you inspect the element with dev tools.

2) $("input[type=range]").change(changeColor); The idea here is that while you are dragging around the sliders you want to be able to see a preview of what the color is, based on where you've moved the sliders. So each time the change event goes off, the changeColor function is called. This function will get the 3 values of the sliders and build up the color from that and set the preview square to that color.

It turns out that the "change" event is not the correct event to be listening for here. The "change" event only goes off once when you've released the slider. This isn't ideal if you want a real time update of that color while you're dragging. The "input" event is the correct one to listen for. This one goes off whenever an input value changes. When you drag the slider around you're repeatedly changing the value and so the "input" event will fire repeatedly. The changeColor function will then get repeatedly called allowing a real time update of the color preview while you're dragging.

It worked in the videos because chrome had an incorrect implementation of the change event at the time the videos were recorded.

You should change that code to this: $("input[type=range]").on ("input", changeColor);

3) The e object contains the coordinates of where the mouse is. When you hold down the mouse button the 'mousedown' event will trigger and what it does is save that event in the lastEvent variable. You're then going to move the mouse and the 'mousemove' event will go off. In order to draw you have to know where it was before and where it is now. The e object passed in holds the current position and lastEvent is where it was just at. At the end of the 'mousemove' handler you have to again set the current event e to lastEvent so that as you continue to move the mouse you will always have the coordinates of where it was last at in lastEvent.

Does that make sense or have I made it more confusing?

Hi Jason,

This is incredibly helpful! Thank you so much for the detailed response. I did think of one other question, though. I couldn't find offsetX or offsetY here http://api.jquery.com/offset/. It makes sense, though - basically each represents part of a coordinate (x,y) but where in the documentation can I read more about it?

This link contains some information on these properties: http://www.jacklmoore.com/notes/mouse-position/

It also contains a link to the w3c working draft.

You might also be interested in this discussion: https://teamtreehouse.com/forum/this-wont-work-in-firefox-out-of-the-box-i-made-a-change-to-the-mousemove-function-to-make-it-compatible-with-ff

Hi Jason,

I found your response very helpful, but still have a question. Namely, I am still trying to understand this line of code

$("input[type = range]").change(changeColor);

What's up with the stuff in the brackets? I see where a similar equation shows up in the HTML, but I am unfamiliar with the use of brackets in this particular instance of jquery.

I appreciate any help!!

-Rose