Backbone view not removing properly? - backbone.js

There is something I'm missing here it seems my view is not removing.
// ROUTER //
screensaveroff: function() {
AnimationManager.outAnimation([self.screensaverView], function() {
console.log($(this.screensaverView.el).length); //!! always trigger 1 !!
});
}
// ANIMATION MANAGER outANimation function (trigger outAnimation for the passed view as arg)//
outAnimation : function(animationArray, callback){
var time = [];
window.animationArray = animationArray;
for (var i=0; i<animationArray.length; i++)
{
var view = animationArray[i];
view.outAnimation();
time[i] = animationArray[i].animationTime;
}
var timeoutMax = Math.max.apply(null, time);
setTimeout(function(){callback()},timeoutMax);
}
// screensaverView outANimation function //
outAnimation: function() {
var self = this;
this.$el.slideToX(1920, self.animationTime, function() {
self.clearIntervalAnimation();
self.remove();
});
},
any idea what's wrong with my code ?? thanks a lot

Related

Salesforce Lightning: Controller functions interaction within the same component

Do anyone know "how to call a lightning controller function from another function within the same lightning component?"
Thanks
Aruna
({
doInit: function(component, event, helper){
var action = component.get("c.gettemps");
action.setParams({ recordId : component.get("v.recordId") });
action.setCallback(this, function(response){
var parsedJSON= JSON.parse(response.getReturnValue());
var size=component.get("v.limit");
var counter = component.get("v.counter");
component.set("{!v.myObject}",parsedJSON);
var list=[];
for(var i=0; i<size;i++)
{
list.push(parsedJSON[i]);
counter++;
}
component.set("v.end",counter);
component.set("{!v.counter}",counter);
component.set("{!v.paginationList}",list);
});
$A.enqueueAction(action);
},
next:function(component,event,helper)
{
var myObject = component.get("v.myObject");
var size=component.get("v.limit");
var end = component.get("v.end");
var counter = component.get("v.counter");
var list=[];
for(var i=end; i<end+size; i++)
{
if(i<myObject.length)
{
if(i>-1)
{
list.push(myObject[i]);
counter++;
}
}
}
component.set("v.end",counter);
component.set("{!v.counter}",counter);
component.set("{!v.paginationList}",list);
},
previous:function(component,event,helper)
{
var myObject = component.get("v.myObject");
var size=component.get("v.limit");
var end = component.get("v.end");
var counter = component.get("v.counter");
var list=[];
for(var i=end-1; i>end-size-1; i--)
{
if(i>=-1)
{
list.push(myObject[i-1]);
counter--;
}
}
component.set("v.end",counter);
component.set("{!v.counter}",counter);
component.set("{!v.paginationList}",list);
}
})
Actually I have problem with my previous function. When I stay in my first page and selects previous button my page should not be changed but my code is behaving abnormally. So I thought of reusing my doInit function to stay in the current page when I am already in the first page. Please help
Thanks
Aruna
In the helper it is possible by "this" operator
this.next();
In the controller you cannot do this directly.
But i have one solution for you :)
Create method handler in component .
Then you can call this method in controller and helper by componet.methodName function
component.triggerNextFun();
You can also try this way
JS Controller :
({
doInit : function(component, event, helper){
var action = component.get("c.getBeforeAWBDetails");
action.setParams({
"CaseId" : component.get("v.recordId")
});
console.log("caseId :" + component.get("v.recordId"));
action.setCallback(this, function(response) {
var state = response.getState();
if(component.isValid() && state == "SUCCESS"){
component.set("v.BeforeAWB", response.getReturnValue());
}
});
$A.enqueueAction(action);
},
closeModal : function(component, event, helper) {
$A.get('e.force:refreshView').fire();
var reInit = component.get("c.doInit");
// use this and extend the values you need to get from "doInit" method
$A.enqueueAction(reInit);
}
})

Two $firebaseArrays on one page & one ctrl

