Ember.application.create arguments - javascript

I am exploring one of Ember.js demo application and I find lot of arguments being passed to Ember.Application.create() in addition to usual VERSION and rootElement. The demo uses require.js which I understood is for AMD.
Does Ember.js does not take care by itself in its v1.0 to load javascripts based on need ? If it does so, I don't fully understand why should require.js be used with it..
Second, if require.js has a use case, what is the use of passing as many arguments like controller names and view names to Ember.Application.create() to bootstrap application.
// Define libraries
require.config({
paths:{
jquery:'lib/jquery-1.8.0.min',
handlebars:'lib/handlebars',
ember:'lib/ember_1.0pre',
ember_data:'lib/ember-data5',
text:'lib/require/text',
md5:'lib/md5',
//domready:'lib/require/domReady',
spin:'lib/spin'
},
shim:{
'ember':{
deps:[ 'jquery', 'handlebars'],
exports:'Ember'
},
'ember_data':{
deps:[ 'ember'],
exports:'DS'
}
},
waitSeconds:15,
urlArgs:"bust=" + (new Date()).getTime() //cancel caching for network requests,for development.
});
// Define application
define('application', [
'routes/app_router',
'controllers/application_controller',
'controllers/contacts_controller',
'controllers/contact_controller',
'controllers/edit_contact_controller',
'controllers/login_controller',
'views/application_view',
'views/contact_in_list_view',
'views/contacts_view',
'views/contact_view',
'views/edit_contact_view',
'views/login_view',
'models/contact',
'jquery',
'handlebars',
'ember',
'ember_data',
// 'domready',
'spin'
], function (Router,
ApplicationController,
ContactsController,
ContactController,
EditContactController,
LoginController,
ApplicationView,
Contact_In_List_View,
ContactsView,
ContactView,
EditContactView,
LoginView,
Contact )
{
return Ember.Application.create({
VERSION: '1.0.0',
rootElement:'#main',
// Load router
Router:Router,
//Load Controllers
ApplicationController:ApplicationController,
ContactsController:ContactsController,
ContactController:ContactController,
EditContactController:EditContactController,
LoginController:LoginController,
//Load associated Views
ApplicationView:ApplicationView,
Contact_In_List_View:Contact_In_List_View,
ContactsView:ContactsView,
ContactView:ContactView,
EditContactView:EditContactView,
LoginView:LoginView,
//Load Contact Model
Contact:Contact,
//Persistence Layer,using default RESTAdapter in ember-data.js.
store:DS.Store.create({
revision:5,
adapter:DS.RESTAdapter.create({
bulkCommit:false,
serializer:DS.Serializer.create({
primaryKey:function (type) {
return type.pk;
}
}),
mappings:{
contacts:Contact
},
namespace:'api' //you should change the first segment according to the application's folder path on the server.
})
}),
ready:function () {
}
});
}
);
Ex - application_controller.js
define('controllers/application_controller',
['ember' ],
function () {
return Ember.Controller.extend({
loggedin:false
});
}
);

Related

Applying RequireJS to a modular one page application

I actually have two questions concerning requirejs and singleton objects. I want to form a singleton object playing the role of my application core and pass it to modules as a parameter. How should this be done?
The other issue I have is related to a private object inside the application core. It's suppose to act as a container for modules but for some reason when I try to start the application, this container seems to have those modules but it can't be looped through. Any ideas why this is happening?
Here's an example code of the situation:
// applicationConfig.js
require.config({
baseUrl: 'js',
paths: {
jquery: 'jquery-3.1.1.min',
core: 'utils/applicationCore',
domReady: '../lib/domReady'
}
});
require(['modules']);
// modules.js
define(['core', 'domReady'], function(Core, domReady) {
require([
'modules/module1'
]);
domReady(function() {
var modules = Core.getModules();
var name = '';
for (name in modules) {
modules[name].creator(); // Start a module...
}
});
});
// applicationCore.js
define(function() {
return (function() {
var _modules = {};
return {
add: function(name, creator) {
_modules[name] = {
creator: creator
};
},
getModules: function() {
return _modules;
}
}
}());
});
// module1.js
define(['core', 'jquery'], function(Core, $) {
Core.add('module1', function() {
// Module constructor function.
});
});

