WEBVTT

NOTE Created by CaptionSync from Automatic Sync Technologies www.automaticsync.com

00:00:01.056 --> 00:00:06.176 align:middle
Here's our next goal: write some
JavaScript so that that when we click the up

00:00:06.176 --> 00:00:11.816 align:middle
or down vote icons, it will make an
AJAX request to our JSON endpoint.

00:00:12.376 --> 00:00:17.436 align:middle
This "fakes" saving the vote to the
database and returns the new vote count,

00:00:18.026 --> 00:00:21.006 align:middle
which we will use to update
the vote number on the page.

00:00:21.796 --> 00:00:27.016 align:middle
The template for this page is:
templates/question/show.html.twig.

00:00:27.016 --> 00:00:32.556 align:middle
For each answer, we have these
vote-up and vote-down links.

00:00:33.246 --> 00:00:37.246 align:middle
I'm going to add a few classes to
this section to help our JavaScript.

00:00:38.136 --> 00:00:43.176 align:middle
On the vote-arrows element,
add a js-vote-arrows class:

00:00:43.936 --> 00:00:46.926 align:middle
we'll use that in JavaScript
to find this element.

00:00:47.806 --> 00:00:54.476 align:middle
Then, on the vote-up link, add a data
attribute called data-direction="up".

00:00:56.376 --> 00:01:00.246 align:middle
Do the same for the down
link: data-direction="down".

00:01:01.046 --> 00:01:03.576 align:middle
This will help us know which link was clicked.

00:01:03.576 --> 00:01:15.816 align:middle
Finally, surround the vote number - the 6 - with
a span that has another class: js-vote-total.

00:01:16.286 --> 00:01:20.156 align:middle
We'll use that to find the element
so we can update that number.

00:01:20.746 --> 00:01:25.616 align:middle
To keep things simple, the JavaScript code
we are going to write will use jQuery.

00:01:26.266 --> 00:01:33.286 align:middle
In fact, if your site uses jQuery, you probably
will want to include jQuery on every page...

00:01:34.106 --> 00:01:38.986 align:middle
which means that we want to add
a script tag to base.html.twig.

00:01:39.966 --> 00:01:44.166 align:middle
At the bottom, notice that we
have a block called javascripts.

00:01:45.006 --> 00:01:49.666 align:middle
Inside this block, I'm going to paste a
&lt;script&gt; tag to bring in jQuery from a CDN.

00:01:49.666 --> 00:01:55.776 align:middle
You can copy this from the code block
on this page, or go to jQuery to get it.

00:01:55.776 --> 00:02:01.266 align:middle
If you're wondering why we put this
inside of the javascripts block...

00:02:01.526 --> 00:02:06.406 align:middle
other than it "seems" like a logical
place, I'll show you why in a minute.

00:02:07.036 --> 00:02:12.736 align:middle
Because technically, if we put this
after the javascripts block or before,

00:02:13.236 --> 00:02:15.876 align:middle
it would make no difference right now.

00:02:16.966 --> 00:02:19.806 align:middle
But putting it inside will be useful soon.

00:02:19.806 --> 00:02:25.726 align:middle
For our custom JavaScript, inside the public/
directory, create a new directory called js/.

00:02:25.726 --> 00:02:30.466 align:middle
And then a new file: question_show.js.

00:02:31.806 --> 00:02:36.706 align:middle
Here's the idea: usually you
will have some custom JavaScript

00:02:36.836 --> 00:02:39.736 align:middle
that you want to include on every page.

00:02:40.816 --> 00:02:46.516 align:middle
We don't have any right now, but if
we did, I would create an app.js file

00:02:47.026 --> 00:02:50.906 align:middle
and add a script tag for it in base.html.twig.

00:02:51.746 --> 00:02:58.236 align:middle
Then, on certain pages, you might also need
to include some page-specific JavaScript,

00:02:58.746 --> 00:03:04.036 align:middle
like to power a comment-voting
feature that only lives on one page.

00:03:04.946 --> 00:03:10.176 align:middle
That's what I'm doing and that's why I
created a file called question_show.js:

00:03:10.176 --> 00:03:14.506 align:middle
it's custom JavaScript for that page.

00:03:15.486 --> 00:03:19.966 align:middle
Inside question_show.js, I'm going
to paste about 15 lines of code.

00:03:20.716 --> 00:03:29.236 align:middle
This finds the .js-vote-arrows element -
which we added here - finds any a tags inside,

00:03:29.526 --> 00:03:32.036 align:middle
and registers a click listener on them.

00:03:32.536 --> 00:03:41.096 align:middle
On click, we make an AJAX request to
/comments/10 - the 10 is hardcoded for now -

00:03:41.096 --> 00:03:48.236 align:middle
/vote/ and then we read the data-direction
attribute off of the anchor element to know

00:03:48.236 --> 00:03:51.546 align:middle
if this is an up vote or down vote.