I would like to use two different $firebaseArrays on one view with one controller. But only one of them works and the other only works if i put him in his own controller.
from my factory file:
.factory("AlphaFactory", ["$firebaseArray",
function($firebaseArray) {
var ref = firebase.database().ref('alpha/');
return $firebaseArray(ref);
}
])
.factory("BetaFactory", ["$firebaseArray",
function($firebaseArray) {
var ref = firebase.database().ref('beta/');
return $firebaseArray(ref);
}
])
and my controller:
.controller('DemoCtrl', function($scope, AlphaFactory, BetaFactory) {
$scope.alphaJobs = AlphaFactory;
$scope.addalphaJob = function() {
$scope.alphaJobs.$add({
Testentry: $scope.loremipsum,
timestamp: Date()
});
$scope.alphaJob = "";
};
$scope.betaJobs = BetaFactory;
$scope.addbetaJob = function() {
$scope.betaJobs.$add({
Testentry2: $scope.dolorest,
timestamp: Date()
});
$scope.betaJob = "";
};
)}
Are you sure it is not a simple matter of a promise has not finished?
var alphaJobs = AlphaFactory;
alphaJobs.$loaded().then(function() {
// Do something with data if needed
$scope.alphaJobs = alphaJobs;
});
var betaJobs = BetaFactory;
betaJobs.$loaded().then(function() {
// Do something with data if needed
$scope.betaJobs = betaJobs;
});

backbone memory leak remove not working?

In the router I do this
function test() {
self.topbarView = new TopbarView();
self.topbarView.render();
GhostviewHunter.addView(self.topbarView);
}
function clean() {
console.log(GhostviewHunter.currentViews.length);
GhostviewHunter.clean();
}
setInterval(test, 1000);
setInterval(clean, 1000);
ghostviewhunter should clean/remove the views:
define('ghostviewHunter', [], function() {
var GhostviewHunter = function() {};
GhostviewHunter.prototype.currentViews = [];
GhostviewHunter.prototype.addView = function(view) {
this.currentViews.push(view);
}
GhostviewHunter.prototype.clean = function() {
_.each(this.currentViews, function(view) {
view.remove();
});
this.currentViews.length = 0;
}
GhostviewHunter.__instance = null;
GhostviewHunter.getInstance = function() {
if( GhostviewHunter.__instance == null ) {
GhostviewHunter.__instance = new GhostviewHunter();
}
return GhostviewHunter.__instance;
}
return GhostviewHunter.getInstance();
})
TopView is fetching a model, the model is updated every 1seconde with setInterval function.
I thought that remove(); would be enough be the memory leak is very quick when I monitor the app.
Any idea ?
EDIT:
TOPBARVIEW
define('topbarView', [
'backbone',
'parameterManager',
'text!views/topbarView/topbarTemplate.html',
'drupalidModel',
'weatherModel',
'refreshTime',
'dateParser'
], function(Backbone, ParameterManager, TopbarTemplate, DrupalidModel, WeatherModel, RefreshTime, DateParser) {
var TopbarView = Backbone.View.extend({
el: '#topbar',
template: _.template(TopbarTemplate),
events: {},
initialize: function() {
var self = this;
_.bindAll(this, 'render', 'startDateRefresh');
this.dateParser = new DateParser();
self.startDateRefresh();
setInterval(self.startDateRefresh, RefreshTime.date);
this.initWeatherModel();
},
render: function() {
var self = this;
var data = {
picto_url : ParameterManager.get('WEATHER_RESOURCE_URL') + ParameterManager.get('WEATHER_PICTO_CODE') + ".png",
date: self.date
}
this.$el.html(this.template({data: data}));
},
initWeatherModel: function() {
var self = this;
var weather_url = ParameterManager.get('WEATHER_URL');
if(weather_url === null) {
this.drupalidModel = new DrupalidModel();
this.drupalidModel.fetch({
success: function(model, response) {
var center_id_num = model.get('center_id_num');
ParameterManager.set('DRUPAL_CENTER_ID_NUM', center_id_num);
ParameterManager.constructWeatherUrl();
self.model = new WeatherModel();
self.listenTo(self.model,'change', self.render);
self.startModelRefresh();
},
error: function() {
console.log("Failed to fetch center id!");
}
})
} else {
this.model = new WeatherModel();
self.listenTo(self.model,'change', self.render);
this.startModelRefresh();
};
},
startModelRefresh: function() {
var self = this;
this.modelRefresh = function() {
self.model.fetch();
}.bind(this);
self.modelRefresh();
setInterval(self.modelRefresh, RefreshTime.weather);
},
stopModelRefresh: function() {
var self = this;
clearInterval( self.modelRefresh );
},
startDateRefresh: function() {
var self = this;
this.date = this.dateParser.classicDate();
this.render();
}
});
return TopbarView;
})
As fbynite suggested, your code which is supposed to clear the interval(s) is not correct, you should pass the interval id to clearInterval.
apart from that, you're not calling stopModelRefresh() at all. You should make sure all external references are properly removed before removing the view. For example I've added a destroy method that clears the interval before removing the view:
var TopbarView = Backbone.View.extend({
el: '#topbar',
template: _.template(TopbarTemplate),
events: {},
initialize: function() {
},
render: function() {
},
modelRefresh: function() {
this.model.fetch();
},
startModelRefresh: function() {
this.modelRefresh();
this.intervalId = setInterval(_.bind(this.modelRefresh,this), RefreshTime.weather);
},
stopModelRefresh: function() {
clearInterval(this.intervalId);
},
destroy: function() {
this.stopModelRefresh();
this.remove();
}
});
Now your GhostviewHunter should call it instead of directly calling remove:
GhostviewHunter.prototype.clean = function() {
_.each(this.currentViews, function(view) {
view.destroy();
});
this.currentViews.length = 0;
}
or you can even override the remove method itself to something like:
remove: function(){
this.stopThisInterval();
this.stopThatInterval();
this.cleanUpSomethingElse();
Backbone.View.prototype.remove.call(this);
}
and have the ghost thingy call remove itself.
Note that you have other interval calling startDateRefresh which you're not even attempting to clear... You should clear all such similarly.
And as a side note, I strongly suggest to stop spamming self = this where it is totally unnecessary for eg:
stopModelRefresh: function() {
var self = this;
clearInterval( self.modelRefresh );
// Why..? Nothing here changes the context?
},
and I also suggest recursively calling modelRefresh once the current fetch succeeds/fails rather than calling it from an interval where you have no guarantee that the previous fetch is complete

