How to call a Layout from itself to make an instance - backbone.js

I have a Layout(SubMenu100) that have an event to call other Layout(SubMenu200), but it also make a onClick trigger that will create an instance if layout(SubMenu100) and call itself, but I don't know how to get an instance like the next code.
this.SubMenu100 = new SubMenu100();
I try to put it in Define vars but get me an error.
define([
'backbone.marionette',
'underscore',
'logger',
'tpl!apps/templates/SubMenu100.html',
'i18n!apps/nls/Messages',
'apps/views/SubMenu200',
'apps/views/SubMenu100'
], function (Marionette, _, Logger, Template, i18n, SubMenu200, SubMenu100) {
launch: function (e) {
$("#title_wrapper_div").click(this.callMe);
},
callMe: function () {
if (this.subMenu100 === undefined) {
this.subMenu100 = new SubMenu100(); // <- here
}
window.App.vent.trigger("dashboard:showView",this.subMenu100, "", "", "", "");
}
}
So, this is the question, How can I create an instance of SubMenu100 inside within itself?

If launch is called with context of SubMenu100, you can do this.callMe.bind(this) then you should be able to do new this() inside callMe.
But for simplicity you could do this :
define([
'backbone.marionette',
'underscore',
'logger',
'tpl!apps/templates/SubMenu100.html',
'i18n!apps/nls/Messages',
'apps/views/SubMenu200'
], function(Marionette, _, Logger, Template, i18n, SubMenu200) {
var SubMenu100 = Class SubMenu100 {
launch: function(e) {
$("#title_wrapper_div").click(this.callMe);
},
callMe: function() {
if (this.subMenu100 === undefined) {
this.subMenu100 = new SubMenu100();
}
window.App.vent.trigger("dashboard:showView", this.subMenu100, "", "", "", "");
}
}
return SubMenu100;
});
Note that every launch will create new event handler potentially on the same element (unless something else is doing proper cleanup) and this can lead to bugs. I don't recommend using global jQuery selectors in backbone components.
If you want to create instances of SubMenu100 and SubMenu200 I'd create a higher level component in charge of that:
require([
// ^ ------ this is NOT SubMenu100 definition
'apps/views/SubMenu100',
'apps/views/SubMenu200',
], function (SubMenu100, SubMenu200) {
// this is NOT SubMenu100 definition
launch: function (e) {
$("#title_wrapper_div").click(this.callMe);
},
callMe: function () {
if (this.subMenu100 === undefined) {
this.subMenu100 = new SubMenu100();
}
}
});

Related

How to angular-translate controller function objects

I cannot find examples for how to translate objects inside of functions, only examples for translating html content.
Inside the function are system button labels that need to be translated. I have provided the actual en.json and th.json files to show what needs to be translated. I can find no examples for angular-translate that translate non-html objects like in this function. I have managed to get translation working on all other areas of my application, but not this function. The documentation http://angular-translate.github.io/docs/#/guide/03_using-translate-service does not provide a good example that fits my code. I have seen others ask this same type of question, and just be pointed to the documentation (i.e. https://github.com/angular-translate/angular-translate/issues/1466).
en.json
{
"CHOOSE_IMAGE": "Choose image source",
"CAMERA": "Camera",
"LIBRARY": "Library",
"CANCEL": "Cancel"
}
th.json
{
"CHOOSE_IMAGE": "เลือกที่มาของภาพ",
"CAMERA": "กล้อง",
"LIBRARY": "คลังรูปภาพี่ี",
"CANCEL": "ยกเลิก"
}
feedback.controller.js
...
function getImageSource() {
var deferred = $q.defer();
$ionicActionSheet.show({
buttons: [
{ text: 'CAMERA' },
{ text: 'LIBRARY' }
],
titleText: 'CHOOSE_IMAGE',
cancelText: 'CANCEL',
cancel: function () {
deferred.reject();
},
buttonClicked: function (index) {
if (index === 0) {
deferred.resolve(Camera.PictureSourceType.CAMERA);
} else {
deferred.resolve(Camera.PictureSourceType.PHOTOLIBRARY);
}
return true;
}
});
return deferred.promise;
}
...
Well, apparently all the necessary information are in the docs. But let me do your work..
You have to inject $translate service in your controller. Assuming you have your translations already loaded the most convinient way to translate your labels is to use $translate.instant() method. What does it do?
According to docs http://angular-translate.github.io/docs/#/api/pascalprecht.translate.$translate it:
Returns a translation instantly from the internal state of loaded translation. All rules regarding the current language, the preferred language of even fallback languages will be used except any promise handling. If a language was not found, an asynchronous loading will be invoked in the background.
So your code should look like that:
feedback.controller.js
...
function getImageSource() {
var deferred = $q.defer();
$ionicActionSheet.show({
buttons: [
{ text: $translate.instant('CAMERA') },
{ text: $translate.instant('LIBRARY') }
],
titleText: $translate.instant('CHOOSE_IMAGE'),
cancelText: $translate.instant('CANCEL'),
cancel: function () {
deferred.reject();
},
buttonClicked: function (index) {
if (index === 0) {
deferred.resolve(Camera.PictureSourceType.CAMERA);
} else {
deferred.resolve(Camera.PictureSourceType.PHOTOLIBRARY);
}
return true;
}
});
return deferred.promise;
}
...
Or you can use asynchronous loading with:
feedback.controller.js
....
$translate(['CAMERA',
'LIBRARY',
'CHOOSE_IMAGE',
'CANCEL']).then(function (translations) {
$ionicActionSheet.show({
buttons: [
{ text: $translate.instant('CAMERA') },
{ text: $translate.instant('LIBRARY') }
],
....
Hope it helps.
Use filter function
.controller(["$filter",....],function($filter,....){
var translateFilter=$filter("translate");
...
buttons: [
{ text: translateFilter('CAMERA') },
{ text: translateFilter('LIBRARY') }
]
...
})
or when translations isn't loaded already
.controller(["$q","$translate",....],function($q,$translate,....){
var translateFilter=$filter("translate");
$q.all({
CAMERA:$translate('CAMERA'),
LIBRARY:$translate('CAMERA')
}).then(function(translations){
...
buttons: [
{ text: translations.CAMERA },
{ text: translations.LIBRARY }
]
...
})
})

how i call private block method without create object outside in ext Js?

Ext.define('App.View.ClassDemo', {
privates: {
runFactory: function () {
this.factory('paresh');
}
},
factory: function (brand) {
alert(brand);
}
});
this class contain privates block and its contain runFactory method how i call this method without creating object outside
With ExtJS you can do something like this:
Ext.define('Computer', {
statics: {
factory: function(brand) {
// 'this' in static methods refer to the class itself
return new this(brand);
}
},
constructor: function() { ... }
});
var dellComputer = Computer.factory('Dell');
The "factory" method is static and can be used without a Computer instance.

Small Jasmine test for Javascript file: Best approach to test it

First of all I want to say that I am new in Jasmine, so I beg for your kind comprehension if the question is very basic. I am writing a test for this file:
define([
'q',
'backbone',
'marionette',
'education/eet/views/destinationview',
'education/eet/views/editdestinationview',
'education/eet/models/destination',
'common/ajaxerrorhandler',
'common/alertdialog'
], function (Q, Backbone, Marionette, DestinationView, EditDestinationView, Destination, AjaxErrorHandler, AlertDialog) {
'use strict';
var ReferenceDataController = Marionette.Controller.extend({
initialize: function (options) {
this._subjectCompositeId = options.subjectCompositeId;
},
getView: function (destinationTypes, editMode) {
var self = this,
deferred = Q.defer(),
destination = new Destination();
destination.fetch({
data: {subjectCompositeId: self._subjectCompositeId}
}).done(function () {
var view;
if (editMode) {
view = new EditDestinationView({
model: destination,
'destinationTypes': destinationTypes
});
view.on('click:saveDestination', self._handleSaveDestination, view);
} else {
view = new DestinationView({
model: destination
});
}
deferred.resolve(view);
}).fail(function (jqXHR) {
deferred.reject(jqXHR);
});
return deferred.promise;
},
_handleSaveDestination: function () {
if (this.model.isValid(true)) {
this.model.save(null, {
success: function () {
Backbone.Wreqr.radio.vent.trigger('education', 'show:destination');
},
error: function (jqXHR) {
var userFriendlyErrorString = AjaxErrorHandler.buildDefaultErrorMessage(jqXHR);
return new AlertDialog(userFriendlyErrorString);
}
});
}
}
});
return ReferenceDataController;
});
The problem is that I am not very sure about how can I access the variables inside it to test it. I am a Java Tester but never test Javascript even when I wrote, so I am very confused with it.
Any hint or code will be actually appreciated.
Thanks.
Think of Jasmine suite/spec as your application that is dependent on this module.
We do our specs as RequireJS modules that require the appropriate module, instantiate it - sometimes on module level, sometimes on suite (describe) level, sometimes on spec (it) level.
At this point, due to you (in it) having an access to an actual instance of the class, you invoke its various methods and test for the results using various asserts in the form of
expect(something).toBeTruthy();
or similar.

Underscore 'after' function

I have code similar to this
(function(exports, $, Backbone, document){
"use strict";
var modals = {
"Alerts.alert_delete" : (function() {
var self = this;
return {
template : {
count : this.collection.length,
models : this.collection.models
},
events : {
"click .confirm" : function(event) {
event.preventDefault();
var modal = this,
finished = _.after(modal.collection.length, self.reDraw);
// Models are succesfully delete, but finished is not completed
this.collection.each(function(model) {
modal.collection.sync('delete', model, { success : finished });
});
}
}
};
})
};
exports.app.modal = function(name, context) {
return modals[name].call(context);
};
}(this, jQuery, Backbone, document));
Please ignore the abstraction, this is to allow me to use one generic view for all my modals whilst keeping unique logic abstracted. I am at a loss as to why the _.after function is not completing when it has been called the correct number of times. self in this instance is a reference to the parent view.
Can someone shed some light on this for me?

backbone extension file loads, some helpers work, one doesn't

I have a backbone-extend.js file that I load in the require define in app.js. It has a Backbone.View extender class defining a couple helper methods. Two of the methods work just fine in my views, one always errors with Uncaught TypeError: Object [object global] has no method 'gotoUrl'. Why would just this one method be not defined but the other two are working fine? Do you see any issue in this code...
// Filename: backbone-extend.js
define([
'jquery',
'underscore',
'backbone'
], function($, _, Backbone) {
var helpers = {
eventSyncError: function(model,response,options) {
console.log('Sync error='+response.statusText);
$('#server-message').css({'color':'red', 'font-weight':'bold'}).text(response.statusText);
},
gotoUrl: function(url,delay) {
var to = setTimeout(function() { Backbone.history.navigate(url, true); }, delay);
},
getFormData: function(form) {
var unindexed_array = form.serializeArray();
var indexed_array = {};
$.map(unindexed_array, function(n, i) {
indexed_array[n['name']] = n['value'];
});
return indexed_array;
}
}
_.extend(Backbone.View.prototype, helpers);
});
Here is the code in view that calls it...
eventSyncMemberSaved: function(model,response,options) {
console.log("Member saved!");
$('#server-message').css({'color':'green', 'font-weight':'bold'}).text("Member saved!");
this.gotoUrl('members',2000);
//setTimeout(function() { Backbone.history.navigate('members', true); }, 2000);
},
saveMember: function() {
var data = this.getFormData($('#member-form'));
this.member.save(data, { success: this.eventSyncMemberSaved });
},
Thanks in advance for your help. I'm stuck.
The context of this is different in the success callback.
It no longer points to the view as it points to the xhr object
So it throws an error as that method is not available on the xhr object
To resolve it you need to bind the context of this to the success handler so that it points to the right object.
So in the initialize of the view add this code
initialize: function() {
_.bindAll(this, 'eventSyncMemberSaved');
}

Resources