ko is not defined Error in Chutzpah

I'm trying to write Unit Testing for my SPA project. Where we have used the Durandal (Framework), Knockout (Binding) with RequireJs.
I have installed the Chutzpah in Visual Studio 2012.
When i run my Test for the View Model, it throws me below error, even though the knockout js and other js are loaded correctly.
Uncaught ReferenceError: ko is not defined
My Json Config Code:
{
"Framework": "jasmine",
"TestHarnessReferenceMode": "AMD",
"TestHarnessLocationMode": "SettingsFileAdjacent",
"References" : [
{"Path" : "../Scripts/require.js" },
{"Path" : "config.js" }
],
"Tests" : [
{"Path": "tests"}
]
}
My Config Js Code:
require.config({
paths: {
'text': '../Scripts/text',
'durandal': '../Scripts/durandal',
'plugins': '../Scripts/durandal/plugins',
'jquery': '../Scripts/jquery-2.1.4',
'knockout': '../Scripts/knockout-3.3.0'
},
shim: {
}
});
My FirstTest.Js Code:
define(['project/modules/Settings/Subscriber/Viewmodels/Channels'],
function (nChannel) {
describe("Get Channels", function () {
it("will check the Get Channels call and result", function () {
var disp = nChannel.getChannels().then(function () {
var actualResult = ko.toJS(nChannel.Channels);
expect(actualResult.length).toEqual(3);
});
});
});
});
ViewModel Code:
define(['plugins/dialog'], function (dialog) {
var subscriberList = ko.observableArray(); //Getting Error here - while loading the Js for Unit Testing
var JsQ = $; //Getting JQUERY members here. // Works good.
//Other Logics goes here
return {
subscriberList : subscriberList,
JsQ : JsQ
};
});
The Configuration for the Jquery works perfect, since knockout also same as that. But gives error.
Any Idea's / Suggestion why the error?
Do i need to load the ko (knockout) separately?
Edit 1:
I have tried changing the knockout to ko it gives me the error Uncaught Error: Script error for: knockout.
Edit 2:
The problem i'm facing when i apply this solution, those existing code file needs the massive changes and the file counts are in hundreds. From Init.Js we have loaded the Jquery and Knockout. Like below.
requirejs.config({
paths: {
'text': '../Scripts/text',
'durandal': '../Scripts/durandal',
'plugins': '../Scripts/durandal/plugins'
}
});
define('jquery', [], function () {
return jQuery;
});
define('knockout', [], function () {
return ko;
});
So inside any viewmodel we can get the instance of knockout as ko, without declaring the require js stuff in each veiwmodel for the Knockout (As you suggested).
But when i try the same in Chutzpah declaration this is not working. Not sure why.
Hope you understand the problem.
In both modules you show in your question, you use ko but you do not list knockout in your list of dependencies. This is a sure way to get the error you got. Modify your modules to list knockout in the dependencies, and add a corresponding parameter to the callback you give to define. For instance,
define(['knockout', 'plugins/dialog'], function (ko, dialog) {

Loading soundmanager2 with requirejs amd shim, logs undefined

So here's my main.js file (stripped out all my other scripts for clarity):
require.config({
paths: {
'soundmanager2': '../libs/soundmanager2/soundmanager2',
},
shim: {
'soundmanager2': {
'exports': 'soundManager'
}
}
});
Then i'm loading the library like so:
define(['jquery', 'underscore', 'backbone', 'utilities/events', 'utilities/helpers', 'soundmanager2'],
function($, _, Backbone, events, h, soundManager){
var TrackModel = Backbone.Model.extend({
initialize: function() {
console.log(soundManager);
}
});
return TrackModel;
}
);
The script is being downloaded - but when I log soundManager, I get undefined, no other errors.
Any ideas? Fear i'm missing something obvious..
I found the usage with requirejs in source code comment, but documentation no description. Here is the example.
define(['soundManager2'], function(SoundManager) {
var sound = SoundManager.getInstance();
sound.setup({
useHTML5Audio: true,
idPrefix: '',
onready: function() {},
ontimeout: function() {}
});
sound.beginDelayedInit();
})
This was an issue with the version of soundmanager2 - it has AMD baked in but I can't get it to export for some reason. I reverted to an earlier version, used the shim, and that fixed it!

RequireJS: How do I pass variables from one file to another?

I'm using require with backbone + backbone-forms. I'm currently using RequireJS to seperate code into multiple files. I have models stored in separate files and want to keep form validators separately.
However, I am unable to access variables defined in one files, in another file that depends on this one. What I get is Uncaught ReferenceError: isEmptyName is not defined. isEmptyName is defined in validators and used in model. Any feedback about RequireJS config is also appreciated.
My config:
requirejs.config({
//By default load any module IDs from js/lib
baseUrl: 'js',
paths: {
jquery: 'lib/jquery',
app: 'lib/app',
wizard: 'lib/jquery.bootstrap.wizard.min',
bootstrap: 'lib/bootstrap.min',
underscore: 'lib/underscore-min',
backbone: 'lib/backbone-min',
backboneForms: 'lib/backbone-forms.min',
langSwitcher: 'lib/lang',
cookie: 'lib/cookie',
datepicker: 'lib/bootstrap-datepicker',
mask: 'lib/jquery.maskedinput.min',
validators: 'modules/validators',
// models
personalData: 'models/personal-data',
addressData: 'models/address-data',
workData: 'models/work-data',
productsData: 'models/products-data',
statmentData: 'models/statment-data',
model: 'models/form',
collection: 'collections/form',
view: 'views/form',
setup: 'setup',
send: 'send',
},
shim: {
'underscore': {
deps: ['jquery'],
exports: '_'
},
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'backbone'
},
// all model needs to go within one collection
'bootstrap' : ['jquery'],
'wizard': ['jquery'],
'backboneForms': ['backbone'],
'validators': ['backbone','mask'],
'personalData' : ['backbone','backboneForms','validators'],
'addressData': ['backbone','backboneForms'],
'workData': ['backbone','backboneForms'],
'statmentData': ['backbone','backboneForms'],
//'collection': ['backbone','backboneForms','personalData'],
//'view': ['backbone','backboneForms','personalData']
}
});
Beginning of validators.js
require(['backbone','backboneForms'], function(){
var lettersOnly = /^[A-Za-zęóąśłżźćńĘÓĄŚŁŻŹĆŃ]+$/;
var lettersOnlyDash = /^[A-Za-zęóąśłżźćńĘÓĄŚŁŻŹĆŃ\-]+$/;
var err = {};
var errCh = {};
var errFormat = {};
var isEmptyName = function(value){
err = { message: 'Wpisz imię.'};
if (value.length === 0) return err;
};
Beginning of model.js that needs the validators in validators.js
require(['backbone','backboneForms','mask','validators'], function(backbone,backboneForms,mask,validators){
var PersonalData = Backbone.Model.extend({
schema: {
first_name:{
title: 'Imię',
validators: [isEmptyName, isLetter, minCharCount] //Accessing validators.js members here...
}, ...
I think you're using require when what you really need is define. From When should I use require() and when to use define()?,
With define you register a module in require.js that you than can
depend on in other module definitions or require statements. With
require you "just" load/use a module or javascript file that can be
loaded by require.js.
So here, you have some variables that are defined in one file, but are required to be accessed in another file. Seems like a 'Module', doesn't it? So now, you have two ways of using this file as a module:
Conform to AMD-ness
Conform to chaotic javascript global variable-ness
Using the AMD Approach
validators.js is now a module. Anybody wishing to use 'validator functions' can depend on this module to provide it for them. That is,
define(['backbone','backboneForms'], function(){
var lettersOnly = /^[A-Za-zęóąśłżźćńĘÓĄŚŁŻŹĆŃ]+$/;
var isEmptyName = function(value){
err = { message: 'Wpisz imię.'};
if (value.length === 0) return err;
return {
someVariable: lettersOnly,
someFunction: isEmptyName
}
};
You'll notice that the require has been replaced with define. Now, when somebody (model) depends on validator.js, they can access their dependencies as follows
require(['backbone','backboneForms','mask','validators'],
function(backbone, backboneForms, mask, validators) {
var isEmptyNameReference = validators.someFunction;
...
Using shim
Check Requirejs why and when to use shim config, which references this link which says,
if we were to just add the backbone.js file to our project and list
Backbone as a dependency from one of our modules, it wouldn’t work.
RequireJS will load backbone.js, but nothing in backbone.js registers
itself as a module with RequireJS. RequireJS will throw up its hands
and say something like, “Well, I loaded the file, but I didn’t find
any module in there.”
So, you could have your validator.js populate a global Validator namespace, and still use it the way we used it in the example above.
function(){
var lettersOnly = /^[A-Za-zęóąśłżźćńĘÓĄŚŁŻŹĆŃ]+$/;
var isEmptyName = function(value){
err = { message: 'Wpisz imię.'};
if (value.length === 0) return err;
Globals.Validator = {
someVariable: lettersOnly,
someFunction: isEmptyName
}
}();
Your config.js would then be,
shim: {
'validator': {
deps: ['backbone','backboneForms'],
exports: 'Globals.Validator'
},
...
Note that you can alias the namespace as you wish, but the alias is just a reference to the existing global object/namespace. This is helpful if you have, say, Foo.Bar.Foobar as your namespace, but want to refer to it as FB. Shimming, hence, is a way for non-AMD libraries to adapt to AMD usage. In this case, option 1 should be sufficient.

using Backbone JS boilerplate & code navigation

a newbe question:
I've downloaded the backbone boilerplate from https://github.com/david0178418/BackboneJS-AMD-Boilerplate it uses require.js and I wonder about the code navigation during development.
Here is my question:
let's say I have 2 views one extend the other like so:
View 1:
define([
'underscoreLoader',
'backboneLoader',
'text!templates/main.html'
],
function (_, Backbone, MainTemplate) {
"use strict";
return Backbone.View.extend({
template:_.template(MainTemplate),
initialize:function () {
this.render();
},
log:function(msg){
console.log(msg);
},
render:function () {
this.$el.append(this.template({}));
return this;
}
});
}
);
View 2:
define([
'underscoreLoader',
'backboneLoader',
'text!templates/other.html',
'views/main-view'
],
function (_, Backbone, MainTemplate,MainView) {
"use strict";
// how would you navigate to MainView (main-view.js)
return MainView.extend({
template:_.template(MainTemplate),
initialize:function () {
this.render();
},
render:function () {
this.log("my message");
this.$el.append(this.template({}));
return this;
}
});
}
);
Now when I develop (I use IntelliJ) I would like to middle click MainView on the extended view and navigate to the code without having to browse the project tree.
Is that possible using this boilerplate? is there a better approach or a better boilerplate?
I would really like Netbeans's navigator to show me all the methods:
var New_Controller = Backbone.View.extend({
el : null, ...
}
But I can't seem to get it to work. Google came up with something for #lends, but I can't even get Backbone.js to get loaded to the code hint cache.
I ended up installing WebStorm (I saw the IDE in all the egghead.io tutorials) to get the navigator to list all methods and properties.
FYI, Aptana Studio and Zend Studio showed nothing like Netbeans. And Eclipse IDE for JavaScript Web Developers only partially (impractical in real life) works; it flattens the entire hierarchy.
I found this to work fine for me:
the Backbone Objects are wrapped with my custom objects, which allows me to navigate code, extend objects and keep multiple files easily.
Here is how:
Object 1
function ItemModel() {
ItemModel.model = (
Backbone.Model.extend({
initialize:function () {
},
defaults:{
name:"item name"
},
log:function(){
console.log("inherited method");
}
})
);
return new ItemModel.model();
}
Object 2
function ItemModel2() {
ItemModel2.model = (
ItemModel.model.extend({
initialize:function () {
},
defaults:{
name:"item name2"
}
})
);
return new ItemModel2.model();
}
and in my app:
var App = {
item:new ItemModel(),
item2:new ItemModel2()
};

Categories

Resources