Angularjs State transition

I am building a hybrid mobile app using ionic framework and cordova (first time).I am having problems with state transition because by default angular renders the template before completing the transition.This makes the the app look slow (when you click a menu item and wait for it to come).This happens only for those who load data from local storage or service! My Question is: How can I make the template come empty in the moment I click the menu item , then show a loader until the template is ready.Below is some code is use in my menu controller for the state transition!
//I use ng-click="navigateTo('state name')"
$scope.navigateTo = function (stateName) {
$timeout(function () {
$mdSidenav('left').close();
if ($ionicHistory.currentStateName() != stateName) {
$ionicHistory.nextViewOptions({
disableAnimate: false,
disableBack: true
});
$state.go(stateName);
}
}, ($scope.isAndroid == true ? 1000 : 0));
};// End navigateTo.
Below is the controller code for the view that needs a solution
appControllers.controller("calendar_Ctrl", function($scope,$rootScope, $state,$stateParams, $ionicHistory, $filter, $q, $timeout, $log, MaterialCalendarData, $moment) {
$scope.isAnimated = $stateParams.isAnimated;
$scope.selectedDate = null;
$scope.weekStartsOn = 0;
$scope.dayFormat = "d";
$scope.disableFutureDates = false;
$scope.directionn = "horizontal";
$scope.setDirection = function(direction) {
$scope.directionn = direction;
$scope.dayFormat = direction === "vertical" ? "EEEE, MMMM d" : "d";
};
$scope.dayClick = function(date) {
$scope.msg = "You clicked " + $filter("date")(date, "MMM d, y h:mm:ss a Z");
};
$scope.setContentViaService = function() {
var today = new Date();
MaterialCalendarData.setDayContent(today, '<span> :oD </span>')
}
$scope.getItems = function(){
if(localStorage.getItem("eventsData")){
var eventsData = localStorage.getItem("eventsData");
return JSON.parse(eventsData);
}else{
return [];
}
}
var events = $scope.getItems();
// You would inject any HTML you wanted for
// that particular date here.
var numFmt = function(num) {
num = num.toString();
if (num.length < 2) {
num = "0" + num;
}
return num;
};
var loadContentAsync = false;
$log.info("setDayContent.async", loadContentAsync);
$scope.setDayContent = function(date) {
var key = [date.getFullYear(), numFmt(date.getMonth()+1), numFmt(date.getDate())].join("-");
var data = (events[key]||[{ type: ""}]);
if (loadContentAsync) {
var deferred = $q.defer();
$timeout(function() {
deferred.resolve(data);
});
return deferred.promise;
}
return data;
};
$scope.isAnimated = $stateParams.isAnimated;
});
Thank You Very Much for your time and help!!
Hi Use $ionicLoading Service to solve this problem,
http://ionicframework.com/docs/api/service/$ionicLoading/

