All my deps are being found and loaded, but my Application which is the mapApp.js file is never found and always gives me a Undefined when I try to use it.
What am I doing wrong ?
this is my folder hierarchic
Site
|
|- JS
|- Libs
| |- * All my deps *
|
|- mapApp.JS
|
.
.
.
|- /models
|- /views
|- /collections
This is my Main.js file that initialize require.js
require.config({
baseUrl: '/ctt-ct/js/'
,urlArgs: "ts=" + (new Date()).getTime()
,paths: {
'jquery': 'libs/jquery.min'
,'underscore': 'libs/underscore-min'
,'backbone': 'libs/backbone'
,'templates': '../templates'
}
,shim: {
jquery: {
exports: '$'
}
,underscore: {
exports: '_'
}
,backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
}
}
});
require([
'jquery'
,'underscore'
,'backbone'
,'mapApp'
],
function ($, _, Backbone, App) {
$; // <- working
_; // <- working
Backbone.View; // <- working
var app = new App(); // <- NOT working !!!
});
mapApp.js
require([
'jquery'
,'underscore'
,'backbone'
],
function ($, _, Backbone) {
var App = Backbone.View.extend({
el : $('#map_canvas')
,initialize : function(){
// DO a lot of stuff and don't return anything.
}
,drawData: function(){
// Do other stuff.
}
});
});
You must return App from the function :
...
function ($, _, Backbone) {
var App = Backbone.View.extend({
});
return App;
});
Usually, I don't use it require like that, but I'm absolutely not sure of the correct way (the documentation is not very friendly). I would write often :
mapApp.js
define([
'views/otherView' //Other BackboneView
],
function (OtherView) {
var App = Backbone.View.extend({
el : $('#map_canvas')
,initialize : function(){
// stuff ; not too much in a View
}
,render : function(){
var otherView = new OtherView();
...
return this;
}
});
return App;
});
In that case, Backbone, Underscore and jQuery are global variables in the page. I think it make sense as you always need them.
Related
I am trying to make a module that uses jQuery and Handlebars
This is the main file:
require(['app', 'jquery', 'handlebars' ], function (app, $, handlebars) {
console.log('Running jQuery %s', $().jquery);
});
And this is the app file:
define(['jquery', 'handlebars'], function ($, hb) {
$(function() {
var source = $("#some-template").html();
var template = hb.compile(source);
var data = {...});
});
Why is does it say hb is not defined but when I remove all dependencies it works when using Handlebars instead of hb (which is the normal way)?
Handlebars is not AMD/RequireJS compliant. You will need to shim it: http://requirejs.org/docs/api.html#config-shim
shim: {
handlebars: {
exports: 'Handlebars'
},
}
Scenario:
Framework used are backbone and require.
I have a main.js which have several dependencies on util, model and view js, which are again inter-dependent. There are cyclic dependencies also.
This main.js has been compiled into a single file using requirejs optimizer.
Problem:
How to override certain views and models at runtime?
(I have a single compiled version of main, so i am not talking about excluding the js for models or views at compile time).
At compile time i don't know whether the model/view would be over-ridden. So when i run the optimizer a single js file with all the models and views is created.
I need to override a particular class definition in that single js file, such that i don't modify that file.
Is there any configuration which will tell 'require' to load the model/view from a separate file rather than that single compiled js file?
or is there any way this could be achieved, with minimal changes?
//models/ - folder
//mymodel.js - filename
define([
'jquery',
'underscore',
'backbone'
], function($, _, Backbone) {
var mymodel2 = Backbone.Collection.extend({
//some code
});
return mymodel2;
});
//mymodel2.js - filename
define([
'jquery',
'underscore',
'backbone',
'mymodel'
], function($, _, Backbone, mymodel) {
var mymodel2 = Backbone.Collection.extend({
//some code
});
return mymodel2;
});
//views/ - folder
//view1.js - filename
define([
'jquery',
'underscore',
'backbone',
'runtime/util/logmanager',
'runtime/util/logger'
], function($, _, Backbone, LogManager, Logger) {
var view1 = Backbone.View.extend({
_configure: function(options) {
//some code
},
initialize: function() {
//some code
},
endsWith: function(str, suffix) {
//some code
}
});
return view1;
});
//like this i have view2.js, view3.js... etc
//Similarly i have util folder with util1.js, util2.js... etc
//main.js
;(function(){
if (!window.console) window.console = {};
if (!window.console.log) window.console.log = function () { };
var paths = {
jquery: 'libs/jquery/jquery',
underscore: 'libs/underscore/underscore',
initializer: 'runtime/initializer/initializer',
backbone: 'libs/backbone/backbone',
json2: 'libs/json/json2',
text: 'libs/require/text',
jqueryform: 'libs/jqueryform/jqueryform',
jqueryui: 'libs/jqueryui/jquery-ui',
slimscroll: 'libs/slimscroll/slimScroll',
i18next: 'libs/i18next/i18next',
common: 'libs/commons/common',
utility1 : 'util/util1',
utility2 : 'util/util2',
.
.
model2 : 'model/mymodel2',
.
.
.
view2 : 'view/view1'
};
window.configData = window.configData || {};
window.configData.serverPath = location.protocol + "//" + window.location.host;
require.config({
paths: paths,
shim: {
'underscore': {
exports: '_'
},
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
'i18next': {
deps: ['jquery', 'json2'],
exports: 'i18n'
}
}
});
require(['router'],
function(Router) {
Router.initialize();
});
})();
compiled/ combined file will look something like:
*! jQuery v1.7.1 jquery.com | jquery.org/license */
(//jquery-def file code)(window);
// Underscore.js 1.3.3
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
// Underscore is freely distributable under the MIT license.
// Portions of Underscore are inspired or borrowed from Prototype,
// Oliver Steele's Functional, and John Resig's Micro-Templating.
// For all details and documentation:
// http://documentcloud.github.com/underscore
(function() {
//uderscore code
}).call(this);
define("underscore", (function (global) {
return function () {
var ret, fn;
return ret || global._;
};
}(this)));
.
.
.
all lib definition
.
.
then depending on the dependencies models, views, utils, routers, definition
.
.
and finally main
;(function(){
if (!window.console) window.console = {};
if (!window.console.log) window.console.log = function () { };
var paths = {
jquery: 'libs/jquery/jquery-min',
underscore: 'libs/underscore/underscore',
initializer: 'runtime/initializer/initializer',
backbone: 'libs/backbone/backbone',
json2: 'libs/json/json2',
text: 'libs/require/text',
bootstrap: 'libs/bootstrap/bootstrap',
jqueryform: 'libs/jqueryform/jqueryform',
jqueryui: 'libs/jqueryui/jquery-ui',
slimscroll: 'libs/slimscroll/slimScroll',
i18next: 'libs/i18next/i18next',
common: 'libs/commons/common',
utility1 : 'util/util1',
utility2 : 'util/util2',
.
.
model2 : 'model/mymodel2',
.
.
.
view2 : 'view/view1'
};
window.configData = window.configData || {};
window.configData.serverPath = location.protocol + "//" + window.location.host;
require.config({
paths: paths,
shim: {
'underscore': {
exports: '_'
},
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
'i18next': {
deps: ['jquery', 'json2'],
exports: 'i18n'
}
}
});
require(['router'],
function(Router) {
Router.initialize();
});
})();
define("main", function(){});
Is there any configuration which will tell 'require' to load the
model/view from a separate file rather than that single compiled js
file?
To load a Javascript file using require, you can call it at any time (even after the optimizer has been run), like so:
myModule = require('myJavascriptFile');
The optimized file isn't designed to be manipulated. Modify your source, then re-optimize.
Also, note: Require does not compile your Javascript.
How to override certain views and models at runtime?
In Javascript, you can reassign variables at any time. Example:
var x = 1; // the value of x is 1
x = 2; // the value of x is now 2
Similarly, you can override Backbone Models and Views at runtime like so:
var myModel = new Backbone.Model({x: 1});// create myModel
myModel = new Backbone.Model({x: 2});// now, myModel is a different model
myModel = "something else entirely";// now, myModel is a string
You could override require() itself and make it look for the module in a directory first before loading it the way that it normally does.
This probably won't be easy to do.
Am building a single page site with backbone.js. Am using require.js to make the code modular,
but am having problems initializing the backbone router for urls.
I load the main js file using require.js, heres what it looks like
enter code here
//App Namespace
var Chrono = Chrono || {};
//App Config Namespace
Chrono.Config = Chrono.Config || {};
//App Views Namespace
Chrono.Views = Chrono.Views || {};
//Config
Chrono.Config = {
url:"http://localhost/chronotech/",
site_url:"http://localhost/chronotech/index.php/",
data_source:"http://localhost/chronotech/assets/datasource/"
};
require.config({
paths : {
'backbone': 'libs/backbone',
'jquery':'libs/jquery.min',
'underscore':'libs/underscore',
'text':'libs/require/text'
},
baseUrl : 'assets/js'
});
require(
['require', 'underscore', 'backbone', 'jquery'],
function(require,_, Backbone, $) {
require(['app'],
function(require) {
} );
} );
And the app.js looks like this
define(['backbone','routers/workspace'],
function( Backbone,Workspace) {
$(function () {
var space = new Workspace();
} );
} );
And router file looks like this
define(['jquery','backbone'],
function($, Backbone) {
var Workspace = Backbone.Router.extend( {
routes: {
"about":"aboutPage",
"team":"teamPage",
"contact":"contactPage",
"work":"portfolioPage",
"products":"productPage"
},
aboutPage : function() {
alert("about");
},
teamPage : function() {
alert("team");
},
contactPage: function() {
alert("contact");
},
portfolioPage : function() {
alert("work");
},
productPage : function() {
}
} );
return Workspace;
} );
When i load the page, i get the following errors:
"Uncaught ReferenceError: $ is not defined",
"Uncaught TypeError: Cannot read property 'Router' of null".
What am i doing wrong?
define(['backbone','routers/workspace'],
function( Backbone,Workspace) {
$(function () {
var space = new Workspace();
} );
} );
Is it a separate file? Maybe you need to load jQuery in order to use $?
I'm new to RequireJS but seem to be hitting a brick wall.
The trouble starts with my "app" module. I'm not sure how to tell RequireJS to load my leaf modules - packages that depend on "app".
I think I understand why - since nothing in the system depends on them and they aren't registered anywhere, but I need to deal with this case.
How can I let RequireJS know about these modules and to load them appropriately?
Cheers
//index.html
....
<script data-main="app/config" src="/assets/js/libs/require.js"></script>
....
//config.js
require.config({
deps: [ "app" ],
paths: {
libs: "../assets/js/libs",
plugins: "../assets/js/plugins",
jquery: "../assets/js/libs/jquery",
underscore: "../assets/js/libs/underscore",
backbone: "../assets/js/libs/backbone",
marionette: "../assets/js/libs/backbone.marionette"
}
});
//app.js
require(
[ "jquery", "underscore", "backbone", "marionette" ],
function ( $, _, Backbone, Marionette ) {
//....
}
);
//app.view.js
require(
[ "jquery", "underscore", "backbone", "marionette", "app" ],
function ( $, _, Backbone, Marionette, App ) {
//....
}
);
//app.route.js
require(
[ "backbone", "app" ],
function ( Backbone, App ) {
//....
}
);
Hence:
app.js depends on "jquery", "underscore", "backbone", "marionette"
app.view.js depends on "jquery", "underscore", "backbone",
"marionette", "app" app.route.js depends on "backbone", "app"
As stated in the docs ->
http://requirejs.org/docs/api.html#config
dependencies are defined in the deps array. They are the first thing that's loaded when require.js is run, it's really mostly used when you have to define dependencies before you load require.js.
this is what your structure should look like
//config.js
require.config({
paths: {
libs: "../assets/js/libs",
plugins: "../assets/js/plugins",
jquery: "../assets/js/libs/jquery",
underscore: "../assets/js/libs/underscore",
backbone: "../assets/js/libs/backbone",
marionette: "../assets/js/libs/backbone.marionette"
}
});
require(['app']);
//app.js
define(
[ "jquery", "underscore", "backbone", "marionette" ],
function ( $, _, Backbone, Marionette ) {
//....
}
);
//app.view.js
define(
[ "jquery", "underscore", "backbone", "marionette", "app" ],
function ( $, _, Backbone, Marionette, App ) {
//....
}
);
//app.route.js
define(
[ "backbone", "app" ],
function ( Backbone, App ) {
//....
}
);
Bear in mind that all your libraries and modules need to be AMD compliant and if you want to use app as a path like in app.view.js then you need to define it as one. The same with egis, because you can't load modules like so [ "Backbone", "App" ] if they are not defined in require.config as paths.
This is how I startup:
// main.js
define(["jquery", "app", "router"], function ($, App) {
"use strict";
// domReady plugin maybe best used here?
$(function() {
App.start();
});
});
// app.js
define(["backbone", "marionette"], function (Backbone) {
"use strict";
var app = new Backbone.Marionette.Application();
app.on("initialize:after", function(options){
if (Backbone.history){
Backbone.history.start();
}
});
return app;
});
// router.js
define(["backbone", "controller", "marionette"], function(Backbone, controller) {
"use strict";
var Router = Backbone.Marionette.AppRouter.extend({
appRoutes: {
"": "index"
}
});
return new Router({
controller: controller
});
});
// controller.js
define(["view"], function(View) {
return {
"index": {
new View(); // Do what you like hereā¦
}
}
});
// view.js
define(["backbone"], function(Backbone) {
// view here
});
I assume that the dependency to router.js could be put on app.js but basically the call to Backbone.history.start() needs routers to be loaded.
The router has a dependency on the controller. It's the controller that has all the dependencies to the views etc that is used by it. There could be models and collections etc.
Hope that helps.
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
};
}
);