WEBVTT

NOTE Created by CaptionSync from Automatic Sync Technologies www.automaticsync.com

00:00:01.066 --> 00:00:03.006 align:middle
Everything should be working...

00:00:03.216 --> 00:00:07.476 align:middle
but nope! We've got this
jQuery is not defined error...

00:00:08.146 --> 00:00:09.956 align:middle
but it's not from our code!

00:00:10.146 --> 00:00:13.666 align:middle
It's coming from inside of
autocomplete.jquery.js -

00:00:13.946 --> 00:00:16.346 align:middle
that third party package we installed!

00:00:17.016 --> 00:00:19.446 align:middle
This is the second jQuery
plugin that we've used.

00:00:20.016 --> 00:00:21.296 align:middle
The first was bootstrap...

00:00:21.666 --> 00:00:23.546 align:middle
and that worked brilliantly!

00:00:24.496 --> 00:00:29.356 align:middle
Look inside app.js: we imported
bootstrap and, yea...

00:00:29.716 --> 00:00:30.406 align:middle
that was it.

00:00:30.946 --> 00:00:37.686 align:middle
Bootstrap is a well-written jQuery plugin,
which means that inside, it imports jquery -

00:00:37.956 --> 00:00:40.776 align:middle
just like we do - and then modifies it.

00:00:41.436 --> 00:00:43.936 align:middle
But this Algolia autocomplete.js plugin?

00:00:44.436 --> 00:00:47.116 align:middle
Yea, it's not so well-written.

00:00:47.776 --> 00:00:53.246 align:middle
Instead of detecting that we're inside
Webpack and importing jQuery, it just says...

00:00:53.526 --> 00:00:57.676 align:middle
jQuery! And expects it to be
available as a global variable.

00:00:58.386 --> 00:01:04.366 align:middle
This is why jQuery plugins are a special
monster: they've been around for so long,

00:01:04.776 --> 00:01:08.466 align:middle
that they don't always play nicely
in the modern way of doing things.

00:01:08.846 --> 00:01:10.506 align:middle
So... are we stuck?

00:01:10.506 --> 00:01:15.656 align:middle
I mean, this 3rd-party package
is literally written incorrectly!

00:01:16.166 --> 00:01:16.806 align:middle
What can we do?

00:01:17.386 --> 00:01:20.786 align:middle
Well... it's Webpack to the rescue!

00:01:21.646 --> 00:01:29.156 align:middle
Open up webpack.config.js and find some
commented-out code: autoProvidejQuery().

00:01:29.976 --> 00:01:30.816 align:middle
Uncomment that.

00:01:31.446 --> 00:01:40.836 align:middle
Then, go restart Encore: When it
finishes, move back over and...

00:01:41.276 --> 00:01:44.886 align:middle
refresh! No errors!

00:01:45.436 --> 00:01:48.106 align:middle
And if I start typing in the autocomplete box...

00:01:49.106 --> 00:01:52.956 align:middle
it works! What black magic is this?!

00:01:53.566 --> 00:01:55.526 align:middle
The .autoProvidejQuery() method...

00:01:55.526 --> 00:01:57.926 align:middle
yea... it sorta is black magic.

00:01:58.496 --> 00:02:00.816 align:middle
Webpack is already scanning all of our code.

00:02:01.296 --> 00:02:08.786 align:middle
When you enable this feature, each time it
finds a jQuery or $ variable- anywhere in any

00:02:08.786 --> 00:02:15.576 align:middle
of the code that we use - that is uninitialized,
it replaces it with require('jquery').

00:02:16.056 --> 00:02:19.556 align:middle
It basically rewrites the
broken code to be correct.

00:02:20.536 --> 00:02:23.586 align:middle
While we're here, there's an
organizational improvement I want to make.

00:02:24.446 --> 00:02:26.356 align:middle
Look inside admin_article_form.js.

00:02:27.636 --> 00:02:33.936 align:middle
Hmm, we include both the JavaScript file
and the CSS file for Algolia autocomplete.

00:02:34.466 --> 00:02:38.466 align:middle
But if you think about it,
this CSS file is meant

00:02:38.566 --> 00:02:42.826 align:middle
to support the algolia-autocomplete.js file.

00:02:43.696 --> 00:02:50.216 align:middle
To say it differently: the CSS file is
a dependency of algolia-autocomplete.js:

00:02:50.986 --> 00:02:56.286 align:middle
if that file was ever used without this
CSS file, things wouldn't look right.

00:02:57.216 --> 00:03:01.806 align:middle
Take out the import and move it
into algolia-autocomplete.js.

00:03:02.276 --> 00:03:03.596 align:middle
Make sure to update the path.

00:03:04.416 --> 00:03:05.636 align:middle
That's nice!

00:03:06.246 --> 00:03:08.836 align:middle
If we want to use this autocomplete
logic somewhere else,

00:03:09.106 --> 00:03:14.696 align:middle
we only need to import the JavaScript file:
it takes care of importing everything else.