Firebase child_removed not working in real-time

I am following tutsplus Real time web apps with Angularjs and Firebase.
I have main.js (below) which allows me to add and change items in Firebase in real time with no refresh of the browser (in Chrome and Safari).
However when I delete a message from Firebase I have to refresh the browser for the message list to update - so not in real time. I can't see where the problem is.
/*global Firebase*/
'use strict';
/**
* #ngdoc function
* #name firebaseProjectApp.controller:MainCtrl
* #description
* # MainCtrl
* Controller of the firebaseProjectApp
*/
angular.module('firebaseProjectApp')
.controller('MainCtrl', function ($scope, $timeout) {
var rootRef = new Firebase('https://popping-inferno-9738.firebaseio.com/');
var messagesRef = rootRef.child('messages');
$scope.currentUser=null;
$scope.currentText=null;
$scope.messages=[];
messagesRef.on('child_added', function(snapshot){
$timeout(function() {
var snapshotVal = snapshot.val();
console.log(snapshotVal);
$scope.messages.push({
text: snapshotVal.text,
user: snapshotVal.user,
name: snapshot.key()
});
});
});
messagesRef.on('child_changed', function(snapshot){
$timeout(function() {
var snapshotVal = snapshot.val();
var message = findMessageByName(snapshot.key());
message.text = snapshotVal.text;
});
});
messagesRef.on('child_removed', function(snapshot){
$timeout(function() {
var snapshotVal = snapshot.val();
var message = findMessageByName(snapshot.key());
message.text = snapshotVal.text;
});
});
function deleteMessageByName(name){
for(var i=0; i < $scope.messages.length; i++){
var currentMessage = $scope.messages[i];
if(currentMessage.name === name){
$scope.messages.splice(i, 1);
break;
}
}
}
function findMessageByName(name){
var messageFound = null;
for(var i=0; i < $scope.messages.length; i++){
var currentMessage = $scope.messages[i];
if(currentMessage.name === name){
messageFound = currentMessage;
break;
}
}
return messageFound;
}
$scope.sendMessage = function(){
var newMessage = {
user: $scope.currentUser,
text: $scope.currentText
};
messagesRef.push(newMessage);
};
});
The code that is invoked when a message is deleted from Firebase:
messagesRef.on('child_removed', function(snapshot){
$timeout(function() {
var snapshotVal = snapshot.val();
var message = findMessageByName(snapshot.key());
message.text = snapshotVal.text;
});
});
This code never actually deletes the message from the HTML/DOM.
There is a convenient deleteMessageByName method to handle the deletion. So if you modify the above to this, it'll work:
messagesRef.on('child_removed', function(snapshot){
$timeout(function() {
deleteMessageByName(snapshot.key());
});
});

Resources