New terms from treehouse – jQuery Basics Part 2 – Mobile Drop Down, Password Confirmation and Drawing App Projects

Creating a Mobile Drop Down Menu

We have a site with a top nav that doesn’t look good on mobile. Highlighted to show some of the links go missing.

Screen Shot 2014-09-29 at 1.40.33 PM

Here is our current problem/solution and psuedocode gameplan:

Screen Shot 2014-09-29 at 1.52.44 PM

We’ll start by created a detached (aka disembodied) element for the select element. Then we’ll append it to the menu div, and check to see if it worked (it did).

Screen Shot 2014-09-29 at 1.57.49 PMScreen Shot 2014-09-29 at 1.57.54 PM

Now we need to cycle over the menu links, so we’ll select those with “#menu a”. This is better than div a because it’s more specific. To cycle over them, we should look under the traverse section, and choose the each() method, which let’s us iterate over a matched object, executing a function for each matched element.

We’ll start with a disembodied element $anchor which simply refers to the link, the create an option element using one as well, calling it $option. We’ll then set the option’s text to that of the link’s using the text() method twice, once to set and once to get: $option.text($anchor.text());. Then, we’ll add these new options to the select element using  $select.append($option);. Finally, we’ll set the value attribute of the option element using the val() method listed under attributes. So we’ll write $option.val($anchor.attr(“href”);, which is saying, set the value attribute of option to the value of the href attribute on the anchor element.

Screen Shot 2014-09-29 at 2.25.44 PM Screen Shot 2014-09-29 at 2.26.10 PM

Now, we’ll create a button and append it to the #menu div using the same disembodied element way as before.

Screen Shot 2014-09-29 at 2.29.58 PM

Next we’ll bind a click handler to that button using $button.click(function(){});. Now we need to make it go to the select’s location when clicked. We want to use the value of the value attribute for the $select objects, so we can use the val() method again, this time as a getter because we’re not passing in any parameters. We’ll then use window.location, which is how Javascript let’s you change the windows location, and set it to that.

Screen Shot 2014-09-29 at 2.36.42 PM

Now, when you choose the option from the drop down and click the Go button on the right, it takes you to the selected page.

Screen Shot 2014-09-29 at 2.37.03 PM


Password confirmation project

Here we have some pop ups for when you put in your password wrong that we only want to show during certain conditions. Here’s that and the pseudocode gameplan:

Screen Shot 2014-09-30 at 4.13.39 PM

We start by hiding the spans.

Screen Shot 2014-09-30 at 4.16.26 PM

Now we need to select the password input when someone is writing in it. We’ll select it using the id on the input element, “password”. Then we’ll use the focus() method, under Events > Form Events, which occurs when you click on an input field, giving it focus. It accepts a handler, which is an anonymous or named function.

Screen Shot 2014-09-30 at 4.22.04 PM

We’ll then use the val() method again, which works for select, textarea and input form elements. It returns a string, and strings in JS have a property called .length, which returns the length of the string, so we’ll put that at the end of it. We’ll then set that > 8 and we now have our parameter for our if/else block.

Screen Shot 2014-09-30 at 4.26.24 PM

We now need to traverse the DOM a bit, because we’re trying to show/hide the span that comes after the input.

Screen Shot 2014-09-30 at 4.28.05 PM

The next() method under traversing the DOM let’s us do that. We add this in to show and hide it.

Screen Shot 2014-09-30 at 4.31.57 PM

But this doesn’t work. Even if we write 9 characters, it doesn’t disappear until we give it focus again. What we really need is a method that binds the event (what triggers the function) handler (its function) to when you’re done with your keypress: keyup(). We’ll add this to the end of our current thing, but rather than do the same code twice for hiding and showing, we’ll just make that into our own named method for later use, calling is passwordEvent. Now it works!

Screen Shot 2014-09-30 at 4.38.42 PM

Now to do the confirmation password, which has an id of confirm_password. Since the solution here will probably be similar, we’ll start by getting another function ready, confirmPasswordEvent. We need the event to happen on confirmation input, so we’ll set that up the same way too.

Screen Shot 2014-09-30 at 4.58.42 PM

Now we need to find out if the confirm password is equal to the first password.

Screen Shot 2014-09-30 at 5.02.28 PM

But this is starting to get a bit messy, so we’ll make some variables for them, which allow us to use them instead and also replace all the $(this)’s from the last function.

Screen Shot 2014-09-30 at 5.05.05 PM

We now need to show and hide the hint, so we can do just what we did before with next() and hide/show().

Screen Shot 2014-09-30 at 5.08.04 PM

But what if our passwords match, then we go back and change the first password? The confirm hint should show up again because they don’t match, but it won’t unless we focus on it or keyup. We can do this by calling the confirm password events on the first password object as well.

Screen Shot 2014-09-30 at 5.13.29 PM

A good thing to note – we can use focus() twice with different event handlers and they don’t mess with each other. So when we focus on it, it’s doing both focus() methods, not just the first one. It’s good we made them variables as well, because using $(this) would have messed this up.

Time to perfect this by making the submit button invalid if the password isn’t long enough or if they don’t match. So, we want to add the disabled boolean attribute to the submit input element.

We’ll start by making two functions, one to check if the first is 8 characters and the second to check if they’re matching. For the first one, we can actually replace the first part of the passwordEvent one in the if block, since it will be returning that and is the same thing.

Screen Shot 2014-09-30 at 5.37.09 PM

What’s nice is that if there are other conditions need later for the password (like 1 cap 1 number, etc), we can just add them to the isPasswordValid() function now.

We’ll do the same thing for whether they’re matching.

Screen Shot 2014-09-30 at 5.39.31 PM

Now we’ll make a function for whether it can submit or not. Remember, return with something after will return true or false.

Screen Shot 2014-09-30 at 5.42.03 PM

Now we need a function to enable or disable the submit event. An exclamation point means “not”, so !true = false and !false = true. In the function, we’re selecting the submit button, the we’re changing the “disabled” property based on whether the canSubmit() returns true or false. However, right now if it’s true, which means the button should be good to submit, it would return true and add the disabled property. We want the opposite, so we put in !canSubmit(), which flips those values.

Screen Shot 2014-09-30 at 5.49.00 PM

Now we can add that to our previous code, with keyup() at the end of each.

Screen Shot 2014-09-30 at 5.51.52 PM

However, if we just click submit as soon as the page loads, all this doesn’t work because it’s dependent on a keyup event in the password or confirm inputs. So, we need to execute it when the page loads. So, we simply put this at the bottom.

Screen Shot 2014-09-30 at 5.56.05 PM


Simple drawing application project

We should always aim for our projects to work without JS, this is called graceful degradation. 5 of the 6 projects we’ve done here do that, except for this one, but we don’t really have a choice as there’s no other way for us to get it working. Here’s the problem/solution and pseudocode game plan:

Screen Shot 2014-10-01 at 3.11.12 PM

First is to get the color selector working. We’ll use the click() method. We should also create a variable for the .selected color, as we’ll likely be using that a bit for other stuff. We select it using the .selected selector, then we need its color property so we’ll use the .css() method.

Screen Shot 2014-10-01 at 3.18.59 PM

We’ll probably want to cache the current color, so we can copy that code and put it in the function, using (this) instead for the selected color. Now, to deselect the sibling elements, we’ll first use this, for the thing we clicked, followed by the .sibling() method, which selects its sibling elements, then finally we can use the .removeClass() method to remove the specified .selected class from them.

Screen Shot 2014-10-01 at 3.25.07 PM

Then, to add a class we simply use this and the addClass() method, and we’re good to go.

Screen Shot 2014-10-01 at 3.30.25 PM

Now to make the new color button work. We want to hide or show the color selector when you click the button, based on whether it’s hiding or showing at that time. The show and hide methods aren’t the best option for this, you should use the toggle() method. With no parameters, it simply toggles the visibility of elements. So, we’ll set up a click method on the button, and the toggle method on the colorSelect div.

Screen Shot 2014-10-01 at 4.02.37 PM

Now to update the color span when the sliders change. We’ll start by creating our own method called changeColor, which will change the background-color css property of our selected #newColor span. Then we need to select the range inputs, the sliders, which we can do with attribute selectors. We then use the on() method that says, on an input (which is when you move the slider in this case), it triggers the handler, which in this case is our changeColor function.

Now, in our changeColor() method, we created a variable for each of the color sliders, that takes their value, which is where the slider is at. We then did some math with the css() method that added the three variables together to give us an rbg value, which is what is set as the background color for the #newColor span. It starts as black when we click the new color button because all the sliders are at 0, making it black.

Screen Shot 2014-10-01 at 4.22.20 PM

Now we need it to actually add the new color when you click the Add color button. We’ll start with the click method on the selected button, then create a disembodied list item element. We then want to alter that new color’s background color using the css() method. For the value we’ll use the $(“#newColor”).css(“background-color”) created from the previous method above. We’ll then append() it to the ul list in the div with the.controls class. We’ll then try and make it select it with a click() method.

Screen Shot 2014-10-01 at 5.32.12 PM

Issue – the color gets added (yay!) but doesn’t get selected. The issue is because the click listener we created earlier that switched the selected color on picking one, when the page loads, it binds the click handler to the existing ones, and ignores any new list items. We need a method that will bind when the page loads but also for any future things elements added. The on() method let’s us do that. First we set what happens, the click, then the child element we want it to happen to, the “li”, then we set the function that runs when that happens.

Screen Shot 2014-10-01 at 5.40.29 PM

Ok, finally we get to make the pencil draw stuff. This works via the HTML5 canvas element. First we select the canvas element using jQuery, then we’re actually going to select the canvas itself instead of the jQuery representation of the canvas, and we do this by writing [0] after it. This is actually the same as writing document.getElementByTagName(“canvas”)[0], only easier to write/read. The reason we do this is because the actual element has a special method we can call on that element, which is to get its context – .getContext().

Context in 2d and 3d graphics is just a way for the computer to know where to draw. We’ll set the value to “2d”. We’ll then save this as a variable. Online you may see it named ctx, which is short for context. Finally we’ll move it to the top so we can cache it as a variable when the page loads.

Screen Shot 2014-10-01 at 5.48.47 PM

Now for the drawing code. We’ll start with the context variable, then the beginPath() method, which is saying in the context we want to start a path. We then use moveTo() to say the distance we want it to move on the x and y coordinates, in px. This will be our starting point. Then we use lineTo() to say where the line will go. If we write 20, 10, it will move on the x axis ten px. This is the ending point. Finally, we use .stroke(), and get this:

Screen Shot 2014-10-01 at 5.53.48 PM Screen Shot 2014-10-01 at 5.53.44 PM

To draw a square, we just add more lineTo’s. For the last line, we can use a method called closePath(), which will close things up for you.

Screen Shot 2014-10-01 at 5.56.21 PM Screen Shot 2014-10-01 at 5.55.09 PM

Now to make the pencil do this. When you draw, you don’t just click, you click and hold the mouse down, the let go, so we’ll use the mousedown()mousemove()  and mouseup() methods, in that order. First we’ll select the canvas and cache it as a variable, putting it at the top of the page.

Screen Shot 2014-10-01 at 6.17.50 PM

We’ll apply the mousedown() method to the $canvas object. Just like keyboard click events, there is an event object that can be passed into the handler. When we click down with a mousedown event, it gives us the coordinates. To save this, we’ll first create another global variable, lastEvent. Then in the mousedown() method we’ll pass in e and set lastEvent equal to that. When we check it in the console, we can see a bunch of properties for it now, based on where we clicked. This includes the offset x and y, which we’ll use in our drawing code.

Screen Shot 2014-10-01 at 6.20.16 PM

Screen Shot 2014-10-01 at 6.19.34 PM Screen Shot 2014-10-01 at 6.18.51 PM

Now we need to write what happens when the mouse is moved while being held down. When can chain the mousemove() method onto the one we just wrote, and will pass in e again. We can use the same code we used before with some tweaks. We’ll leave in beginPath, and for moveTo, which remember is the offset, well pass in the lastEvent variable with its properties for the x and y offsets. Now for the lineTo, which draws the line, we do e.offsetX and Y. We can then remove the other lineTo’s and the closePath as they’re not needed.

With the current code, we get this:

Screen Shot 2014-10-01 at 6.27.08 PM Screen Shot 2014-10-01 at 6.27.01 PM

So we’re still drawing even when the mouse is up. What we need to do is update the last event so it stops drawing on mouseUp(). First we’ll set lastEvent to e again, which makes it at least follow the cursor. We want to store if a mouseDown has occurred, so we’ll create a variable for that, and set it to false. Then in our code below, we’ll set it to true. We’ll then use this to make an if block for the drawing code, which will only be true (and therefore running) when the mouse is down.

Screen Shot 2014-10-01 at 6.30.37 PM Screen Shot 2014-10-01 at 6.33.05 PM

Now we get to add on the mouseup() method. We’ll add it in and make it so that it causes the mouseDown variable to be set to false, stopping the drawing.

Screen Shot 2014-10-01 at 6.36.10 PM

Now to make it actually use the selected color. We do this with the strokeStyle property for context, and setting it to our color variable from before.

Screen Shot 2014-10-01 at 6.40.09 PM

One last issue – when you draw outside the canvas and come back in, a line appears.

Screen Shot 2014-10-01 at 6.44.45 PM

The mouseleave() method binds an event handler to when the mouse leaves a an element. We’ll the make the function simply trigger the mouseup() method from above, and we’re good.

Screen Shot 2014-10-01 at 6.48.48 PM

Finally done, woooooo!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s