I'm trying to setup a project using jQueryMobile, Backbone and RequireJs. Here is the relevant code snippet:
require([ "jquery", "backbone", "routers/mobileRouter" ],
function( $, Backbone, Mobile ) {
/* do something */
}
) ;
It is actually coming from here. Running the code gives a 404 on 'routers/mobileRouter'
GET http://localhost:9000/scripts/routers/mobileRouter.js 404 (Not Found)
For example, if I search for 'mobileRouter.js' in my project I get the following
./app/bower_components/jquery-mobile/demos/examples/backbone-require/js/routers/mobileRouter.js
./app/bower_components/jquery-mobile/dist/demos/examples/backbone-require/js/routers/mobileRouter.js
These are demos/examples, so how should I load this, maybe I need to install an other package ? Any link to some documentation about this would of course help me too!
UPDATE: here is all the js code
// Sets the require.js configuration for your application.
require.config( {
// 3rd party script alias names (Easier to type "jquery" than "libs/jquery-1.8.3.min")
paths: {
// Core Libraries
jquery: '../bower_components/jquery/jquery',
backbone: '../bower_components/backbone/backbone',
underscore: '../bower_components/underscore/underscore',
jquerymobile:'../bower_components/jquery-mobile/dist/jquery.mobile.min'
},
// Sets the configuration for your third party scripts that are not AMD compatible
shim: {
"backbone": {
"deps": [ "underscore", "jquery" ],
"exports": "Backbone" //attaches "Backbone" to the window object
},
"jquery.mobile": ['jquery']
} // end Shim Configuration
} );
// Includes File Dependencies
require([ "jquery", "backbone", "routers/mobileRouter" ], function( $, Backbone, Mobile ) {
$( document ).on( "mobileinit",
// Set up the "mobileinit" handler before requiring jQuery Mobile's module
function() {
// Prevents all anchor click handling including the addition of active button state and alternate link bluring.
$.mobile.linkBindingEnabled = false;
// Disabling this will prevent jQuery Mobile from handling hash changes
$.mobile.hashListeningEnabled = false;
}
);
require( [ "jquerymobile" ], function() {
// Instantiates a new Backbone.js Mobile Router
this.router = new Mobile();
});
} );
Just add another key/value to your paths:
paths: {
// Core Libraries
jquery: '../bower_components/jquery/jquery',
backbone: '../bower_components/backbone/backbone',
underscore: '../bower_components/underscore/underscore',
jquerymobile:'../bower_components/jquery-mobile/dist/jquery.mobile.min',
jquerymobilerouter: '../bower_components/jquery-mobile/demos/examples/backbone-require/js/routers/mobileRouter.js'
},
then you can use it like this:
require(["jquery", "backbone", "jquerymobilerouter"], function($, Backbone, MobileRouter) {
});
Related
I can't get Backbone.js to play nicely with require.js' bundle system.
This works:
requirejs.config({
baseUrl: 'assets/',
bundles: {
corejs: ['jquery', 'underscore']
},
paths: {
corejs: '../core',
jquery: '../static/js/jquery',
backbone: '../static/js/backbone',
underscore: '../static/js/underscore',
knockout: '../static/js/knockout',
knockback: '../static/js/knockback'
},
shim: {
backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
}
},
deps: ['corejs']
});
require(['app/app'], function(App) {
App.initialize();
});
Changing bundles to be
bundles: {
corejs: ['jquery', 'underscore', 'backbone']
}
results in a require.js timeout
core.js currently consists of concatted jQuery, Underscore, Backbone
Backbone is available on the browser console, even before the timeout.
As #ivarni mentioned in the comments, Backboone has had CommonJS support added:
// Next for Node.js or CommonJS. jQuery may not be needed as a module.
} else if (typeof exports !== 'undefined') {
var _ = require('underscore'), $;
try { $ = require('jquery'); } catch(e) {}
factory(root, exports, _, $);
which means that if you use a recent version of Backbone you can just require it normally without having to create a shim.
Can I load jQuery migrate via RequireJS? I don't understand how the timing can be handled correctly. See this example:
require([
'jquery',
'jqmigrate'
], function ($) {
if ($.browser.msie) {...}
});
Isn't is possible that jqmigrate will load before jquery? Also, I do not want to keep loading jqmigrate explicitly in every module. Any way to do this in the require.config so it loads jqmigrate automatically when jQuery is required?
There are a couple of things you will need:
make sure jqmigrate depends on jquery.
you could write a wrapper module that include both, and return jquery, so your require.config could look like:
jquery-wrapper.js:
define(['jquery-src', 'jqmigrate'], function ($) {
return $;
})
require.config
{
paths: {
'jquery-src' : '/path/to/jquery',
'jqmigrate': '/path/to/jqmigrate',
'jquery': '/path/to/jquery-wrapper'
}
}
using shims worked for me. I did get stuck because i had pluralized shims its; shim
requirejs.config({
paths: {
'jquery': '//code.jquery.com/jquery-2.1.4',
'jquery-migrate': '//code.jquery.com/jquery-migrate-1.2.1'
},
shim: {
'jquery-migrate': { deps: ['jquery'], exports: 'jQuery' },
'foo': ['jquery']
}
});
require(['jquery-migrate', './foo'], ($, foo) => {
console.log('bootstrapped', $, foo);
});
jQuery Migrate 3.0.1 currently has a defect that renders it unusable for RequireJS or any AMD loader. A change is required to the UMD fragment before implementing the accepted answer:
define( [ "jquery" ], function ($) {
return factory($, window);
});
Details and solution are here.
jquery-migrate-wrapper.js
define(['jquery', 'jquery-migrate'], function ($) {
// additional initialization logic can be added here
$.UNSAFE_restoreLegacyHtmlPrefilter();
return $;
})
require-config.js
require.config({
...otherConfigOptions,
shim: {
...otherShimSettings,
'jquery-migrate':{deps: ['jquery']},
},
map: {
// provides 'jquery-migrate-wrapper' for all (*) modules that require'jquery'
'*': { 'jquery': 'jquery-migrate-wrapper' },
// but provides the original 'jquery' for 'jquery-migrate-wrapper' and
// 'jquery-migrate'
'jquery-migrate-wrapper': { 'jquery': 'jquery' },
'jquery-migrate': {'jquery': 'jquery'}
}
})
I've read many answers and followed steps I could ( seems right to me) but still DevTools shows Backbone is not defined. error.
Here's how I use requirejs shim.
<script data-main="js/subject_main.js" src="js/libs/require.js"></script>
subject_main.js
require.config({
paths: {
bootstrap: '../libs/bootstrap.min',
jquery: '../libs/jquery',
underscore: '../libs/underscore',
backbone: '../libs/backbone',
text: '../libs/text',
json2: '../libs/json2',
templates: '../../templates'
},
shim: {
'boostrap':{
deps: ['jquery']
},
'backbone': {
deps: ['jquery', 'underscore'],
exports: 'Backbone'
},
'underscore': {
exports: '_'
}
}
});
require(['subjects', 'json2'], function(app) {
app.initialize();
});
subjects.js
define(['jquery', 'underscore', 'backbone', 'subject_router'], function($, _, Backbone, router) {
return {
initialize: function() {
Backbone.history.start();
}
};
});
subject_router
define([
'jquery',
'underscore',
'backbone',
'models/subject_item_model',
'collections/subjects_collection',
'views/subject_view'
],function($, _, Backbone) {
var AppRouter = Backbone.Router.extend({ ... });
return new AppRouter();
});
Chrome DevTools shows following sequence (order ) of scripts -
As you can see, backbone is loaded at very end. I don't know what's going wrong and where.
backbone.js or underscore.js look fine to me here, and indeed they are being loaded!
The 404s in your dev tool are referring to the source mapping files (underscore.min.map). You might want to look at this post: Missing Javascript ".map" file for Underscore.js when loading ASP.NET web page.
PS: In your subject_router code you have a mismatch on the arguments passed in to the module function.
I'm going a bit crazy here. I'm trying to use Grunt to go through a large RequireJS-based project and combine and minify the results during the deployment process. Here is my grunt process (using grunt-contrib-requirejs):
requirejs: {
compile: {
options: {
baseUrl: "public/js",
mainConfigFile: "public/js/config.js",
name: 'config',
out: "public/js/optimized/script.min.js",
preserveLicenseComments: false
}
}
}
Initially, I was taking the outputted script and placing it in the HTML -- but this lead to the 'define is undefined' error that means that RequireJS wasn't evoked. So instead, I'm putting in the HTML like this:
<script data-main="js/optimized/script.min" src="js/vendor/require.js"></script>
However, now I'm only getting a blank page.
The closest thing I can find out there that sounds like this is here, but's not being super helpful right now. For reference, I was using this as a starting point of my project -- however, when I run it, everything seems to be working for them but I can't find the differences.
Here is my config.js file:
require.config({
//Define the base url where our javascript files live
baseUrl: "js",
//Increase the timeout time so if the server is insanely slow the client won't burst
waitSeconds: 200,
//Set up paths to our libraries and plugins
paths: {
'jquery': 'vendor/jquery-2.0.3.min',
'underscore': 'vendor/underscore.min',
'backbone': 'vendor/backbone.min',
'marionette': 'vendor/backbone.marionette',
'mustache': 'vendor/mustache.min',
'bootstrap': 'vendor/bootstrap.min',
'bootbox': 'vendor/bootbox.min',
'jquery-ui': 'vendor/jquery-ui-1.10.2',
'app-ajax': '../conf/app-ajax',
'common': 'common',
'moment': 'vendor/moment.min'
},
//Set up shims for non-AMD style libaries
shim: {
'underscore': {
exports: '_'
},
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
'marionette': {
deps: ['backbone', 'underscore', 'jquery'],
exports: 'Marionette'
},
'mustache': {
exports: 'mustache'
},
'bootstrap': {
deps: ['jquery']
},
'bootbox': {
deps: ['jquery', 'bootstrap'],
exports: 'bootbox'
},
'jquery-ui': {
deps: ['jquery']
},
'jquery-layout': {
deps: ['jquery', 'jquery-ui']
}
}
});
//Initalize the App right after setting up the configuration
define([
'jquery',
'backbone',
'marionette',
'common',
'mustache',
'bootbox',
'controllers/GlobalController',
'routers/GlobalRouter'
],
function ($, Backbone, Marionette, Common, Mustache, bootbox) {
//Declare ECMAScript5 Strict Mode first and foremost
'use strict';
//Define the App Namespace before anything else
var App = Common.app_namespace || {};
//Create the Marionette Application
App.Application = new Marionette.Application();
//Add wrapper region, so we can easily swap all of our views in the controller in and out of this constant
App.Application.addRegions({
wrapper: '#wrapper'
});
// Set up Initalizer (this will run as soon as the app is started)
App.Application.addInitializer(function () {
//Reach into Marionette and switch out templating system to Mustache
Backbone.Marionette.TemplateCache.prototype.compileTemplate = function (rawTemplate) {
return Mustache.compile(rawTemplate);
};
var globalController = new App.Controllers.GlobalController();
var globalRouter = new App.Routers.GlobalRouter({
controller: globalController
});
//Start Backbone History
Backbone.history.start();
});
//Start Application
App.Application.start();
}
);
Okay, so this is the crazy simple fix:
In the module that's declared after the require.config, use 'require' instead of 'define' when declaring the module.
If you use 'define', it added 'config' as a dependency of that module, which broke the whole thing. Craziness!
I have my bootstrap file which defines the require.js paths, and loads the app and config modules.
// Filename: bootstrap
// Require.js allows us to configure shortcut alias
// There usage will become more apparent futher along in the tutorial.
require.config({
paths: {
bfwd: 'com/bfwd',
plugins: 'jquery/plugins',
ui: 'jquery/ui',
jquery: 'jquery/jquery.min',
'jquery-ui': 'jquery/jquery-ui.min',
backbone: 'core/backbone.min',
underscore: 'core/underscore.min'
}
});
console.log('loading bootstrap');
require([
// Load our app module and pass it to our definition function
'app',
'config'
], function(App){
// The "app" dependency is passed in as "App"
// Again, the other dependencies passed in are not "AMD" therefore don't pass a parameter to this function
console.log('initializing app');
App.initialize();
});
app.js is loaded like it should, and it's dependencies are loaded. it's define callback is called, with all the correct dependencies passed as arguments. No error is thrown. HOWEVER, in the bootstrap's callback, App is undefined! no arguments are passed. What can be causing this? Here's my app file ( modified for space)
// Filename: app.js
define(
'app',
[
'jquery',
'underscore',
'backbone',
'jquery-ui',
'bfwd/core',
'plugins/jquery.VistaProgressBar-0.6'
],
function($, _, Backbone){
var initialize = function()
{
//initialize code here
}
return
{
initialize: initialize
};
}
);
As far as I am aware you should probably just drop the 'app' string in your app.js define method.
// Filename: app.js
define([
'jquery',
'underscore',
'backbone',
'jquery-ui',
'bfwd/core',
'plugins/jquery.VistaProgressBar-0.6'
], function($, _, Backbone){
...
);
Ok I had the same problem, the key is the jquery path alias you define. It turns out that RequireJS has some special handling for jquery. If you use the jquery module name it will do a little bit of magic there.
Depending on what you have in jquery.min.js it may cause some problems, also the jquery plugin you have there may be a problem. Here are the relevant lines of code from the RequireJS source:
if (fullName) {
//If module already defined for context, or already loaded,
//then leave. Also leave if jQuery is registering but it does
//not match the desired version number in the config.
if (fullName in defined || loaded[id] === true ||
(fullName === "jquery" && config.jQuery &&
config.jQuery !== callback().fn.jquery)) {
return;
}
//Set specified/loaded here for modules that are also loaded
//as part of a layer, where onScriptLoad is not fired
//for those cases. Do this after the inline define and
//dependency tracing is done.
specified[id] = true;
loaded[id] = true;
//If module is jQuery set up delaying its dom ready listeners.
if (fullName === "jquery" && callback) {
jQueryCheck(callback());
}
}
For me I have it setup such that I have a file called /libs/jquery/jquery.js which returns the jquery object (just a wrapper for RequireJS). What I ended up doing was simply changing the path alias from jquery to $jquery. This helps avoid the undesired magic behavior.
In the original tutorial I read they use jQuery which also works.
This is a simple example that might help get you started:
I've created a very simple module:
https://gist.github.com/c556b6c759b1a41dd99d
define([], function () {
function my_alert (msg) {
alert(msg);
}
return {
"alert": my_alert
};
});
And used it in this fiddle, with only jQuery as an extra dependency:
http://jsfiddle.net/NjTgm/
<script src="http://requirejs.org/docs/release/1.0.7/minified/require.js"></script>
<script type="text/javascript">
require.config({
paths: {
"jquery": "https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min",
"app": "https://gist.github.com/raw/c556b6c759b1a41dd99d/20d0084c9e767835446b46072536103bd5aa8c6b/gistfile1.js"
},
waitSeconds: 40
});
</script>
<div id="message">hello</div>
<script type="text/javascript">
require( ["jquery", "app"],
function ($, app) {
alert($.fn.jquery + "\n" + $("#message").text());
app.alert("hello from app");
}
);
</script>
This is how I do it with requirejs and backbone:
first, define main or bootstrap file with config:
// bootstrap.js
require.config({
paths: {
text: 'lib/text',
jQuery: 'lib/jquery-1.7.2.min',
jqueryui: 'lib/jquery-ui-1.8.22.custom.min',
Underscore: 'lib/underscore-1.3.3',
Backbone: 'lib/backbone-0.9.2'
},
shim: {
'Underscore': {
exports: '_'
},
'jQuery': {
exports: 'jQuery'
},
'jqueryui': {
exports: 'jqueryui'
},
'Zepto': {
exports: '$'
},
'Backbone': {
deps: ['Underscore', 'Zepto'],
exports: 'Backbone'
}
});
define(function (require) {
'use strict';
var RootView = require('src/RootView');
new RootView();
});
Then, I use this syntax to load my scripts. I find it easier than the array notation to just define my depencies via var declarations.
// rootview.js
define(function (require) {
'use strict';
var $ = require('Zepto'),
Backbone = require('Backbone'),
LoginView = require('./LoginView'),
ApplicationView = require('./ApplicationView'),
jQuery = require('jQuery').noConflict();
return Backbone.View.extend({
// append the view to the already created container
el: $('.application-container'),
initialize: function () {
/* .... */
},
render: function () {
/* .... */
}
});
});
Hope it helps!
This is a bit late, but I just had this problem. My solution can be found here:
https://stackoverflow.com/questions/27644844/can-a-return-statement-be-broken-across-multiple-lines-in-javascript
I posted that question for a different reason, to ask why my fix worked in the first place. Elclanrs provided the perfect answer. To make a long story short, the undefined is probably appearing due to javascript's automatic semicolon insertion: Automatic semicolon insertion & return statements
If you try changing the position of the curly bracket from underneath to directly after the return statement, I think your problem will disappear.
// Filename: app.js
define(
.
.
.
function($, _, Backbone){
var initialize = function()
{
//initialize code here
}
return {
initialize: initialize
};
}
);