gstreamer0.10-ffmpeg
gstreamer0.10-plugins-good
packages.
We still have work to do to get the new.html.twig
template working:
... lines 1 - 2 | |
{% block javascripts %} | |
... lines 4 - 5 | |
<script src="https://cdn.jsdelivr.net/autocomplete.js/0/autocomplete.jquery.min.js"></script> | |
<script src="{{ asset('js/algolia-autocomplete.js') }}"></script> | |
... line 8 | |
{% endblock %} | |
... lines 10 - 25 |
we have a script tag for this external autocomplete library and one for our own public/js/algolia-autocomplete.js
file... which is our last JavaScript file in the public/
directory! Woo!
$(document).ready(function() { | |
$('.js-user-autocomplete').each(function() { | |
var autocompleteUrl = $(this).data('autocomplete-url'); | |
$(this).autocomplete({hint: false}, [ | |
{ | |
source: function(query, cb) { | |
$.ajax({ | |
url: autocompleteUrl+'?query='+query | |
}).then(function(data) { | |
cb(data.users); | |
}); | |
}, | |
displayKey: 'email', | |
debounce: 500 // only request every 1/2 second | |
} | |
]) | |
}); | |
}); |
This holds code that adds auto-completion... on this author box... which, yes, is totally broken.
To start, remove the CDN link to this autocomplete library:
... lines 1 - 2 | |
{% block javascripts %} | |
... lines 4 - 5 | |
<script src="https://cdn.jsdelivr.net/autocomplete.js/0/autocomplete.jquery.min.js"></script> | |
... lines 7 - 8 | |
{% endblock %} | |
... lines 10 - 25 |
And, at your terminal, install it properly!
yarn add autocomplete.js --dev
Next, you know the drill, take the algolia-autocomplete.js
file and move it into the assets/js/
directory. But I'm not going to make this a new entry point. We could do that, but really, we already have an entry file that's included on this page: admin_article_form
:
... lines 1 - 2 | |
{% block javascripts %} | |
... lines 4 - 7 | |
{{ encore_entry_script_tags('admin_article_form') }} | |
{% endblock %} | |
... lines 10 - 25 |
So really, admin_article_form.js
should probably just use the code from algolia-autocomplete.js
.
So, move that file into the components/ directory... which is kind of meant for reusable modules. And... well, this isn't really written like a re-usable module yet because it just executes code instead or returning something, like a function. But, we'll work on that later.
Let's also take the algolia-autocomplete.css
file and move that all the way up here into assets/css/
. And just because we can, I'll make it an SCSS file!
Okay! Back in admin_article_form.js
, let's bring in this code: import './components/algolia-autocomplete'
:
... lines 1 - 4 | |
import './components/algolia-autocomplete'; | |
... lines 6 - 157 |
We don't need an import from
yet... because that file doesn't actually export anything. For the CSS: import '../css/algolia-autocomplete.scss'
:
... lines 1 - 4 | |
import './components/algolia-autocomplete'; | |
import '../css/algolia-autocomplete.scss'; | |
... lines 7 - 157 |
Back in new.html.twig
, the great thing is, we don't need to import this CSS file anymore or any of these script files. This is really how we want our templates to look: a single a call to {{ encore_entry_script_tags() }}
and a single call to {{ encore_entry_link_tags() }}
:
... lines 1 - 2 | |
{% block javascripts %} | |
{{ parent() }} | |
{{ encore_entry_script_tags('admin_article_form') }} | |
{% endblock %} | |
{% block stylesheets %} | |
{{ parent() }} | |
{{ encore_entry_link_tags('admin_article_form') }} | |
{% endblock %} | |
... lines 14 - 22 |
So if we refresh right now, not surprisingly, it still won't work! And it's our favorite error!
$ is undefined
from algolia-autocomplete.js
. Yes, this is the error I see when I close my eyes at night.
Let's get to work. Of course, we are referencing $
. So, import $ from 'jquery'
:
import $ from 'jquery'; | |
... lines 2 - 23 |
We're also using the autocomplete library in here. No problem: import autocomplete from 'autocomplete.js'
:
import $ from 'jquery'; | |
import autocomplete from 'autocomplete.js'; | |
... lines 3 - 23 |
Wait... that's not quite right. This autocomplete.js
library is a standalone JavaScript library that can be used with anything - jQuery, React, whatever. But... our existing code isn't using the "standalone" version of the library. It's using a jQuery plugin - this .autocomplete()
function - that comes with that package:
... lines 1 - 3 | |
$(document).ready(function() { | |
$('.js-user-autocomplete').each(function() { | |
... lines 6 - 7 | |
$(this).autocomplete({hint: false}, [ | |
... lines 9 - 19 | |
]) | |
}); | |
}); |
So, we could refactor our code down here to use the, kind of, official way of using this library - independent of jQuery. But... that's the easy way out! Let's see if we can get this to work as a jQuery plugin.
I'll hold Command
or Control
and click into autocomplete.js
. Then double-click the directory to zoom us there. The "main" file is this index.js
at the root of the directory. But if you look in dist/
, hey! autocomplete.jquery.js
! That's what we were including before via the <script>
tag!
So instead of importing the main file, let's import autocomplete.js/dist/autocomplete.jquery
:
import $ from 'jquery'; | |
import 'autocomplete.js/dist/autocomplete.jquery'; | |
... lines 3 - 23 |
And remember, we don't use import from with jQuery plugins... because they don't return anything: they modify the jQuery object.
Ok, I think we're great and I think we're ready. Move over, refresh and... huh:
jQuery is not defined
Notice it doesn't say "$ is not defined": it says "jQuery is not defined"... and it's coming from autocomplete.jquery.js
! It's coming from the third party package!
This... is tricky. Plain and simple, that file is written incorrectly. Yea, it only works if jQuery is a global variable! And in Webpack... it's not! Let's talk more about this and fix it with some black magic, next.
// composer.json
{
"require": {
"php": "^7.1.3",
"ext-iconv": "*",
"aws/aws-sdk-php": "^3.87", // 3.91.4
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"knplabs/knp-markdown-bundle": "^1.7", // 1.7.1
"knplabs/knp-paginator-bundle": "^2.7", // v2.8.0
"knplabs/knp-time-bundle": "^1.8", // 1.9.0
"league/flysystem-aws-s3-v3": "^1.0", // 1.0.22
"league/flysystem-cached-adapter": "^1.0", // 1.0.9
"liip/imagine-bundle": "^2.1", // 2.1.0
"nexylan/slack-bundle": "^2.0,<2.2.0", // v2.1.0
"oneup/flysystem-bundle": "^3.0", // 3.0.3
"php-http/guzzle6-adapter": "^1.1", // v1.1.1
"sensio/framework-extra-bundle": "^5.1", // v5.3.1
"stof/doctrine-extensions-bundle": "^1.3", // v1.3.0
"symfony/asset": "^4.0", // v4.2.5
"symfony/console": "^4.0", // v4.2.5
"symfony/flex": "^1.9", // v1.17.6
"symfony/form": "^4.0", // v4.2.5
"symfony/framework-bundle": "^4.0", // v4.2.5
"symfony/orm-pack": "^1.0", // v1.0.6
"symfony/security-bundle": "^4.0", // v4.2.5
"symfony/serializer-pack": "^1.0", // v1.0.2
"symfony/twig-bundle": "^4.0", // v4.2.5
"symfony/validator": "^4.0", // v4.2.5
"symfony/web-server-bundle": "^4.0", // v4.2.5
"symfony/webpack-encore-bundle": "^1.4", // v1.5.0
"symfony/yaml": "^4.0", // v4.2.5
"twig/extensions": "^1.5" // v1.5.4
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.0", // 3.1.0
"easycorp/easy-log-handler": "^1.0.2", // v1.0.7
"fzaninotto/faker": "^1.7", // v1.8.0
"symfony/debug-bundle": "^3.3|^4.0", // v4.2.5
"symfony/dotenv": "^4.0", // v4.2.5
"symfony/maker-bundle": "^1.0", // v1.11.5
"symfony/monolog-bundle": "^3.0", // v3.3.1
"symfony/phpunit-bridge": "^3.3|^4.0", // v4.2.5
"symfony/profiler-pack": "^1.0", // v1.0.4
"symfony/var-dumper": "^3.3|^4.0" // v4.2.5
}
}
// package.json
{
"devDependencies": {
"@symfony/webpack-encore": "^0.27.0", // 0.27.0
"autocomplete.js": "^0.36.0",
"autoprefixer": "^9.5.1", // 9.5.1
"bootstrap": "^4.3.1", // 4.3.1
"core-js": "^3.0.0", // 3.0.1
"dropzone": "^5.5.1", // 5.5.1
"font-awesome": "^4.7.0", // 4.7.0
"jquery": "^3.4.0", // 3.4.0
"popper.js": "^1.15.0",
"postcss-loader": "^3.0.0", // 3.0.0
"sass": "^1.29.0", // 1.29.0
"sass-loader": "^7.0.1", // 7.3.1
"sortablejs": "^1.8.4", // 1.8.4
"webpack-notifier": "^1.6.0" // 1.7.0
}
}