JavaScript not loading in Drupal (8) - javascript

Im creating my first site in Drupal (converting an existing site over to the Drupal 8 CMS).
Ive loaded the CSS and Script libraries. The CSS is working but the Script files are not. Im not sure if its the script files not loading or jQuery not loading - or both.
Am I doing something wrong?
Here is the code calling the libraries in the .info file:
libraries:
- saq7704/global-styles
- saq7704/global-scripts
and here is the code in the libraries file:
global-styles:
version: 1.x
css:
theme:
css/styles.css: {}
global-scripts:
version: 1.x
js:
js/scripts.js: {}
js/responsiveTabs.js: {}
dependencies:
- core/jquery

I'm wondering that the CSS is loading. As you have to attach your libraries to some render array explicitly (element, node, page etc.). Declaring them in your module's info file shouldn't do anything at all.
Have a look at the docs on Adding stylesheets (CSS) and JavaScript (JS) to a Drupal 8 module.
To have your libraries loaded on every page you have to use hook_page_attachments:
<?php
/**
* Implements hook_page_attachments().
*/
function MYMODULE_page_attachments(array &$attachments) {
$attachments['#attached']['library'][] = 'saq7704/global-styles';
$attachments['#attached']['library'][] = 'saq7704/global-scripts';
// Also have a look at this gem.
// If you've written your JS file the right way you now could do
// <code>console.log(settings.MYMODULE.foo);</code> in your JS
// and guess what it will print ;)
$attachments['#attached']['drupalSettings']['MYMODULE']['foo'] = 'bar';
}
Read on how to write Drupal JS files the right way:
JavaScript API overview (watch out for Drupal.behaviors, context and settings). Then your *.libraries.yml should better look like:
global-scripts:
version: 1.x
js:
js/scripts.js: {}
js/responsiveTabs.js: {}
dependencies:
- core/jquery
- core/jquery.once
- core/drupalSettings

Related

How to make source maps available with requireJS in Tapestry 5

My goal is to use Bootstrap5 Tooltips with my Tapestry 5.8.1 web application. I try to use requireJS for my JavaScript code as much as possible. So I use the Bootstrap5 JS files in their separated form. That means, I don't use the bundle file but single files like this:
src/main/resources
- META-INF
- modules
- bootstrap5
- alert.js
- alert.js.map
- base-component.js
- base-component.js.map
- ...
- tooltip.js
- tooltip.js.map
In my own JS I activate the tooltips by defining this module:
define(["bootstrap5/tooltip"], function(Tooltip) {
var setuptooltips = function() {
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
return new Tooltip(tooltipTriggerEl)
})
};
return {
"setuptooltips" : setuptooltips
};
})
and then calling require(...).setuptooltips().
That all works. But.
For each *.js file in my modules/bootstrap5 directory I now get a warning on the JavaScript console about the missing source map files:
Source-Map-Fehler: Error: request failed with status 404
Ressourcen-Adresse: http://localhost:8080/webapp/modules.gz/bootstrap5/tooltip.js
Source-Map-Adresse: tooltip.js.map
And I don't know how to resolve this. Tapestry stores all the modules that are actually used in this modules.gz path. I have to knowledge of the inner workings of this. In the debugger I can browser this path and only the files that have been loaded via require() calls are listed their. Obviously, the source map files are missing. Is there a way to either resolve the issue or at least remove the warnings without the need to edit all the Bootstrap5 JS files? Since it is those JS files that refer to the source map files.
Thanks!

A way to load different versions of ExtJs via RequireJS (AMD)