00:03:52.726 --> 00:03:57.546 align:middle
On success, jQuery passes us
the JSON data from our endpoint.

00:03:58.426 --> 00:04:01.976 align:middle
Let's rename that variable
to data to be more accurate.

00:04:04.606 --> 00:04:07.256 align:middle
Then we use the votes field from the data -

00:04:07.526 --> 00:04:12.256 align:middle
because in our controller we're returning
a votes key - to update the vote total.

00:04:13.076 --> 00:04:15.846 align:middle
So... how do we include this file?

00:04:16.496 --> 00:04:21.176 align:middle
If we wanted to include this on
every page, it would be pretty easy:

00:04:21.686 --> 00:04:26.096 align:middle
add another script tag below
jQuery in base.html.twig.

00:04:27.036 --> 00:04:30.856 align:middle
But we want to include this
only on the show page.

00:04:31.716 --> 00:04:38.066 align:middle
This is where having the jQuery script tag
inside of a javascripts block is handy.

00:04:38.716 --> 00:04:43.206 align:middle
Because, in a "child" template,
we can override that block.

00:04:43.996 --> 00:04:49.446 align:middle
Check it out: in show.html.twig, it doesn't
matter where - but let's go to the bottom,

00:04:49.966 --> 00:04:52.936 align:middle
say {% block javascripts %} {% endblock %}.

00:04:54.836 --> 00:04:58.466 align:middle
Inside, add a &lt;script&gt; tag with src="".

00:04:58.466 --> 00:05:02.806 align:middle
Oh, we need to remember to
use the asset() function.

00:05:03.296 --> 00:05:08.366 align:middle
But... PhpStorm is suggesting
js/question_show.js.

00:05:08.816 --> 00:05:09.506 align:middle
Select that.

00:05:10.326 --> 00:05:13.326 align:middle
Nice! It added the asset() function for us.

00:05:13.436 --> 00:05:20.636 align:middle
If we stopped now, this would literally override
the javascripts block of base.html.twig.

00:05:21.076 --> 00:05:24.616 align:middle
So, jQuery would not be included on the page.

00:05:25.236 --> 00:05:30.936 align:middle
Instead of overriding the block, what
we really want to do is add to it!

00:05:30.936 --> 00:05:37.036 align:middle
In the final HTML, we want our new
script tag to go right below jQuery.

00:05:37.566 --> 00:05:38.486 align:middle
How can we do this?

00:05:39.126 --> 00:05:42.696 align:middle
Above our script tag, say {{ parent() }}.

00:05:43.736 --> 00:05:45.006 align:middle
I love that!

00:05:45.746 --> 00:05:49.996 align:middle
The parent() function gets the content
of the parent block, and prints it.

00:05:50.746 --> 00:05:51.476 align:middle
Let's try this!

00:05:51.946 --> 00:05:53.086 align:middle
Refresh and...

00:05:53.426 --> 00:05:56.136 align:middle
click up. It updates!

00:05:56.746 --> 00:06:00.076 align:middle
And if we hit down, we see a really low number.

00:06:00.776 --> 00:06:04.316 align:middle
Oh, and see this number "6"
down on the web debug toolbar?

00:06:04.706 --> 00:06:06.146 align:middle
This is really cool.

00:06:06.566 --> 00:06:07.516 align:middle
Refresh the page.

00:06:07.926 --> 00:06:10.356 align:middle
Notice that the icon is not down here.

00:06:10.976 --> 00:06:14.886 align:middle
But as soon as our page makes
an AJAX requests, it shows up!

00:06:15.536 --> 00:06:21.146 align:middle
Yep, the web debug toolbar detects
AJAX requests and lists them here.

00:06:21.856 --> 00:06:28.846 align:middle
The best part is that you can use this to jump
into the profiler for any of these requests!

00:06:28.846 --> 00:06:32.746 align:middle
I'll right click and open this
"down" vote link in a new tab.

00:06:33.446 --> 00:06:38.656 align:middle
This is the full profiler for
that request in all its glory.

00:06:39.306 --> 00:06:43.046 align:middle
If you use dump() somewhere in
your code, the dumped variable

00:06:43.046 --> 00:06:45.156 align:middle
for that AJAX requests will be here.

00:06:45.716 --> 00:06:48.366 align:middle
And later, a database section will be here.

00:06:48.976 --> 00:06:51.146 align:middle
This is a killer feature.

00:06:52.046 --> 00:06:58.356 align:middle
Next, let's tighten up our API endpoint:
we shouldn't be able to make a GET request

00:06:58.356 --> 00:07:00.616 align:middle
to it - like loading it in our browser.

00:07:01.236 --> 00:07:06.236 align:middle
And... do we have anything that
validates that the {direction} wildcard

00:07:06.236 --> 00:07:10.136 align:middle
in the URL is either up or
down but nothing else?

00:07:10.506 --> 00:07:11.436 align:middle
Not yet.