00:03:15.376 --> 00:03:17.166 align:middle
The result is the same, but cleaner.

00:03:17.916 --> 00:03:20.966 align:middle
Well, this file still isn't
as clean as I want it.

00:03:21.386 --> 00:03:24.406 align:middle
We're importing the algolia-autocomplete.js
file...

00:03:24.406 --> 00:03:27.326 align:middle
but it's not really a "module".

00:03:27.936 --> 00:03:32.926 align:middle
It doesn't export some reusable
function or class: it just runs code.

00:03:33.726 --> 00:03:37.086 align:middle
I really want to start thinking
of all of our JavaScript files -

00:03:37.386 --> 00:03:42.036 align:middle
except for the entry files
themselves - as reusable components.

00:03:43.036 --> 00:03:47.606 align:middle
Check it out: instead of just "doing"
stuff, let's export a new function

00:03:47.706 --> 00:03:50.136 align:middle
that can initialize the autocomplete logic.

00:03:50.906 --> 00:03:55.986 align:middle
Replace $(document).ready() with export
default function with three arguments:

00:03:56.776 --> 00:04:02.456 align:middle
the jQuery $elements that we want to attach
the autocomplete behavior to, the dataKey,

00:04:02.696 --> 00:04:06.266 align:middle
which will be used down here as a way
of a defining where to get the data

00:04:06.266 --> 00:04:11.986 align:middle
from on the Ajax response, and displayKey
- another config option used at the bottom,

00:04:12.276 --> 00:04:16.046 align:middle
which is the key on each result
that should be displayed in the box.

00:04:16.776 --> 00:04:22.246 align:middle
Basically, we're taking out all the specific
parts and replacing them with generic variables.

00:04:23.266 --> 00:04:29.726 align:middle
Now we can say $elements.each() and for dataKey,
we can put a bit of logic: if (dataKey),

00:04:29.986 --> 00:04:36.216 align:middle
then data = data[dataKey],
and finally just cb(data).

00:04:36.986 --> 00:04:41.086 align:middle
Some of this is specific to exactly how
the Autocomplete library itself works -

00:04:41.526 --> 00:04:43.196 align:middle
we set that up in an earlier tutorial.

00:04:43.946 --> 00:04:46.946 align:middle
Down at the bottom, set displayKey
to displayKey.

00:04:47.926 --> 00:04:48.506 align:middle
Beautiful!

00:04:48.996 --> 00:04:53.306 align:middle
Instead of doing something, this
file returns a reusable function.

00:04:54.156 --> 00:04:56.546 align:middle
That should feel familiar if
you come from the Symfony world:

00:04:57.046 --> 00:05:01.746 align:middle
we organize code by creating files
that contain reusable classes,

00:05:01.876 --> 00:05:06.206 align:middle
instead of files that contain procedural
code that instantly does something.

00:05:07.206 --> 00:05:12.276 align:middle
Ok! Back in admin_article_form.js,
let's import autocomplete from '.

00:05:12.456 --> 00:05:14.816 align:middle
/components/algolia-autocomplete'.

00:05:15.036 --> 00:05:24.986 align:middle
Oooo. And then, const $autoComplete
= $('.js-user-autocomplete') -

00:05:25.406 --> 00:05:27.626 align:middle
to find the same element we were using before.

00:05:30.076 --> 00:05:38.586 align:middle
Then, if not $autoComplete.is(':disabled'),
call autocomplete() -

00:05:38.776 --> 00:05:43.046 align:middle
because that's the variable we
imported - and pass it $autoComplete,

00:05:44.476 --> 00:05:47.676 align:middle
users for dataKey and email for displayKey.

00:05:48.386 --> 00:05:48.986 align:middle
I love it!

00:05:49.716 --> 00:05:55.526 align:middle
By the way, the reason I'm added this :disabled
logic is that we originally set up our forms

00:05:55.616 --> 00:06:00.846 align:middle
so that the author field that we're adding this
autocomplete to is disabled on the edit form.

00:06:01.316 --> 00:06:05.116 align:middle
So, there's no reason to try to add
the autocomplete stuff in that case.

00:06:05.736 --> 00:06:06.946 align:middle
Ok, refresh...

00:06:07.356 --> 00:06:10.236 align:middle
then type admi...

00:06:10.236 --> 00:06:14.086 align:middle
it works! Double-check that
we didn't break the edit page:

00:06:14.956 --> 00:06:20.236 align:middle
go back to /admin/article,
edit any article and, yea!

00:06:20.756 --> 00:06:21.236 align:middle
Looks good!

00:06:21.706 --> 00:06:23.976 align:middle
The field is disabled, but nothing is breaking.

00:06:24.786 --> 00:06:29.016 align:middle
Hey! We have no more JavaScript
files in our public/ directory.

00:06:29.336 --> 00:06:33.726 align:middle
Woo! But, we do still have 2 CSS files.

00:06:34.296 --> 00:06:35.596 align:middle
Let's handle those next.

