Using TimelineJS and AMD - javascript

I'm looking for a way to use TimelineJS with RequireJS's implementation of AMD. I can get things partially working, e.g.
define(["storyjs", "timelinejs", ...], function(storyjs, timelinejs, ...) {
createStoryJS({
type: 'timeline',
width: '800',
height: '600',
source: { ... }, // sample JSON
embed_id: 'timeline-embed'
});
});
The above produces a timeline, but storyjs (which exports VMM in my RequireJS config) always attempts to perform its own loading of the TimelineJS libraries, which invariably produces errors in the Firebug/developer tools console.
I'm either looking for a way to programmatically build the TimelineJS object (which I couldn't find any examples of), tell StoryJS to not bother loading libs using its mechanism (because I've already provided them) and in general integrate TimelineJS with an AMD solution.
Any suggestions?
UPDATE:
RequireJS configuration used, below. For my own personal use I have a tendency to rename JS libraries and append their version numbers.
var require = {
waitSeconds: 5,
paths: {
"app": "../js/app"
// ** Libraries
,"backbone": "../js/lib/backbone-1.1.0.min"
,"bootstrap": "../js/lib/bootstrap-3.0.2.min"
,"jquery": "../js/lib/jquery-1.10.2.min"
,"jquery-ui": "../js/lib/jquery-ui-1.10.3.min"
,"json2": "../js/lib/json2"
,"underscore": "../js/lib/underscore-1.5.2.min"
// ** TimelineJS
,"storyjs": "../js/lib/storyjs-embed-2.0.3.min"
,"timelinejs": "../js/lib/timeline-2.26.3.min"
// ** RequireJS Plugins
,"domready": "../js/lib/plugins/requirejs/requirejs-plugin-domready-2.0.1"
,"i18n": "../js/lib/plugins/requirejs/requirejs-plugin-i18n-2.0.4"
,"text": "../js/lib/plugins/requirejs/requirejs-plugin-text-2.0.10"
},
shim: {
'backbone': { deps: ['underscore'], exports: 'Backbone' }
,'bootstrap': { deps: ['jquery'] }
,'jquery': { exports: '$' }
,'json2': { exports: 'JSON' }
,'storyjs': { exports: 'VMM' }
,'timelinejs': { deps: ['storyjs'] }
,'underscore': { exports: '_' }
}
};

It took digging into the TimelineJS source a bit to see what exactly createStoryJS was actually doing and then looking at some of the other source code, but I finally answered my own question. In fact, it is relatively straightforward and very similar to my early attempts to make this work before posting my question above to StackOverflow.
RequireJS Config:
// RequireJS config
var require = {
waitSeconds: 5,
paths: {
...
// ** TimelineJS
,"storyjs": "../js/lib/plugins/jquery/storyjs-embed-2.0.3.min"
,"timelinejs": "../js/lib/plugins/jquery/timeline-2.26.3.min"
...
},
shim: {
...
,'storyjs': { deps: ['jquery'], exports: 'VMM' }
,'timelinejs': { deps: ['jquery', 'storyjs'] }
...
}
};
Module instantiating TimelineJS object:
define([ "json2", "timelinejs"], function(JSON, timelinejs) {
var js_version = "2.24",
config = {
version: "2.24", // DEFAULT: 2.x
debug: true,
type: 'timeline',
source: {...} // Sample JSON
};
var timeline = new VMM.Timeline("timeline-embed", 800, 600);
timeline.init(config);
});
This is, at the very least, one example for handling the TimelineJS instantiation using RequireJS/AMD; it is also how I've decided to solve my original issue.

Related

RequireJS, Stripe and dependency (Vue component)

I am using the Stripe library and I've got a vue component that is dependent on the library being loaded first.
I found RequireJS (2.3.6) and having never used it, am just wondering if I'm doing things correctly
I trie using the answer in this question but I can't get it working Load Stripe.js with Require.js
requirejs.config({
paths: {
'stripe': 'https://js.stripe.com/v3/'
},
shim: {
'stripe': {
exports: 'Stripe',
deps:['my-component.js']
}
}
});
I don't get any console errors but I don't see my component either
I worked it out in the end
requirejs.config({
shim: {
form: {
deps: [ 'stripe' ]
}
},
paths: {
stripe: 'https://js.stripe.com/v3/?noext',
form: '/js/my-component'
}
});
require(['stripe', 'form'], function($) {
return {};
});

requirejs duplicate paths entries not working

I have following code as sample to research a problem. In this code "js1 and js2 loaded" never gets called, and no errors. I have tried to debug to log any errors from requirejs, but could not find the root cause.
require.config({
paths: {
jQuery : "jquery",
underScore : "underscore-min",
backBone : "backbone-min",
js1 : "js",
js2: "js"
},
shim: {
'jQuery': {
exports: '$'
},
'underScore': {
exports: '_'
},
'backBone': {
deps: ['underScore', 'jQuery'],
exports: 'Backbone'
}
},
waitSeconds: 0
});
require(["jQuery"], function(){
require(["underScore"], function(){
require(["backBone"], function(){
require(["js1","js2"], function(){
console.log('js1 and js2 loaded');
});
});
});
});
You're not getting any errors because you've set waitSeconds: 0, which disables RequireJS' timeout. See the documentation.
Using paths for this won't work. To be able to load the same actual module under two different names you need to use map:
map: {
"*": {
js2: "js1"
}
}
Note that this does not create two instances of the module. If you compare the module objects you get when you require js1 and js2 you'll see they are the same object. If what you want to do is get multiple instances of an object, you should design your code for such usage.

The jquery.fileupload plugin causes require.js to randomly fail imports

I'm using require.js and have a page with an from that used jquery.fileupload. After introducing the plugin I now see some files fail to be imported before the define call back is executed. This causes random errors where the libraries can't find their dependencies. It's as though require.js is moving on before all the dependencies can be resolved.
I've followed these instructions:
https://github.com/blueimp/jQuery-File-Upload/wiki/How-to-use-jQuery-File-Upload-with-RequireJS
But beyond that it's a very vanilla install. I'm using the minified versions of libraries where possible. Any insight is welcome.
here's the main.js:
(function () {
'use strict';
require.config({
baseUrl: '/js',
waitSeconds: 800,
paths: {
jquery: ['//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min',
'lib/jquery/jquery-2.0.3.min'],
'jquery.fileupload': 'lib/jquery.fileupload/jquery.fileupload',
'jquery.fileupload-ui': 'lib/jquery.fileupload/jquery.fileupload-ui',
'jquery.fileupload-image': 'lib/jquery.fileupload/jquery.fileupload-image',
'jquery.fileupload-validate': 'lib/jquery.fileupload/jquery.fileupload-validate',
'jquery.fileupload-video': 'lib/jquery.fileupload/jquery.fileupload-video',
'jquery.fileupload-audio': 'lib/jquery.fileupload/jquery.fileupload-audio',
'jquery.fileupload-process': 'lib/jquery.fileupload/jquery.fileupload-process',
'jquery.ui.widget': 'lib/jquery.ui/jquery.ui.widget',
'jquery.iframe-transport': 'lib/jquery.iframe-transport/jquery.iframe-transport',
'load-image': 'lib/load-image/load-image.min',
'load-image-meta': 'lib/load-image/load-image-meta',
'load-image-exif': 'lib/load-image/load-image-exif',
'load-image-ios': 'lib/load-image/load-image-ios',
'canvas-to-blob': 'lib/canvas-to-blob/canvas-to-blob.min',
tmpl: 'lib/tmpl/tmpl.min',
bootstrap: 'lib/bootstrap/bootstrap',
bootstrapTab: 'lib/bootstrap/bootstrap-tab',
EventEmitter: 'lib/event_emitter/EventEmitter',
linkedin: ['//platform.linkedin.com/in.js?async=true',
'http://platform.linkedin.com/in.js?async=true'],
skinny: 'lib/skinny/skinny',
selectize: 'lib/selectize/selectize.min',
sifter: 'lib/sifter/sifter',
microplugin: 'lib/microplugin/microplugin.min'
},
shim: {
bootstrap: {
deps: ['jquery'],
},
bootstrapTab: {
deps: ['jquery', 'bootstrap'],
},
linkedin: {
exports: 'IN'
},
selectize: {
deps: ['jquery', 'sifter', 'microplugin']
},
'jquery.iframe-transport': {
deps: ['jquery']
}
}
});
require(['app'], function (App) {
App.initialize();
});
}());
And the from code:
define([], function () {
'use strict';
return function () {
require(['jquery', 'tmpl', 'load-image', 'canvas-to-blob',
'jquery.iframe-transport', 'jquery.fileupload-ui'], function ($) {
$('#product').fileupload({
url: '/products/create'
});
});
};
});
The module gets called after the page has been loaded.
It's also worth noting that all files are downloaded successfully. No 404's, etc.
It turns out there is a flaw in the minified version of load-image.js that breaks how the dependencies load. I don't have exact proof as to why, it could be the smaller size causes a race condition, or it could be something weird in that particular file. What I do know is the minified version causes the random errors and the normal version does not (this is off master so I suppose I was taking a risk).
I raised a flag here
EDIT: it turns out the minified version of the plugin includes all the extensions which explains the odd dependency behavior.
The Answer from matt is the best solution in this case. Thanks a million, it save us a lot of time.
In requirejs.config, you have to add the load-image dependecies separatly - file by file.
For example:
require.config({
'jquery.ui.widget' : 'lib/jQuery-File-Upload-9.9.2/js/vendor/jquery.ui.widget',
'jquery.fileupload':'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload',
'jquery.fileupload-ui': 'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload-ui',
'jquery.fileupload-image': 'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload-image',
'jquery.fileupload-validate':'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload-validate',
'jquery.fileupload-audio':'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload-audio',
'jquery.fileupload-video':'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload-video',
'jquery.fileupload-process': 'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload-process',
'jquery.fileupload-jquery-ui': 'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload-jquery-ui',
'jquery.iframe-transport': 'lib/jQuery-File-Upload-9.9.2/js/jquery.iframe-transport',
'load-image':'lib/load-image-1.10.0',
'load-image-meta':'lib/load-image-meta-1.10.0',
'load-image-ios':'lib/load-image-ios-1.10.0',
'load-image-exif':'lib/load-image-exif-1.10.0',
'canvas-to-blob':'lib/canvas-to-blob-2.0.5',
'tmpl':'lib/tmpl.2.4.1'
}
});
call in html site:
requirejs(['jquery',
'jquery.ui.widget',
'tmpl',
'load-image',
'jquery.iframe-transport',
'jquery.fileupload-ui'], function () {
$('#fileupload').fileupload({
url: 'photo-upload.html'
});
}
);
One possibility modify the shim:
shim: {
bootstrap: {
deps: ['jquery'],
},
bootstrapTab: {
deps: ['jquery', 'bootstrap'],
},
linkedin: {
exports: 'IN'
},
selectize: {
deps: ['jquery', 'sifter', 'microplugin']
},
'jquery.iframe-transport': {
deps: ['jquery']
},
'jquery.fileupload-ui':{
deps: ['jquery']
}
Another option downgrade jquery to 1.X (this is because the sample page is using jquery 1.X)

requirejs window not defined

I'm getting this error when the optimizer is launched by grunt
(I'm using yeoman backbone-generator )
Running "requirejs:dist" (requirejs) task
Error: ReferenceError: window is not defined
I'm using requirejs and the plugin i18n.
This is my main.js
require.config({
//locale: "en",
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: [
'underscore',
'jquery'
],
exports: 'Backbone'
},
'jquery-notify': {
deps: [
'jquery'
]
},
swiper: {
deps: [
'jquery'
],
exports: 'Swiper'
},
bstrapcollapse: {
deps: [
'jquery',
'bstraptransition'
],
exports: 'collapse',
}
},
paths: {
jquery: '../bower_components/jquery/jquery',
backbone: '../bower_components/backbone-amd/backbone',
underscore: '../bower_components/underscore-amd/underscore',
i18n: '../bower_components/requirejs-i18n/i18n',
'backbone.marionette': '../bower_components/backbone.marionette/lib/core/amd/backbone.marionette',
'backbone.wreqr': '../bower_components/backbone.wreqr/lib/amd/backbone.wreqr',
'backbone.babysitter': '../bower_components/backbone.babysitter/lib/amd/backbone.babysitter',
'jquery-ui': '../bower_components/jquery-ui/ui/jquery-ui',
loglevel: '../bower_components/loglevel/dist/loglevel.min',
moment: '../bower_components/moment/moment',
alertify: '../bower_components/alertify/alertify',
swiper: '../bower_components/swiper/dist/idangerous.swiper-2.0.min',
fastclick: '../bower_components/fastclick/lib/fastclick',
bstrapcollapse: '../bower_components/sass-bootstrap/js/bootstrap-collapse',
bstraptransition: '../bower_components/sass-bootstrap/js/bootstrap-transition',
'requirejs-text': '../bower_components/requirejs-text/text',
async: '../bower_components/requirejs-plugins/src/async',
},
config: {
i18n: {
locale: JSON.parse(window.localStorage.getItem('settings')).language || 'en',
}
}
});
I need to change language based on user input that's why i need to fetch localStorage and set the locale in the config.
There's a solution for this?
Thank you.
I haven't done much in the region of runtime javascript, but I know that many of the libraries you know and are used to in browsers (document object model's "getElementById", local storage) are not available in runtimes like Grunt or Rhino. Your use of localStorage in that settings file appears to be the issue.
Instead, you need to make use of whatever API is given to you. For instance, a quick search found some Grunt examples where they read/write to a file on the filesystem: http://gruntjs.com/sample-gruntfile
Obviously, this would be impossible in a browser, as browsers don't let you access files; but you may as well take advantage of it in Grunt. You can also feature-detect which mode you're in with clauses like this:
if (window) {
...
}
else if (grunt) {
...
}
A workaround that worked for me :
config: {
i18n: {
locale: (function(){
try{
return localStorage.getItem('locale') || 'en' ;
}catch(ex){
return 'en';
}
})()
}
}
But still not convinced by this trick. Maybe someone else has a better idea ?

