By peterk900 on
I'm struggling with Javascript functionality and want to add jQuery to every page as well as a CDN link. I thought the first could be solved by amending the main theme library - e.g.
global:
js:
core/jquery
but this doesn't work. I've sifted through a lot of posts but can find an example of either use case. (I can achieve both of these requirements by CDN url's between <script> tags on a Basic Page.)
Any help much appreciated. Thanks.
Comments
jQuery seems available in Drupal 12
I am not a JavaScript developer at all, but it seems like jQuery is still available in Drupal 12, after checking with this command in the Firefox console:
But you could share your use case here, in case someone can suggest a plain JavaScript solution?
About CDN's, see CDN / externally hosted libraries > Adding assets (CSS, JS) to a Drupal module via *.libraries.yml.
Thanks ressa
That link was useful. And what you found out about D12.
Returning to my wish to include jQuery on each page...
This script displays a jQuery dropdown in a Drupal article;
But when I remove the CDN link to jQuery and update libraries.yml, it fails, without error.
I have cloned Olivero. This is libraries.yml, where I have added a dependency on jQuery.
The .info file is unaltered...
Can anyone suggest what I'm doing wrong?
You're welcome @peterk900, I
You're welcome @peterk900, I am glad to hear it was useful.
About the theme, you write "clone", but why not create a sub-theme?
In Olivero's olivero.libraries.yml, the
dependenciesitems are only indented one level (two spaces):But, more importantly -- I do not see jQuery mentioned, maybe jQuery support is added by Drupal core?
Well spotted!
Thanks for your continued help on this.
The spacing for the dependencies was wrong. And my words were careless. I am working with an Olivero sub-theme.
I've corrected the spacing problem...
But it still doesn't work.
I understand that jQuery is part of core in D11 but jQuery UI is not. So I installed the jQuery UI module and cleared cache but, sadly, this has had no effect.
This link refers to D11, jQuery 4 and Bootstrap theme problems but as I'm not using Bootstrap, I can't see this as relevant.
I'm not sure what else to try!
Glad that it got more correct
Glad that it got more correct :) Too bad it doesn't work ...
But since jQuery seems to now be difficult to get working in Drupal 11, maybe it is better to aim for a JavaScript solution, hopefully someone has a tip about that.
Thanks
You may be right. JavaScript today has many of the features which jQuery provides. It’s just I’m used to jQuery!
Your current declaration of
Your current declaration of dependencies looks correct. I'm sure you cleared your cache after doing it, but did you clear your cache after doing it? Upon doing so, I would look at the generated HTML to verify whether the jquery library is being included. I'm not seeing any reason it shouldn't be. If it's not, this would seem like a bug, but lets start there.
Contact me to contract me for D7 -> D10/11 migrations.
Sorry for the delay in replying...
I've only just noticed your response. I'm back on the case and I'll carry out the checks you suggest.
Here's an update...
jQuery is being loaded from core...
both with and without the presence of a CDN link.
This code...
pops up the CDN version - 3.7.1.
So it seems to be that the core version of jQuery is loaded when the page is displayed but the script does not use the core code. But a CDN script, as part of page content, is processed and so the jQuery functionality works.
If there is anything I can try to throw light on what's happening, please let me know.
Update
I think the problem may be related to writing HTML/Javascript using Full HTML and in Source mode which means using CKEditor.
When I create a new text format without a text editor and set no options, I find a jQuery example script runs without the need for a CDN - which means it's using the jQuery code which comes from core. At a stroke, this may solve all the above issues! Interestingly, including a CDN link appears to have no effect.
I'll play with this a little more and post again but I'm fairly convinced CKEditor was responsible for the problem.
Ahhhh I see what has happened
Ahhhh I see what has happened. I didn't look closely enough at the JavaScript you were using in your code. Drupal includes jQuery when the core/jquery library is included, however it does not alias the
jQueryobject into the$variable, in order to prevent conflicts with other libraries. So when you try to do something like:$("body")You will get an error that jQuery is not present, for even though jQuery is present in the DOM, the
$alias does not (yet) exist. To use jQuery in raw, global JavaScript, you have to call thejQueryobject directly:Using the
$alias in your code in an anonymous function that aliases thejQueryobject:I wrote a tutorial for Drupal 7 on using JavaScript that is almost all still entirely valid: https://www.jaypan.com/tutorial/high-performance-javascript-using-drupal...
The only real difference from that tutorial and current Drupal versions is that jQuery
$.once()no longer exists, and insteadonceis used as follows:Contact me to contract me for D7 -> D10/11 migrations.
Thanks for your continued help...
What I wrote earlier about changing Text Format solving the problem isn't repeatable, so maybe it was a cache issue. As I think you realised, changing Text Format does not have any bearing on this issue.
I've enclosed the Javascript in my script in a function as you suggested...
But the Javascript fails to run even though the page source shows jQuery is loaded, as my code snippet above shows. What am I doing wrong?
I'm guessing it's due to
I'm guessing it's due to adding the library in script tags, rather than using the Drupal JS API, and adding it as a Drupal library with a dependency on core/jquery. Using the APIs ensure that the files/scripts are loaded in the correct order.
You can read about the APIs here: https://www.drupal.org/docs/drupal-apis/javascript-api/javascript-api-ov...
Main points:
Contact me to contract me for D7 -> D10/11 migrations.
I've done the first two main points...
I've done the first two main points and looked at the link you provide for Drupal behaviours. But I'm not sure how to use Drupal.behaviours in a web page. My research, including looking at the API link you provide, suggests this is module code which isn't what I want. My use case is creation of an article on the fly where I want a bit of jQuery interactivity. At the moment the only way I can do this in D11 is with a jQuery CDN link - which actually works well and shows no performance hit that I can detect. And a recent web post seems to support this view. That said, I'd still like to find a way I can use Drupal site installed jQuery inside <script> tags or to hear that it simply isn't possible. Can someone share <script> based code which does what I want and works without requiring module code? Thanks.
Drupal behaviors is a
Drupal behaviors is a replacement for
$(document).ready(). It's not specific to modules; core, modules and themes can all add JS files, and these files can each add one or more elements toDrupal.behaviors. So the link I gave you is applicable also to your JS file that you are adding to your theme.In the background, Drupal core creates the
Drupalobject, with thebehaviorselement, early in the pipeline with this code:After that, core, modules, and themes, can add their own elements to the
Drupal.behaviorselement.Bringing this all together. This code:
is replaced in Drupal by adding an element containing an
attach()method to theDrupal.behaviorsobject:When the document (page) has loaded, Drupal loops through all elements of the
Drupal.behaviorsobject, and executes theattach()method for each object. In this case, it will pop up the thealert()text on page load.Note however that there is one major difference between
$(document).ready()andDrupal.behaviors. The former is only called on page load, the latter is called on page load and after any AJAX requests. It is called after AJAX requests, so that handlers can be attached to any new HTML being inserted in the DOM from the AJAX request. Due toDrupal.behaviorsbeing called multiple times, the code below, which looks like it should be fine, can become a problem that requires a fix:With the above code, the click handler is attached on page load, and when
a.some-selectoris clicked, the alert will fire. But then, if some ajax on happens on the page, the above code is executed again, and the click handler is attached again. So whena.some-selectoris clicked with the handler attached twice, the alert is fired twice. If more AJAX is fired, the handler keeps getting attached again again. The fix for this is to useonce():Selectors found with
once('my-module', a.some-selector')are only executed once (tracked using the key passed as the first argument, in this casemy-module), so whena.some-selectoris first loaded, whether that be on the initial page load, or a subsequent AJAX request, the handler is attached, but then on subsequent AJAX calls, will not be re-attached.Final structure of the code, wrapped in an anonymous function:
Contact me to contract me for D7 -> D10/11 migrations.
Thanks...
Thank you for this detailed explanation. With what you've written and re-reading your D7 article, I'm I now much clearer on Drupal.behaviours and how to use this functionality to achieve what I want. Support like you have provided here and in the past is one key reason why I continue to develop in Drupal. Your help is much appreciated.
Happy to have helped :)
Happy to have helped :)
Contact me to contract me for D7 -> D10/11 migrations.
After so much help, I'm hesitant to ask more...
I've now got Drupal.behaviours to write to the browser console just once. Great! And thanks once again.
olivero-clone-1/js/olivero-clone-1.js
olivero-clone-1.js
But when I try to modify the code to use jQuery to add a click event to every <p> tag and change the text color, the code fails.
For example, I tried this code which fails completely...
The jQuery code works fine in a Drupal page with a <script> tags for the code and a jQuery CDN.
If you can point out what's wrong with my script that would be great.
Updated
I've managed to specify jQuery and it's $ alias correctly. And I think the Javascript in the above post was in error. This code now does what I want.
So it looks as though the support I've got might really mean I'm getting the hang of Javascript and Drupal! Thanks again.
You're close, but I would
You're close, but I would change it to this:
While your code would have worked, it was doing something slightly different; I optimized it a bit.
With the code you had, your call to once() was finding the HTML tag, and then if it finds it, executing on all found <p> tags. Where you would run into a problem is if an ajax call returned an iframe. Iframes contain <html> tags, and I believe your code would fire again, and re-apply the internal code to all found p tags.
The change I made was so that each <p> tag ever loaded on the page, both first page load, and any returned from future ajax calls, will have the color applied once. Then that <p> tag will not be found the next time once('my-once-key', 'p') is called.
Contact me to contract me for D7 -> D10/11 migrations.
Got it!
Thanks for this. You've helped me understand 'Once' a bit better.
Glad to have helped.
Glad to have helped :)
Contact me to contract me for D7 -> D10/11 migrations.