How to add AMD/legacy dependency (leaflet) with sub dependencies in requirejs - requirejs

I installed a AMD module called leaflet and successfully using it as "L".
Next I need a plugin called leaflet.draw but I get confused about the dependencies. Consider the following code:
requirejs.config({
baseUrl: 'bower_components',
paths: {
leaflet: 'leaflet/dist/leaflet-src',
leafletdraw: 'leaflet-draw/dist/leaflet.draw-src'
...
requirejs(["leaflet", "leafletdraw"], function(L, leafletdraw) {
var map = new L.Map('map');
...
This gives a referenceError: L is not defined at Leaflet.draw.js:4. So I guess it needs the leaflet (L) as a dependency, right? I then tried to add it in the shim config:
shim: {
leafletdraw: {
deps: 'leaflet'
}
}
This results in a "Invalid require call". So my question is: How do I properly require a plugin with subdependencies?
The modules are installed with "bower install leaflet" and "bower
install leaflet-draw" respectivily. But im not sure if leaflet-draw
is AMD enabled. Why isnt that stated in repos docs? Can I assume it
is enabled by default?
This is what I try to achive:
http://codepen.io/osmbuildings/pen/LVJzWw, but with requirejs.

Solution: shim leaflet itself, and let it export 'L'. Then putting the deps in plugins will work. My full config:
requirejs.config({
baseUrl: 'bower_components',
paths: {
jquery: 'jquery/dist/jquery.min',
leaflet: 'http://cdn.leafletjs.com/leaflet-0.7.3/leaflet',
'leaflet-draw': 'http://cdn.osmbuildings.org/Leaflet.draw/0.2.0/leaflet.draw',
OSMBuildings: ['http://cdn.osmbuildings.org/OSMBuildings-Leaflet']
},
shim: {
leaflet: {
exports: 'L'
},
'leaflet-draw': {
deps: ['leaflet']
},
OSMBuildings: {
deps: ['leaflet'],
exports: 'OSMBuildings'
}
}
});
requirejs(["jquery", "leaflet", "leaflet-draw", "OSMBuildings"], function($, L, dummy, OSMBuildings) {
var map = new L.Map('map');

Related

Using non-modular scripts in Typescript

I'm using Typescript AMD and Requirejs in Visual Studio 2013 and I want to use a non-modular script in my Typescript class.
How can I achieve this:
define(["require", "exports", 'slickgrid'], function(require, exports, slickgrid){
...
});
I can't use the following syntax:
import slickgrid = require('slickgrid');
export class myClass {
...
}
When I do I get 2 errors
Unable to resolve external module '"slickgrid"
Module cannot be aliased to a non-module type.
Config looks like this
require.config({
baseUrl: 'scripts',
paths: {
jquery: 'jquery-1.10.2',
jqueryui: 'jquery-ui-1.10.4',
dragevent: 'jquery.event.drag',
slickcore: 'SlickGrid/slick.core',
slickgrid: 'SlickGrid/slick.grid',
},
shim: {
jquery: { exports: '$' },
jqueryui: ['jquery'],
dragevent: ['jquery'],
slickcore: ['jqueryui'],
slickgrid: {
deps: ['slickcore', 'dragevent'],
exports: 'Slick'
},
}
});
Use this definition file : https://github.com/borisyankov/DefinitelyTyped/blob/master/slickgrid/SlickGrid.d.ts
And add the following in some .d.ts file to tell typescript about your requirejs config:
declare module 'slickgrid'{
export = Slick
}
This will allow you to do:
import slickgrid = require('slickgrid');

RequireJS Optimizer throws ReferenceError: text is not defined

I have been using r.js to attempt to minify a fairly large project and I'm having trouble with the text plugin. I am using node.js and a build file that goes as follows:
Build File
({
name: '../main',
baseUrl: '../../js/app',
appDir: "./app",
dir: 'build',
paths: {
jquery: '../lib/jquery/jquery-1.10.2.min',
underscore: '../lib/underscore/underscore-min',
backbone: '../lib/backbone/backbone-min',
text: '../lib/require/text',
picker: '../lib/pickadate/picker',
pickerDate: '../lib/pickadate/picker.date',
pickerLegacy: '../lib/pickadate/legacy'
},
mainConfigFile : '../js/main.js'
})
Main Config File
requirejs.config({
baseUrl: 'js/app',
paths: {
jquery: '../lib/jquery/jquery-1.10.2.min',
underscore: '../lib/underscore/underscore-min',
backbone: '../lib/backbone/backbone-min',
text: '../lib/require/text',
picker: '../lib/pickadate/picker',
pickerDate: '../lib/pickadate/picker.date',
pickerLegacy: '../lib/pickadate/legacy'
},
shim: {
picker: ['jquery', 'pickerLegacy'],
pickerDate: {
deps: ['jquery', 'picker'],
exports: 'DatePicker'
},
backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
underscore: {
exports: '_'
},
text : {
exports : 'text'
}
}
});
The references above are all verified correct. Whenever I try to compile this, I get the following output in the console:
node r.js -o app.build.js
Tracing dependencies for: ../main
ReferenceError: text is not defined
In module tree:
../main
app
router
views/pages/home
views/panel/allStoresPanel
text
Error: ReferenceError: text is not defined
In module tree:
../main
app
router
views/pages/home
views/panel/allStoresPanel
text
at eval (eval at <anonymous> (C:\code\Web\DixonsDashboard\deploy\_compiler\r.js:23699:64), <anonymous>:1:1)
I have no idea why it finds text to be undefined. The path to it is definitely correct - the site works like a charm in it's current expanded format. I have tried all of the options available to r.js and none of them seem to make any difference.
If I delete the file, I get a "No such file or directory" error, so it looks like it's finding the file OK.
Can anybody point out what I'm missing here?
You only configure shim for plugins that are not AMD compatible. The "text" plugin is already AMD compatible so running it through the shim mechanism actually breaks it.
I've just tested with a simplified version of your code: including text in the shim section does show "ReferenceError: text is not defined", removing it makes the build work fine.

whats the correct way to define custom builds of vendor libraries in bower_components?

I am using the yeoman webapp generator with requirejs and I have installed canjs using bower.
canjs has a dir structure like the following
app/bower_components/canjs/amd/can.js
app/bower_components/canjs/amd/can/control.js
app/bower_components/canjs/amd/can/control/route.js
etc..
Inside the can.js file is the following.
define(["can/util/library", "can/control/route", "can/model", "can/view/ejs", "can/route"], function(can) {
return can;
});
All of the dependancy files (control.js, route.js) have their dependancies listed inside define() functions.
What I want to do is customise the canjs build and replace "can/view/ejs" with "can/view/mustache". I can get it to work by changing the reference to ejs within the can.js file but that means I'm editing a vendor file inside of bower_components dir.
I have tried to create a mycan.js build within my scripts dir which looks the same as the can.js file (except for the mustache dependency change) in bower_components and then I change the config to look like this.
require.config({
paths: {
jquery: '../bower_components/jquery/jquery',
can: '../bower_components/canjs/amd/can',
etc..
Then I require the mycan module in any of my files that need it.
This will work properly if I comment out the code inside bower_components/canjs/amd/can.js but if I don't comment the file out, it will require both builds (including the can/view/ejs file I didn't want).
In the require docs http://requirejs.org/docs/api.html under usage 1.1, it has an example of
• www/
• index.html
• js/
• app/
• sub.js
• lib/
• jquery.js
• canvas.js
• app.js
and in app.js:
requirejs.config({
//By default load any module IDs from js/lib
baseUrl: 'js/lib',
//except, if the module ID starts with "app",
//load it from the js/app directory. paths
//config is relative to the baseUrl, and
//never includes a ".js" extension since
//the paths config could be for a directory.
paths: {
app: '../app'
}
});
// Start the main app logic.
requirejs(['jquery', 'canvas', 'app/sub'],
function ($, canvas, sub) {
//jQuery, canvas and the app/sub module are all
//loaded and can be used here now.
});
Here they are using a path which is a directory, not a file. The sub module is getting found because it matches app/sub with the app in the paths config.
If I define my own version of can within the main.js file which contains the require.config then it seems to work but then when I go to build the app, it says
tim#machine:~/server/javascript/yoman:ruby-1.9.3: (master)$ grunt
Running "jshint:all" (jshint) task
Linting app/scripts/main.js ...ERROR
[L54:C1] W117: 'define' is not defined.
define('can', [
Warning: Task "jshint:all" failed. Use --force to continue.
Aborted due to warnings.
Elapsed time
default 567ms
jshint:all 124ms
Total 691ms
Whats the correct way for me to make a custom build of vendor libraries within bower_components?
Here is my main.js. This version works but fails when linting.
require.config({
paths: {
jquery: '../bower_components/jquery/jquery',
bootstrapAffix: '../bower_components/sass-bootstrap/js/affix',
bootstrapAlert: '../bower_components/sass-bootstrap/js/alert',
bootstrapButton: '../bower_components/sass-bootstrap/js/button',
bootstrapCarousel: '../bower_components/sass-bootstrap/js/carousel',
bootstrapCollapse: '../bower_components/sass-bootstrap/js/collapse',
bootstrapDropdown: '../bower_components/sass-bootstrap/js/dropdown',
bootstrapPopover: '../bower_components/sass-bootstrap/js/popover',
bootstrapScrollspy: '../bower_components/sass-bootstrap/js/scrollspy',
bootstrapTab: '../bower_components/sass-bootstrap/js/tab',
bootstrapTooltip: '../bower_components/sass-bootstrap/js/tooltip',
bootstrapTransition: '../bower_components/sass-bootstrap/js/transition',
can: '../bower_components/canjs/amd/can'
},
shim: {
bootstrapAffix: {
deps: ['jquery']
},
bootstrapAlert: {
deps: ['jquery']
},
bootstrapButton: {
deps: ['jquery']
},
bootstrapCarousel: {
deps: ['jquery']
},
bootstrapCollapse: {
deps: ['jquery']
},
bootstrapDropdown: {
deps: ['jquery']
},
bootstrapPopover: {
deps: ['jquery']
},
bootstrapScrollspy: {
deps: ['jquery']
},
bootstrapTab: {
deps: ['jquery']
},
bootstrapTooltip: {
deps: ['jquery']
},
bootstrapTransition: {
deps: ['jquery']
}
}
});
define('can', [
'can/util/library',
'can/control/route',
'can/construct/proxy',
'can/model',
'can/view/mustache',
'can/route'
], function(can) {
'use strict';
return can;
});
require(['app', 'jquery'], function (app, $) {
'use strict';
// use app here
console.log(app);
console.log('Running jQuery %s', $().jquery);
});
JSHint is complaining because require is in an external file. All require's functions are defined before your script loads, but because they're not inside the script JSHint thinks they're custom code which you forgot to define. This is an easy fix; add a predef config so that define, require are already passed to JSHint before it starts linting your files.
jshint: {
options: {
// all of your other options...
predef: ['define', 'require']
},
files : ['app/scripts/main.js']
},

How to use hammer.js plugins with require.js

I am trying to use hammer.js plugins with require.js but I have no luck.
Here is my code:
requirejs.config({
paths: {
"jquery": ('__proto__' in {}) ? "lib/zepto" : "lib/jquery",
"hammer-jquery": "lib/jquery.hammer",
"hammer-showtouches": "lib/hammer.showtouches",
"hammer-fakemultitouch": "lib/hammer.fakemultitouch"
},
shim: {
"jquery": {
exports: "$"
},
"hammer-showtouches": {
deps: [ "hammer-jquery" ],
exports: "Hammer.plugins.showTouches"
},
"hammer-fakemultitouch": {
deps: [ "hammer-jquery" ],
exports: "Hammer.plugins.fakeMultitouch"
}
},
waitSeconds: 30
});
requirejs(["jquery","hammer-jquery","hammer-showtouches","hammer-fakemultitouch"], function ($,Hammer) {
$(function(){
if(!Hammer.HAS_TOUCHEVENTS && !Hammer.HAS_POINTEREVENTS) {
Hammer.plugins.showTouches();
Hammer.plugins.fakeMultitouch();
}
});
});
And here is the error:
Uncaught TypeError: Cannot read property 'plugins' of undefined hammer.showtouches.js:7
Uncaught TypeError: Cannot read property 'plugins' of undefined require.js:8
Uncaught TypeError: Cannot read property 'plugins' of undefined hammer.fakemultitouch.js:7
Uncaught TypeError: Cannot read property 'plugins' of undefined require.js:8
I have tried to include Hammer in shim config with no luck (It's not necessary beacause last version of jquery.hammer is AMD compatible).
Your issue appears to be that you didn't include the hammerjs library which is required by the hammerjs jquery plugin.
To fix this problem, you'll need to add to your requirejs path something like 'hammer':'lib/hammerjs/dist/hammer.min',
Additionally, here's some related information on how I used hammerjs with requirejs.
In my case, I wanted it to work with backbone and requirejs. I installed the libraries with bower.
bower install --save hammerjs
bower install --save backbone.hammer
Then, I proceeded to add the RequireJS configuration:
I noticed that jquery.hammer.js is AMD and automatically requires jquery. It also silently depends on Hammer. It modifies jquery to support Hammer. No shim is required.
I noticed that hammerjs is AMD and automatically exports Hammer. No shim is required.
I noticed that backbone.hammer is AMD and automatically requires underscore, backbone, and hammer. It modifies Backbone to support Hammer. No shim is required.
Therefore, my configuration uses paths only (since no shim support is required):
require.config({
'baseUrl':'',
'paths':{
'underscore':'js/lib/underscore-amd/underscore-min',
'backbone':'js/lib/backbone-amd/backbone-min',
'jquery':'js/lib/jquery/jquery.min',
'hammer':'js/lib/hammerjs/dist/hammer.min',
'jquery-hammer':'js/lib/hammerjs/dist/jquery.hammer.min',
'backbone-hammer':'js/lib/backbone.hammer/backbone.hammer'
},
shim:{
'underscore': { exports: '_' },
'backbone': { deps: ['underscore', 'jquery'], exports: 'Backbone' }
}
});
Wrap HammerJS then bind to the global window:
// #path utils/hammer
define([
'hammer'
], function (Hammer) {
window.Hammer = Hammer;
});
Then make whatever plugins or modules which have dependencies on HammerJS depend on utils/hammer.

RequireJS + Optimizer Include modules defined on the main file

I'm using Optimizer for the first time and I am running in some issues or questions.
I'm trying to optimize a main file and it puts, like I've expected, the jQuery, Backbone and Require modules ( and uses then across the whole navigation). But let's say I have a jQuery Plugin that I use on several views. I've tried to add it in the main file using the "include" option on the build.js file. It adds it ( e.g jQuery Slides ) but as I have a view with define("jquery-slides") ( again, an example ) the browser loads the file of the plugin again. Even if it is on the main built file.
Is this suppose to happen? Can I fix this?
Thanks.
Here is some code. Hope it helps =)
build.js
{
baseUrl: "javascripts/",
appDir: "..",
dir: "dist",
name: "main-site",
include: ['libs/requirejs/require', jquery-slides'],
insertRequire: ['main-site'],
paths: {
"main-site": 'main-site',
'jquery': 'libs/jquery/jquery',
'jquery-slides': 'libs/jquery/plugins/slides.min.jquery'
}
}
main-site.js
require.config({
baseUrl: "/javascripts/",
paths: {
'jquery': 'libs/jquery/jquery',
'underscore': 'libs/underscore/underscore',
'bootstrap': 'libs/bootstrap/bootstrap.min',
'datepicker': 'libs/bootstrap/plugins/bootstrap-datepicker',
'backbone': 'libs/backbone/backbone.max',
'backbone-paginator': 'libs/backbone/plugins/backbone.paginator',
'backbone-validation': 'libs/backbone/plugins/backbone.validation',
'text': 'libs/requirejs/text',
'templates': '/templates/site',
'views': 'views/site',
'jquery-cookie': 'libs/jquery/plugins/jquery.cookie',
'jquery-raty': 'libs/jquery/plugins/jquery.raty.min',
'jquery-slides': 'libs/jquery/plugins/slides.min.jquery'
},
shim: {
'backbone-paginator': ['backbone'],
'bootstrap': ['jquery'],
'datepicker': ['bootstrap'],
'jquery-cookies': ['jquery'],
'jquery-raty': ['jquery'],
'jquery-slides': ['jquery'],
'backbone-validation': ['backbone']
}
});
require([
'app-site'
], function(App) {
$(function(){
App.initialize();
});
});
Instead of using include I recommend you to declare the modules you want to build. In this way requirejs will package the module and all its dependencies in the optimized bundle.
{
baseUrl: "javascripts/",
appDir: "..",
dir: "dist",
paths: {
"main-site": 'main-site',
'jquery': 'libs/jquery/jquery',
'jquery-slides': 'libs/jquery/plugins/slides.min.jquery'
},
modules : [
{
name : 'main-site',
}
]
}
Further considerations:
If you have jquery-slides included as a dependency in any of your modules define(['jquery-slides'], function() {... } you don't need to use the include directive since all the dependencies of that module will be included in the optimized file
See the documentation of the modules property in this link
https://github.com/jrburke/r.js/blob/master/build/example.build.js#L330
Use the property mainConfigFile to avoid duplications https://github.com/jrburke/r.js/blob/master/build/example.build.js#L35
Good luck and I hope this helps you

Resources