im struggling with a weird Issue with Backbone.Marionette an requireJS.
RquireJS is configured like https://github.com/marionettejs/backbone.marionette/wiki/Using-marionette-with-requirejs says:
require.config({
deps: ['main'],
paths : {
backbone : '../vendor/backbone.marionette/backbone',
underscore : '../vendor/underscore/underscore',
jquery : '../vendor/jquery/jquery',
marionette : '../vendor/backbone.marionette/backbone.marionette.min'
},
shim : {
jquery : {
exports : 'jQuery'
},
underscore : {
exports : '_'
},
backbone : {
deps : ['jquery', 'underscore'],
exports : 'Backbone'
},
marionette : {
deps : ['jquery', 'underscore', 'backbone'],
exports : 'Marionette'
}
}
});
The main.js:
require([
'app'
],
function(App) {
App.start();
}
);
And the app.js:
define([
'marionette'
],
function(Marionette) {
var app = Marionette.Application();
return app;
}
);
But when I wanna start a Application my Console says:
Uncaught TypeError: Object #<Object> has no method '_initRegionManager'
I did nothing special so far:
define(
[
'marionette'
],
function(Marionette) {
"use strict";
var app = Marionette.Application();
// app.on('initialize:after', function() {
// console.log("Initialize:After");
// });
return app;
}
);
And in the main.js (Startingpoint) i require the code above and wanna start it.
But it fails at Marionette.Application();
When i look into the marionette.js i can clearly see underscore extending the Application with the _initRegionManager-Method. Also in the Prototype-list of the Marionette-Object i can see the method.
Any ideas what i'm missing here?
Your require.config ({ … }) should be in main.js and also as Ratweb_on indicated, there should not be “deps: [‘main’]” in the require.config.
You can follow this example in here, and ignore the jquerymobile stuffs. Essentially it dose the initialization in the same way as your code intended.
See main.js and app.js.
Updated
In your app.js
var app = Marionette.Application();
Should be
var app = new Marionette.Application();
Related
I am using requirejs and gulp to build angular app. I am using amd-optimize and gulp-requirejs-optimize to add all js files into single file. Here is my main.js file:
require.config(
{
paths: {
app : 'app',
angular : '../bower_components/angular/angular',
jquery : '../bower_components/jquery/dist/jquery',
angularResource : '../bower_components/angular-resource/angular-resource',
angularRoute : '../bower_components/angular-route/angular-route',
publicModule : 'public_module',
route : 'route'
},
shim: {
'app': {
deps: ['angular']
},
'angularRoute': ['angular'],
angular : {exports : 'angular'}
}
}
);
And gulpfile.js
var gulp = require('gulp');
var rjs = require('gulp-requirejs');
var connect = require('gulp-connect');
var requirejsOptimize = require('gulp-requirejs-optimize');
var amdOptimize = require('amd-optimize');
var concat = require('gulp-concat');
// using amd-optimize.
gulp.task('bundle', function () {
return gulp.src('app/**/*.js')
.pipe(amdOptimize('main'))
.pipe(concat('main-bundle.js'))
.pipe(gulp.dest('dist'));
});
// using gulp-requirejs-optimize.
gulp.task('scripts', function () {
return gulp.src('app/main.js')
.pipe(requirejsOptimize())
.pipe(gulp.dest('dist'));
});
When I run gulp bundle or gulp scripts, it shows me same content of main.js file in output file(not showing all js template in one output file).
The output file is:
require.config({
paths: {
angular: '../bower_components/angular/angular',
jquery: '../bower_components/jquery/dist/jquery',
angularResource: '../bower_components/angular-resource/angular-resource',
angularRoute: '../bower_components/angular-route/angular-route',
publicModule: 'public_module',
route: 'route'
},
shim: {
'app': { deps: ['angular'] },
'angularRoute': ['angular'],
angular: { exports: 'angular' }
}
});
define('main', [], function () {
return;
});
How can I configure gulp to put every js template into one js file?
check the docs for all the options for amdoptimize. For example you can point to your config file or add paths.
I always have trouble getting all the paths to line up, so make sure to check them diligently.
here is how you can start to put the options in:
gulp.task('requirejsBuild', function() {
gulp.src('app/**/*.js',{ base: 'app' })
.pipe(amdOptimize("app",{
baseUrl: config.app,
configFile: 'app/app-config.js',
findNestedDependencies: true,
}))
.pipe(concat('app.js'))
.pipe(gulp.dest('dist'))
});
You are not requiring any files - you just define an empty module named main.
You need to kick off you app by requiring a module, eg.
require(['app'], function (App) {
new App().init();
});
On some occasions, requirejs returns an undefined object to my module. I've looked at a number of posts and most of the answer are related to circular dependencies. However I could find none (I have checked several times). I apologize by advance for pasting a quantity of code that I've tried to reduced to the minimum :) Any help would be greatly appreciated!
Here is the module init_app.js that fails:
define([
'marionette',
], function(
Marionette
) {
"use strict";
var App;
App = new Marionette.Application();
App.addRegions({ body: "#main_body" });
return App;
});
Sometimes the Marionette module is undefined. Here is the part of my config.js that might be relevant:
define([], function() {
'use strict';
require.config({
baseUrl: 'js',
paths : {
underscore : 'vendors/underscore/underscore',
jquery : 'vendors/jquery/dist/jquery',
backbone : 'vendors/backbone/backbone',
marionette : 'vendors/marionette/lib/backbone.marionette',
wreqr : 'vendors/backbone.wreqr/lib/backbone.wreqr',
eventbinder : 'vendors/backbone.eventbinder/lib/backbone.eventbinder',
babysitter : 'vendors/backbone.babysitter/lib/backbone.babysitter',
},
shim : {
jquery : {
exports : 'jQuery'
},
underscore : {
exports : '_'
},
backbone : {
deps : ['jquery', 'underscore'],
exports : 'Backbone'
},
wreqr: {
deps : ['backbone'],
exports: 'Backbone.Wreqr'
},
eventbinder : {
deps : ['backbone']
},
babysitter : {
deps: ['backbone']
},
marionette : {
deps: ['backbone', 'wreqr', 'eventbinder', 'babysitter'],
exports : 'Marionette'
},
}
});
});
The main.js file is
require(['config'], function() {
require( ['app'], function (App) {
App.start({});
});
});
where the app.js file is
define([
'init_app',
'router',
], function(
App,
Router
) {
"use strict";
App.on('start', function() {
new Router();
Backbone.history.start();
});
return App;
});
And the router will define a bunch of things that might depend on init_app.js. I've been especially carefull that none of them defines the app.js, which should be sufficient to guaranty that no circular dependency could cause this bug. Any clue??
You should review your shim configuration to remove all those shims that you've put in for modules that actually use define. For instance, jQuery uses define and thus does not need a shim. The same is true of Marionette. I've just installed it with Bower and found this towards the start of the file:
if (typeof define === 'function' && define.amd) {
define(['backbone', 'underscore'], function(Backbone, _) {
return (root.Marionette = root.Mn = factory(root, Backbone, _));
});
}
...
If you see something like this in a module you use, or a flat out call to define, then you should not use a shim for it.
I've not checked every single module you use. Please review all of them to make sure you do not use shims where not needed. If you use shims incorrectly, you can get undefined values for your modules.
Here is how I solved it: I changed the main.js to
require(['config'], function() {
require( ['init_app'], function () {
require( ['app'], function () {
App.start({});
});
});
});
and put the App in the global scope in init_app. This works well but doesn't explain the previous failure.
I am new using RequireJS and I have a problem with it, this is the error:
Uncaught TypeError: Object [object Object] has no method 'jarvismenu'
This my code:
app.js (RequireJS main configuration):
/*global define, angular */
'use strict';
requirejs.config({
paths: {
'jquery' : 'libs/jquery-2.0.2.min',
'jqueryui' : 'libs/jquery-ui-1.10.3.min',
'jquerytouch' : 'plugin/jquery-touch/jquery.ui.touch-punch.min',
'bootstrap' : 'bootstrap/bootstrap.min',
'smartnotification' : 'notification/SmartNotification.min',
'jasviswidget' : 'smartwidgets/jarvis.widget.min',
'jqueryeasypiechart' : 'plugin/easy-pie-chart/jquery.easy-pie-chart.min',
'sparkline' : 'plugin/sparkline/jquery.sparkline.min',
'jqueryvalidate' : 'plugin/jquery-validate/jquery.validate.min',
'jquerymaskinput' : 'plugin/masked-input/jquery.maskedinput.min',
'select' : 'plugin/select2/select2.min',
'bootstrapslider' : 'plugin/bootstrap-slider/bootstrap-slider.min',
'jquerymbbrowser' : 'plugin/msie-fix/jquery.mb.browser.min',
'fastclick' : 'plugin/fastclick/fastclick',
'demo' : 'demo',
'appDash' : 'appDash',
//controller
'dashboard-ctrl' : 'controllers/DashboardCtrl',
'home-ctrl' : 'controllers/HomeCtrl',
'report-ctrl' : 'controllers/ReportCtrl',
'instance-ctrl' : 'controllers/InstanceCtrl',
//services
'report-service' : 'services/ReportService',
'instance-service' : 'services/InstanceService',
'util-service' : 'services/UtilService',
//directives
// taxonomyDrtv : 'directives/TaxonomyDrtv',
'directives' : 'directives/Directives'
//service
// taxonomyServices : 'services/TaxonomyService'
//filters,
},
shim: {
jqueryui : ['jquery'],
jquerytouch : ['jquery'],
smartnotification : {
deps :['jquery'],
exports : 'jQuery'
} ,
bootstrap : ['jquery'],
jasviswidget : ['jquery'],
jqueryeasypiechart : ['jquery'],
jqueryvalidate : ['jquery'],
jquerymaskinput : ['jquery'],
jquerymbbrowser : ['jquery'],
select : ['jquery'],
bootstrapslider : ['jquery','bootstrap'],
demo : ['jquery'],
appDash : {
deps : ['jquery','jqueryui','jasviswidget','bootstrap','jquerytouch','smartnotification','sparkline'],
exports : 'jQuery'
}
}
});
define('jquery-private', ['jquery'], function (jq) {
return jq.noConflict( true );
});
require([
'jquery',
'jqueryui',
'jquerytouch',
'bootstrap',
'smartnotification',
'jasviswidget',
'jqueryeasypiechart',
'sparkline',
'jqueryvalidate',
'jquerymaskinput',
'select',
'bootstrapslider',
'jquerymbbrowser',
'fastclick',
'demo',
'appDash'
], function($){
$(document).ready(function(){
pageSetup(); <<<<< I want to Load this method on on page load
});
console.log($);
});
appDash.js:
$.fn.extend({
//pass the options variable to the function
jarvismenu : function(options) { << this jarvis menu variable which cannot load
............
............
}
});
$(document).ready(function() {
if (!null) {
$('nav ul').jarvismenu({
accordion : true,
speed : $.menu_speed,
closedSign : '<em class="fa fa-expand-o"></em>',
openedSign : '<em class="fa fa-collapse-o"></em>'
});
} else {
alert("Error - menu anchor does not exist");
}
});
function pageSetUp() { << i want to call this code but when i call this method it call jquery ready above too.., the problem is he cannot read jarvismenu variable from jarvis menu above
// some code
}
when application is start (first request) is work fine no error found..
but when i refresh (second request) there are an error above.
You're getting that error because appDash contains a jquery extension.
Take this chunk of code out of appDash.js
$.fn.extend({
//pass the options variable to the function
jarvismenu : function(options) {
... rest of code
}
});
Put it in a file of it's own eg 'jarvis-menu-ext.js'.
Add that to your paths and shim.
'jarvis-menu-ext' : 'libs/jarvis-menu-ext',
'jarvis-menu-ext' : ['jquery'],
Also add it to your require call in app.js.
require([
'jquery',
'jqueryui',
'jquerytouch',
'bootstrap',
'smartnotification',
'jasviswidget',
'jarvis-menu-ext' <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
'jqueryeasypiechart',
'sparkline',
'jqueryvalidate',
'jquerymaskinput',
'select',
'bootstrapslider',
'jquerymbbrowser',
'fastclick',
'demo',
'appDash'
], function($){ ...
I've got the following requireJS config. When trying to reference the package/ImagingX module I always get undefined even though I can see that the script has been loaded in firebug. If I move the js file in question into the baseUrl directory and remove package/ it works as expected.
What am I doing wrong?
window.requirejs.config(
{
baseUrl: '/Scripts',
paths: {
"jquery": "./jquery-1.7.1.min",
"jqx": "/Content/Plugins/jqWidgets",
"package" : "/Scripts/packages"
},
urlArgs: "bust=" + (new Date()).getTime(),
shim : {
'jqx/jqxcore': ['jquery'],
'jqx/jqxsplitter': ['jquery','jqx/jqxcore']
}
}
);
window.require(['jquery', 'layoutManager', 'container', 'package/ImagingX'],
function ($,lm,container,px) {
px.Focus();
$(document).ready(function () {
lm.Init(); // Sets up panes
container.Init(); //Set up the containers
});
});
Update 15/10/2012
I'm getting desperate to solve this issue now, I've stripped everything back to the basics so here is the new main file :
(function () {
requirejs.config({
paths: {
"packages": "packages"
}
});
require([
'packages/testmodule'
],
function (tm) {
alert(tm);
});
})();
And the module which is in a sub folder called packages.
define('testmodule',
function () {
alert("called");
return {
set : 'rar '
};
});
I can see the script loaded but it never gets executed, hence I never get a reference for it.
requirejs.config({
paths: {
//"jquery": "./jquery-1.8.2.min",
//"jqx": "/Content/Plugins/jqWidgets",
"templates": 'templates',
"text": "commonRequireJsModules/text",
"domReady": "commonRequireJsModules/domReady",
"packages" : 'packages/'
//'signalR': './jquery.signalR-0.5.3.min',
//'knockout': './knockout-2.1.0',
//'pubsub' : './pubsub'
}
//,urlArgs: "bust=" + (new Date()).getTime()
//,
//shim : {
// 'jqx/jqxcore': ['jquery'],
// 'jqx/jqxsplitter': ['jquery', 'jqx/jqxcore'],
// 'signalR': ['jquery'],
// 'pubsub' : ['jquery']
//}
});
The trailing slash on the packages path seems to have addressed the issue, in part with also removing the name in the define part of the module. So it now looks like
define(['deps'],function(deps){
});
Rather than
define('myMod',['deps'],function(deps){
});
Couple of things:
it seems strange to use window.require instead of just require
names in 'shim' must match names in 'paths', this is not the case, here
document.ready is done for free by require, no need to do it again
So: do you have any loading error in your JS console? Does it says a script is missing?
Here is a working require configuration, Router is in the same folder of this code:
require.config({
paths:{
'jquery':'lib/jquery.min',
'backbone':'lib/backbone.min',
'underscore':'lib/underscore.min',
'router':'Router'
},
shim:{
'backbone':{ deps:['jquery', 'underscore'] },
'router':{ deps:['backbone'] }
}
});
require(['router', 'jquery', 'underscore', 'backbone'],
function (Router) {
var router = new Router();
$('img').hide();
});
});
And the index.html:
<html>
<head>
<script data-main="assets/js/App.js" src="assets/js/lib/require.min.js"></script>
</head>
<body>...</body>
</html>
Can some one post an example of combining these libraries together?
including the handler for the i18n and marionette.
Thanks
point backbone.marionette templates to compile hendlebars.
this can be done on your main.js:
Backbone.Marionette.TemplateCache.prototype.compileTemplate = function(rawTemplate) {
return Handlebars.compile(rawTemplate);
};
configure your app to use handlebars and i18n:
this can be done on your config.js:
require.config({
// Initialize the application with the main application file
deps: ["main"],
paths: {
libs: "../assets/js/libs",
plugins: "../assets/js/plugins",
// Libraries
jquery: "../assets/js/libs/jquery",
underscore: "../assets/js/libs/lodash",
backbone: "../assets/js/libs/backbone",
marionette: "../assets/js/libs/backbone.marionette",
handlebars: "../assets/js/libs/handlebars",
//plugins
text : "../assets/js/plugins/text",
i18n : "../assets/js/plugins/i18n",
},
config: {
//Set the config for the i18n
//module ID
i18n: {
locale: 'fr-fr'
}
},
shim: {
marionette: {
deps: ['backbone'],
exports: 'Backbone.Marionette'
},
backbone: {
deps: ["underscore", "jquery"],
exports: "Backbone"
},
handlebars: {
deps: [],
exports: "Handlebars"
}
}
});
use it on any of your modules:
define([
'jquery',
'underscore',
'backbone',
'marionette',
'handlebars',
'text!templates/template.html',
'i18n!nls/your_i18n_text'
],
function($, _, Backbone, Marionette, Handlebars, tmpl, msg) {
'use strict';
var mod = Backbone.Model.extend({
defaults: function() {
return {
feedUrl : "this is for test"
};
}
});
view = Backbone.Marionette.ItemView.extend({
template: Handlebars.compile(tmpl),
model: new mod(),
initialize: function() {
this.tmpl_data = msg;
if(msg && this.model)
this.tmpl_data = _.extend(this.model.toJSON(),msg);
},
render: function() {
var view = this;
$(this.el).html(this.template(view.tmpl_data));
return this;
}
});
});
this will fetch templates + i18n files and render
I use i18n-JS, which is everything-agnostic, so you can use it with any server-side framework (Ruby on Rails for me) and any Javascript template engine (Haml Coffee for me).
Here is an example:
%form.form-horizontal
.modal
.modal-header
%button{ class: 'close', data: { dismiss: 'modal' } } ×
%h3
= I18n.t(#property.get('name'), scope: 'data_sheets.properties')
.modal-body
- unless #property.get('editable')
%p= I18n.t('data_sheets.you_already_contributed_to_this_property')
So there is nothing to do about Backbone nor Marionette side.