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

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)?

Related

JavaScript not loading in Drupal (8)

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

Using D3.JS and the sankey plugin in a require.js module

I'm trying to build a requirejs module giving client code the options to render stuff with d3.js. The first plugin I want to use is a sankey diagram.
My module so far:
define(['d3'], function(ignore) {
console.log("bef", d3);
require(['sankey.js']);
console.log("aft", d3);
d3.sankey();
return {
...
d3: d3,
renderSankey: function(options) {
...
}
}
The sankey.js script uses the global d3 variable and adds the function sankey(). (I tried both btw, define(['d3'], function(ignore) and define(['d3'], function(d3), exactly the same result).
The error: TypeError: d3.sankey is not a function, no matter if I try to call it directly as the code shows or like this.d3.sankey() in the renderSankey function.
The console output says (both times, before and after the require(...) call:
sankey: d3.sankey()
No matter what I try, it won't work. I feel like I missed something JS specific about shadowing, but why is there a sankey function, when I console.log the object and a row later, when I try to call I get an error? What am I doing wrong?
info:
I'm using this inside a splunk html dashboard, this is maybe important...
I don't want the client code to import the dependicies (with about 100 plugins to come, this would be a pain)
When I just copy the content of the sankey.js into my module, everything works fine
/edit: Here is the Require configuration (given by the Splunk Dashboard)
require.config({
baseUrl: "{{SPLUNKWEB_URL_PREFIX}}/static/js",
waitSeconds: 0 // Disable require.js load timeout
});
The require call you are using to load sankey is asynchronous. It will launch the loading of sankey but by the time require returns, sankey is not loaded. You should change your code to:
define(['d3', 'sankey'], function (d3) {
d3.sankey();
I take it that d3 also leaks the symbol d3 in the global space but AMD modules should not rely on global symbols unless these are part of the runtime environment (e.g. window, document).
You also need to set your RequireJS configuration to make sankey dependent on d3 because the define above does not by itself ensure that d3 will load before sankey. So you need this in your configuration:
shim: {
sankey: ['d3']
}
This makes sankey dependent on d3. (Note that shim can only be used to affect the loading of files that are not proper AMD module. sankey does not call define to register itself, and thus is not a proper AMD module, and we can use shim for it.)
Also, module names should generally not have .js in them so when you want to load the plugin, load it as sankey, not sankey.js.
Okay, I think #Louis and I just misunderstood each other. This may be caused by my own stupidity, since I wasn't aware that a configuration of require.js can be done anywhere (and not only once in the root file). How ever, to still get the Splunk specific part I post this answer (instead of accepting Louis'):
I added a new app to my splunk environment to (a viz app). I actually configure the dependencies first (in the by other splunk apps loadable d3-viz module):
require.config({
paths: {
'd3': '../app/D3_Viz/d3', // d3.js
'sankey': '../app/D3_Viz/sankey', // sankey.js
'XYZ': 'all the paths go here'
},
shim: {
'sankey': ['d3'],
'XYZ': ['d3'],
// all the dependecies go here
}
});
define(['splunkjs/ready!', 'jquery', 'd3'],
function(mvc, $, ignore) {
var d3Vis = {
...
renderSankey: function(options) {
// load dependencies dynamically
require(['sankey'], function() {
// actually render things
});
},
renderXYZ: function(options) {
require(['XYZ'], function() {
...
});
},
...
}
}
return d3Vis;
All my dependencies can be configured in the viz-app (and not in the client code using the app, this has been my fundamental missunderstanding of require.js); the only thing to do is loading the app/viz as a whole (in this example in a HTML dashboard:
require([
"splunkjs/mvc",
"splunkjs/mvc/utils",
"splunkjs/mvc/tokenutils",
"underscore",
"jquery",
"splunkjs/mvc/simplexml",
"splunkjs/mvc/headerview",
"splunkjs/mvc/footerview",
...
"../app/D3_Viz/viz"
],
function(
mvc,
utils,
TokenUtils,
_,
$,
DashboardController,
HeaderView,
FooterView,
...
d3Viz
){
... splunk specific stuff
// No dependencies have to be configured
// in the client code
d3Viz.renderSankey({...});
}
);

How can I use a videojs plugin when I also use RequireJS

I'm working on a website that includes some JS code that I do not control. That code uses RequireJS to load dependencies and all.
Disclaimer: I'm a RequireJS noob. I understand the basics, but that's pretty much it...
In my website, I need to use VideoJS. VideoJS can work with, or without RequireJS but from what I understand, if RequireJS is used somewhere in the page, I cannot use VideoJS without it.
So I'm loading VideoJS with RequireJS like this:
var MyRequire = requirejs.config({
baseUrl: '/_/js',
paths: {
videojs: 'http://vjs.zencdn.net/5.3.0/video'
}
});
MyRequire(["videojs"], function(videojs) {
videojs('myPlayer', {}, function(){
console.log('...');
});
});
And it's working.
But I want to use a VideoJS plugin to manage preroll ads. (https://github.com/dirkjanm/videojs-preroll)
I tried to include the plugin script with RequireJS, the script is included but as soon as the plugin tries to access the videojs object, I get an error telling me that videojs is not defined.
My guess is that when I load VideoJS as a RequireJS module, it's not in the global scope and the plugin that I'm using is looking for VideoJS in the global scope and that's why I get that error.
Is there any way I can use VideoJS without loading it as a RequireJS module? Or how can I help the plugin find the VideoJS object?
Thanks for your help!
You should use shim from requirejs and inject videojs into global scope.
I made an example of code for your case. I tested it and it works (you can see images below):
Loading order:
"videojs"
"add-video-js-in-global-scope"
"ads" (at this moment videojs var already in window object)
"preroll"
Requirejs analysis order:
requirejs(["preroll", "ads"] - entry point
"preroll" - requires "ads"
"ads" - requires "add-video-js-in-global-scope"
"add-video-js-in-global-scope" - requires "videojs" and add videojs var in window object.
app.js
requirejs.config({
paths: {
"videojs": "./libs/video",
"ads": "./libs/videojs.ads",
"preroll": "./libs/videojs-preroll"
},
shim:{
"preroll": {
deps: ['ads']
},
"ads": {
deps: ["add-video-js-in-global-scope"],
}
}
});
define("add-video-js-in-global-scope",["videojs"], function(videojs) {
window.videojs = videojs;
});
requirejs(["preroll", "ads"], function (preroll,ads) {
// preroll and ads will be undefined because it's not amd.
videojs('idOne', {}, function () {
var player = this;
player.ads(); // initialize the ad framework
// your custom ad integration code
});
});
index.html
<html>
<head>
</head>
<body>
<script data-main="app.js" src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js"></script>
<div id="idOne"></div>
</body>
</html>
result:
files:

Loading Angular from CDN via RequireJS is not injected

In my project I want to use RequireJS and bootstrap my app as follows:
requirejs.config({
baseUrl: 'scripts/vendor',
paths: {
jquery: [
'https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min',
'jquery'
],
angular: [
'http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min',
'angular'
],
app: '../app'
}
});
require(['require', 'jquery', 'angular', 'app'], function(require, $, angular, app) {
console.log(require);
console.log($);
console.log(angular);
console.log(app);
});
On my index.html only RequireJS is loaded via script tag, where the RequireJS loads the above code.
What works:
- in my Network monitor I can see that RequireJS, jQuery, Angular and app are loaded
- The console.log messages print correct for require, jQuery and app
The angular object is somehow undefined. But if I don't load it from CDN and use my local load, it works! The local file is a RequireJS wrapper that looks like this:
define(['/components/angular/angular.min.js'], function () {
return angular;
});
How do I get this work with Angular'S CDN? Or does this depend on support from Angular?
First, you are confusing "paths" with "shim"
Path is good, don't go for "shim" behavior. But, you need to make your "paths" proper:
paths: {
jquery: 'https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min',
// NOTE: angular is "plain JS" file
angular: 'http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min',
app: '../app'
}
Then, you need to let go of the need to have something returned to you... Just "use the force, Luke" :) and expect the right globals to be there when you need them:
require(['jquery', 'app', 'angular'], function($, app, thisValueDoesNotMatter) {
// you don't need to wrap "require" Just use global
console.log(require);
console.log($);
console.log(app);
// note, angular is loaded as "plain JavaScript" - not an AMD module.
// it's ok. It returns "undefined" but we just don't care about its return value
// just use global version of angular, which will be loaded by this time.
// because you mentioned it in your dependencies list.
console.log(window.angular);
});

How to load ckeditor via requirejs

I'm having issues trying to load ckeditor via requirejs (I've tried converting the main ckeditor js file into individual modules but that has just caused all hell to break loose) and so I'm now checking to see if there is a very simple way to do this that I've missed.
I know requirejs allows you to load normal js scripts so maybe just loading the ckeditor.js file (un-edited, so it's still an IIFE/self-executing function) - would that work with requirejs or if you're using requirejs for loading modules, does the entire project then need to be module based?
Any help appreciated.
Kind regards,
Mark
Alternatively, you can create a RequireJS shim to load things in the correct order, and alias proper RequireJS module names to the CKEditor distribution files.
This means your module still declares it is dependant on CKEditor, which is a lot nicer than having it just show up by magic.
require.config({
shim: {
'ckeditor-jquery':{
deps:['jquery','ckeditor-core']
}
},
paths: {
"jquery": '/javascript/jquery-1.7.1/jquery.min',
'ckeditor-core':'/javascript/ckeditor-3.6.4/ckeditor',
'ckeditor-jquery':'/javascript/ckeditor-3.6.4/adapters/jquery'
}
});
then in a module you can depend on ckeditor-jquery (or ckeditor-core for that matter, if you don't need the jQuery integration) and know it'll be available:
require(
[
"jquery",
"ckeditor-jquery"
],
function( _jquery_ ) {
$('#editorContent2').ckeditor({
customConfig : '',
skin:'office2003'
});
}
}
Another way to do that:
var require = {
"shim": {
"path/foo/ckeditor/ckeditor": { "exports": "CKEDITOR" }
}
};
define(['moduleX', 'path/foo/ckeditor/ckeditor'], function (x, ckeditor) {
ckeditor.editor.prototype.fooFunc = function() {
};
});
OK, it seems I answered my own question here.
Instead of trying to break ckeditor down into modules I just used RequireJs to load the script in it's entirety.
require(['require', 'dependancy-A', 'dependancy-B', 'dependancy-C'], function(require, A, B, C){
// this = [object DOMWindow]
// CKEDITOR_BASEPATH is a global variable
this.CKEDITOR_BASEPATH = '/ckeditor/';
require(['/ckeditor/ckeditor'], function(){
// Code to create a new editor instance
});
});
```

Categories