Old code uses deprecated ExtJs version (version 4.x).
New code should use ExtJs 5.x
I try to load ExtJs 5 on the same page where ExtJs 4 has been already loaded and used by some other JavaScript code.
I want to hide ExtJs 5 from the rest of the code. Something like:
define(["../../extjs-5.0.1/ext-all.js"], function (extjs) {
//TODO use the "extjs" as link to Ext js global variable
});
ExtJs is not implemented as AMD module, so I cannot load it as described in the previous example.
Can you please give me a workaround of the issue? Can I use some AMD-wrapper, that is a module itself, and returns "Ext" js variable that is defined in an ext-all.js file.
Is there a way to reuse script that was written as regular JavaScript file (like ExtJs) as AMD - module?
UPDATED: I've read about shim section of RequireJS, here is what I try to do:
On a html page:
<script data-main="../js/configuration/skin/app" src="../requirejs/require-2.1.17.js"></script>
app.js file:
requirejs.config({
baseUrl: '../js',
paths: {
app: 'configuration/skin',
extjs5: '../extjs-5.0.1/ext-all'
},
shim: {
'extjs5': {
exports: 'Ext'
}
}
});
requirejs(['app/main']);
main.js file:
define(['extjs5'], function (extjs5) {
//extjs5 is not nullable, it points to Ext variable
// but Ext.getVersion() points to version 5
});
The problem now, the global Ext variable points to version 5. It may be a problem. I want global Ext js variable is not changed.
When I remove all extjs version 5 related steps, app.js:
requirejs.config({
baseUrl: '../js',
paths: {
app: 'configuration/skin'
}
});
requirejs(['app/main']);
main.js:
define(function () {
// here I test Ext.getVersion() it points to version 4, not 5, as expected
});
In the last method Ext.getVersion() - refers to version 4 which is loaded as default for the page.
How to use in my module ExtJs 5, and don't touch existing global Ext (version 4)?

How to introduce non-core dependencies to js libraries via *.libraries.yml in drupal 8?

I am working on a Drupal 8 template that makes use of a good number of bootstrap plugins on a number of pages. How can I add the non-core Bootstrap library to the dependencies of such plugins in the THEME.libraries.yml file? I don't need the bootstrap framework on all pages - just those with certain plugins included.
Here is a sample code from my *.libraries.yml yet the last line doesn't work.
bootstrap-datepaginator:
js:
assets/global/plugins/.js: {}
css:
theme:
assets/global/plugins/.css: {}
dependencies:
- core/jquery
- THEME_NAME/js/bootstrap
This is how I solved my problem; you just need to add the registered name of the library after the theme_name
bootstrap-datepaginator:
js:
assets/global/plugins/.js: {}
css:
theme:
assets/global/plugins/.css: {}
dependencies:
- core/jquery
- THEME_NAME/LIBRARY_NAME

TypeError: dojo._xdResourceLoaded(...) is not a function

