amd and coffeescript - javascript

I am working on a combination of coffeescript and require.js for AMD.
The problem would be that I must return a value for each module loaded by require.js, and I do that. But.. coffeescript helps me out and appends:(function() { and }).call(this);. which blows my code.
main.js
require.config( {
paths: {
'backbone': 'libs/AMDbackbone-0.5.3',
'underscore': 'libs/underscore-1.2.2',
'text': 'libs/require/text',
'jquery': 'libs/jquery-1.7.1',
},
baseUrl: '/app'
} );
require(
['require', 'backbone', 'jquery', 'underscore' ],
function( require, Backbone, $, _ ) {
// framework loaded
require(
['require', 'app'],
function( require, app) {
return {};
} );
} );
app.js
define( [
'jquery',
'underscore',
'backbone',
'views/gameview',
], function( $, _, Backbone, GameView, ) {
"use strict";
window.app = {};
$(function(){
var app = window.app = _.extend({
views: {
GameView: new GameView
},
//code..
}, window.app);
//code...
return window.app;
} );
And the coffeescript:
/views/gameview.coffee
define ["jquery", "underscore", "backbone"], ($, _, Backbone, RankView) ->
"use strict"
GameView = Backbone.View.extend()
GameView
Which translates to:
/views/gameview.js
(function() {
define(["jquery", "underscore", "backbone"], function($, _, Backbone) {
"use strict";
var GameView;
GameView = Backbone.View.extend({...});
return GameView;
});
}).call(this);
But I would like to translate to:
define(["jquery", "underscore", "backbone"], function($, _, Backbone) {
"use strict";
var GameView;
GameView = Backbone.View.extend({...});
return GameView;
});
Would be nice to use this in console: var GameView = new app.views.GameView; in console.
How do I force coffeescript compiler not to do that? Is there a flag or something for that?
AGAIN: I JUST WANT TO CUT OFF (function() { and }).call(this); - is not that important the amd code behind it, be it global or not..
Thank you

You can use the --bare flag when compiling your coffee files:
-b, --bare Compile the JavaScript without the top-level function safety wrapper.

Related

Handlebars.js and Webpack - precompile templates

I'm using Backbone.js, Handlebars.js and Webpack for my website.
I used to use Require.js instead of Webpack. I have the following files:
template.js
define({
structure: "structure.html",
home: "home.html"
});
webpack.config.js
resolve: {
extensions: ['', '.js', '.json'],
alias: {
root: path.resolve( __dirname ),
"router": path.resolve( __dirname ) + "/www/js/router",
"templates": path.resolve( __dirname ) + "/www/js/templates",
"handlebars": path.resolve( __dirname ) + "/node_modules/handlebars/dist/handlebars",
"templates_html": path.resolve( __dirname ) + "/www/templates"
}
},
view.js
define( ['jquery', 'underscore', 'backbone', "utils" ],
function($, _, Backbone, Utils) {
var View = Utils.Page.extend({
constructorName: "View",
id: "home",
initialize: function() {
this.template = Utils.templates.home; // this is what I need
},
render: function () {
this.$el.html( this.template( this.model.toJSON() ) );
return this;
},
});
return View;
});
I'd like to compile all templates with Handlebars.js at start of my website.
When I was using Require.js I was used to doing something like this:
utils.js
define( ['jquery', 'underscore', 'backbone', 'handlebars', 'templates'],
function($, _, Backbone, Handlebars, Templates) {
var Utils = {
templates: {}
};
for (var t in Templates) {
Templates[t] = "text!" + Templates[t];
}
require(_.values(Templates), function() {
var fragments = _.object(_.keys(Templates), arguments);
// precompile all the fragments
for (var t in fragments) {
Utils.templates[t] = Handlebars.compile(fragments[t]); /* <Handlebars> */
}
});
return Utils;
});
How can I do something like that in utils.js with webpack?
Thanks
You can use this handlebars loader for web pack https://github.com/pcardune/handlebars-loader/blob/master/README.md full info is given there but basically set the loader to compile all of your html files in your templates folder or rename them from .html to .hbs or .handlebars then simple require them in your modules and they will be compiled.

Import and using javascript library in backbone.js project

I'm newbie to backbone.js and require.js. Currently I create one backbone project.
Here is app.js code :
define([
'jquery',
'underscore',
'backbone',
'script',
'router'
], function($, _, Backbone, Script, Router){
var initialize = function(){
Router.initialize();
};
return {
initialize: initialize
};
});
Here is main.js:
require.config({
path: {
jquery: 'libs/jquery/jquery-min',
underscore: 'libs/underscore/underscore-min',
backbone: 'libs/backbone/backbone-min',
script: 'libs/scripts/index'
},
shim:{
backbone: ['jquery', 'underscore'],
script: ['jquery'],
enforceDefine: true
}
});
require([
'app',
], function(App){
App.initialize();
});
And the last one is router.js :
define([
'jquery',
'underscore',
'backbone',
'script'
], function($, _, Backbone){
var AppRouter = Backbone.Router.extend({
routes:{
'*actions': 'defaultAction'
}
});
var initialize = function(){
var app_router = new AppRouter;
app_router('route:defultAction', function(actions){
});
Backbone.history.start();
};
return {
initialize: initialize
};
});
I want to add jquery-json library to my project. If in html project, here is my code :
<script type="text/javascript" src="jquery-min.js"></script>
<script type="text/javascript" src="jquery.json-2.4.min.js">
</script>
<script>
function serializeObjToJSON(_obj) {
var _json = $.toJSON(_obj);
return _json;
}
function deserializeJSONToObj(_json) {
var _obj = $.evalJSON(_json);
return _obj;
}
</script>
I want to import the library above and using it in my backbone project. But I have no idea how to do that.
Any help would be much appreciated, thank you.
in your main JS you should add the JSON reference. (put jquery.json-2.4.min.js into lib/ folder)
require.config({
path: {
jquery: 'libs/jquery/jquery-min',
underscore: 'libs/underscore/underscore-min',
backbone: 'libs/backbone/backbone-min',
script: 'libs/scripts/index',
json: 'libs/jquery.json-2.4.min'
}
Then you can add it as a definition into the app.js or any other module.js file which is using it in reference .
define([
'jquery',
'underscore',
'backbone',
'script',
'router',
'json'
], function($, _, Backbone, Script, Router, Json){
//Code
}
Then within your js files you have your reference to json. You can call it by using
Json.method()
for example.. As soon as you write json, it looks for your definition and then reffers to that lib for the functions you called.
So your index.js or whichever end you want to call it will require something like :
define([
'jquery',
'underscore',
'backbone',
'script',
'router',
'json'
], function($, _, Backbone, Script, Router, Json){
serializeObjToJSON: function(_obj) {
var _json = Json.toJSON(_obj);
return _json;
}
deserializeJSONToObj: function(_jsonObject) {
var _returnObj = Json.evalJSON(_jsonObject);
return _returnObj;
}

How to Override a model/ view file at runtime, for a js file combined by requirejs optimizer?

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.

Require JS can't find my application

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.

RequireJS loading leaf modules

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.

Categories