How to handle dependencies with requireJS

This is what my config.js file looks like:
require.config({
baseUrl: '../',
paths: {
jQuery: 'js/jquery-1.10.2.min',
uiEffectsCore: 'js/jQueryUIEffectsCore',
//Handlebars: 'js/handlebars',
SyntaxHighlighter: 'js/syntaxhighlighter/scripts/shCore',
shXml: 'js/syntaxhighlighter/scripts/shBrushXml'
},
shim: {
jQuery: {
exports: 'jQuery'
},
uiEffectsCore: {
deps: ['jQuery']
},
shXml: {
deps: ['SyntaxHighlighter']
}
}
});
require(['js/main']);
Then my main.js looks like this:
define(function(require){
require('jQuery');
require('uiEffectsCore');
require('SyntaxHighlighter');
require('shXml');
});
I think the problem is that there is no define(...) wrapper around my shXml file... I am wondering if I can make this work without having to use that wrapper. Maybe an export shim would do it.
As it stands now, i get this error every time.
This question has also been asked here on github.
Check out this article, also from github. I tested this, and it works great, but you have to replace the first line of your brush.js files (inside syntaxhighlighter) with this line here:
SyntaxHighlighter = SyntaxHighlighter || (typeof require !== 'undefined'? require('shCore').SyntaxHighlighter : null);
I don't even know why that fixes the issue, but it does, and you can load your scripts like this:
define(function(require){
require('jQuery');
require('uiEffectsCore');
require('SyntaxHighlighter');
require('shXml');
require('shCss');
require('shJs');
require('Raphael');
And you need a shim in your config for dependencies:
paths: {
SyntaxHighlighter: 'js/syntaxhighlighter/scripts/shCore',
shXml: 'js/syntaxhighlighter/scripts/shBrushXml',
shCss: 'js/syntaxhighlighter/scripts/shBrushCss',
shJs: 'js/syntaxhighlighter/scripts/shBrushJScript'
},
shim: {
shXml: {
deps: ['SyntaxHighlighter']
},
shCss: {
deps: ['SyntaxHighlighter']
},
shJs: {
deps: ['SyntaxHighlighter']
}
}

Categories