I'm working on a project that requires that some custom Dojo widgets are loaded from another server.
I am wrapping everything with dojo._xdResourceLoaded(function() based on what was suggested at Dojo - Issue loading widget cross-domain
I do get this error
TypeError: dojo._xdResourceLoaded(...) is not a function but my widget works. Not sure why it is throwing this error
We are using dojo 1.6.
dojo._xdResourceLoaded(function(){
return {
depends: [
["provide", "widgets.test"],
["require", "dijit._Widget"],
["require", "dijit._Templated"]
],
defineResource: function(dojo) {
///////////////////////////////
/// Begin standard declaration
dojo.provide("widgets.test");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.declare("widgets.test", [dijit._Widget, dijit._Templated], {
// Our template - important!
templateString: dojo.cache("widgets.test", "templates/Widgettest.html"),
postCreate: function(){...
The reply in the linked thread is not really correct. Your code, like all user code, should not call underscored (private) methods of the Dojo object. These methods are intended for use by Dojo code only.
If you are writing modules that load dependencies cross-domain using the legacy XD loader, you need to require all of your cross-domain dependencies and then wrap your code that uses those dependencies in dojo.ready:
dojo.provide("widgets.test");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.ready(function () {
dojo.declare("widgets.test", [ dijit._Widget, dijit._Templated ], { /* … */ });
});
dojo.ready executes the callback once all the asynchronous dependencies are loaded.
Needless to say, AMD is much better than this, so upgrading to Dojo 1.7+ and using AMD modules would be the best solution as soon as you are capable.

Is it possible to stop requireJS from adding the .js file extension automatically?

I'm using requireJS to load scripts. It has this detail in the docs:
The path that is used for a module name should not include the .js
extension, since the path mapping could be for a directory.
In my app, I map all of my script files in a config path, because they're dynamically generated at runtime (my scripts start life as things like order.js but become things like order.min.b25a571965d02d9c54871b7636ca1c5e.js (this is a hash of the file contents, for cachebusting purposes).
In some cases, require will add a second .js extension to the end of these paths. Although I generate the dynamic paths on the server side and then populate the config path, I have to then write some extra javascript code to remove the .js extension from the problematic files.
Reading the requireJS docs, I really don't understand why you'd ever want the path mapping to be used for a directory. Does this mean it's possible to somehow load an entire directory's worth of files in one call? I don't get it.
Does anybody know if it's possible to just force require to stop adding .js to file paths so I don't have to hack around it?
thanks.
UPDATE: added some code samples as requested.
This is inside my HTML file (it's a Scala project so we can't write these variables directly into a .js file):
foo.js.modules = {
order : '#Static("javascripts/order.min.js")',
reqwest : 'http://5.foo.appspot.com/js/libs/reqwest',
bean : 'http://4.foo.appspot.com/js/libs/bean.min',
detect : 'order!http://4.foo.appspot.com/js/detect/detect.js',
images : 'order!http://4.foo.appspot.com/js/detect/images.js',
basicTemplate : '#Static("javascripts/libs/basicTemplate.min.js")',
trailExpander : '#Static("javascripts/libs/trailExpander.min.js")',
fetchDiscussion : '#Static("javascripts/libs/fetchDiscussion.min.js")'
mostPopular : '#Static("javascripts/libs/mostPopular.min.js")'
};
Then inside my main.js:
requirejs.config({
paths: foo.js.modules
});
require([foo.js.modules.detect, foo.js.modules.images, "bean"],
function(detect, images, bean) {
// do stuff
});
In the example above, I have to use the string "bean" (which refers to the require path) rather than my direct object (like the others use foo.js.modules.bar) otherwise I get the extra .js appended.
Hope this makes sense.
If you don't feel like adding a dependency on noext, you can also just append a dummy query string to the path to prevent the .js extension from being appended, as in:
require.config({
paths: {
'signalr-hubs': '/signalr/hubs?noext'
}
});
This is what the noext plugin does.
requirejs' noext plugin:
Load scripts without appending ".js" extension, useful for dynamic scripts...
Documentation
check the examples folder. All the info you probably need will be inside comments or on the example code itself.
Basic usage
Put the plugins inside the baseUrl folder (usually same folder as the main.js file) or create an alias to the plugin location:
require.config({
paths : {
//create alias to plugins (not needed if plugins are on the baseUrl)
async: 'lib/require/async',
font: 'lib/require/font',
goog: 'lib/require/goog',
image: 'lib/require/image',
json: 'lib/require/json',
noext: 'lib/require/noext',
mdown: 'lib/require/mdown',
propertyParser : 'lib/require/propertyParser',
markdownConverter : 'lib/Markdown.Converter'
}
});
//use plugins as if they were at baseUrl
define([
'image!awsum.jpg',
'json!data/foo.json',
'noext!js/bar.php',
'mdown!data/lorem_ipsum.md',
'async!http://maps.google.com/maps/api/js?sensor=false',
'goog!visualization,1,packages:[corechart,geochart]',
'goog!search,1',
'font!google,families:[Tangerine,Cantarell]'
], function(awsum, foo, bar, loremIpsum){
//all dependencies are loaded (including gmaps and other google apis)
}
);
I am using requirejs server side with node.js. The noext plugin does not work for me. I suspect this is because it tries to add ?noext to a url and we have filenames instead of urls serverside.
I need to name my files .njs or .model to separate them from static .js files. Hopefully the author will update requirejs to not force automatic .js file extension conventions on the users.
Meanwhile here is a quick patch to disable this behavior.
To apply this patch (against version 2.1.15 of node_modules/requirejs/bin/r.js) :
Save in a file called disableAutoExt.diff or whatever and open a terminal
cd path/to/node_modules/
patch -p1 < path/to/disableAutoExt.diff
add disableAutoExt: true, to your requirejs.config: requirejs.config({disableAutoExt: true,});
Now we can do require(["test/index.njs", ...] ... and get back to work.
Save this patch in disableAutoExt.diff :
--- mod/node_modules/requirejs/bin/r.js 2014-09-07 20:54:07.000000000 -0400
+++ node_modules/requirejs/bin/r.js 2014-12-11 09:33:21.000000000 -0500
## -1884,6 +1884,10 ##
//Delegates to req.load. Broken out as a separate function to
//allow overriding in the optimizer.
load: function (id, url) {
+ if (config.disableAutoExt && url.match(/\..*\.js$/)) {
+ url = url.replace(/\.js$/, '');
+ }
+
req.load(context, id, url);
},
The patch simply adds the following around line 1887 to node_modules/requirejs/bin/r.js:
if (config.disableAutoExt && url.match(/\..*\.js$/)) {
url = url.replace(/\.js$/, '');
}
UPDATE: Improved patch by moving url change deeper in the code so it no longer causes a hang after calling undef on a module. Needed undef because:
To disable caching of modules when developing with node.js add this to your main app file:
requirejs.onResourceLoad = function(context, map)
{
requirejs.undef(map.name);
};

Categories