Is there some how to detect changes on the window object? - reactjs

I;'m working in a project that's uses a custom browser. This custom browser injects an object inside the window object. I need to track the changes...something like...
componentDidMount() {
window.customObject.addListener('onchange' , (changes) => console.log(changes))
}
The example above is just hypothetical to make this thing more easy to understand. Is there some how to archive it ?

Yes, you can observe dom changes with MutationObserver api.
var observeDOM = (function(){
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
return function( obj, callback ){
if( !obj || !obj.nodeType === 1 ) return; // validation
if( MutationObserver ){
// define a new observer
var obs = new MutationObserver(function(mutations, observer){
if( mutations[0].addedNodes.length || mutations[0].removedNodes.length )
callback( mutations[0] );
});
// have the observer observe foo for changes in children
obs.observe( obj, { childList:true, subtree:true });
}
else if( window.addEventListener ){
obj.addEventListener('DOMNodeInserted', callback, false);
obj.addEventListener('DOMNodeRemoved', callback, false);
}
}
})();
Usage example:
// Observe a specific DOM element:
observeDOM(document.querySelector('body'), function(m) {
console.log('Added:', m.addedNodes, 'Removed:', m.removedNodes);
});

Related

Remove $watch and bring the logic out of the $watch in AngularJS

I have a code in AngularJS which looks like below :
$scope.startWatching = function () {
return $scope.$watch('form', function (n, o) {
var timeoutPromise;
$timeout.cancel(timeoutPromise); //does nothing, if timeout alrdy done
timeoutPromise = $timeout(function () {
if (n !== o) {
if ($scope.isLegacy) {
$scope.showCompleteBtn = $scope.showCompleteButton2();
} else {
$scope.showCompleteBtn = $scope.showCompleteButton();
}
}
}, 400);
}, true);
So whenever form changes, either $scope.showCompleteButton2() is called or $scope.showCompleteButton() is called.
The problem is that the $watch() gets called many number if times, so I need to bring these two methods out of the $watch().
Watchers like event listeners should only be added once when the DOM is built. And removed when the DOM is torn down.
If the code needs to enable or disable the actions performed by the watcher, provide a state in the model to do so:
var enableWatch = false;
$scope.startWatching = function () {
enableWatch = true;
};
var timeoutPromise;
$scope.$watch('form', function (n, o) {
if (!enableWatch) return;
//ELSE
timeoutPromise && $timeout.cancel(timeoutPromise);
timeoutPromise = $timeout(function () {
if (n !== o) {
if ($scope.isLegacy) {
$scope.showCompleteBtn = $scope.showCompleteButton2();
} else {
$scope.showCompleteBtn = $scope.showCompleteButton();
}
}
}, 400);
}, true);
The watcher ignores changes when the enableWatch variable is false. Set the variable to true to enable the specified actions.

Cant minify angular directive

I'm having an issue minifying one of my directives.
(function () {
angular.module("inflightApp.bnLazySrc", [])
.directive(
"bnLazySrc",
function( $window, $document) {
// I manage all the images that are currently being
// monitored on the page for lazy loading.
var lazyLoader = (function() {
// I maintain a list of images that lazy-loading
// and have yet to be rendered.
var images = [];
// I define the render timer for the lazy loading
// images to that the DOM-querying (for offsets)
// is chunked in groups.
var renderTimer = null;
var renderDelay = 100;
// I cache the window element as a jQuery reference.
var win = $( $window );
// I cache the document document height so that
// we can respond to changes in the height due to
// dynamic content.
var doc = $document;
var documentHeight = doc.height();
var documentTimer = null;
var documentDelay = 2000;
// I determine if the window dimension events
// (ie. resize, scroll) are currenlty being
// monitored for changes.
var isWatchingWindow = false;
// ---
// PUBLIC METHODS.
// ---
// I start monitoring the given image for visibility
// and then render it when necessary.
function addImage( image ) {
images.push( image );
if ( ! renderTimer ) {
startRenderTimer();
}
if ( ! isWatchingWindow ) {
startWatchingWindow();
}
}
// I remove the given image from the render queue.
function removeImage( image ) {
// Remove the given image from the render queue.
for ( var i = 0 ; i < images.length ; i++ ) {
if ( images[ i ] === image ) {
images.splice( i, 1 );
break;
}
}
// If removing the given image has cleared the
// render queue, then we can stop monitoring
// the window and the image queue.
if ( ! images.length ) {
clearRenderTimer();
stopWatchingWindow();
}
}
// ---
// PRIVATE METHODS.
// ---
// I check the document height to see if it's changed.
function checkDocumentHeight() {
// If the render time is currently active, then
// don't bother getting the document height -
// it won't actually do anything.
if ( renderTimer ) {
return;
}
var currentDocumentHeight = doc.height();
// If the height has not changed, then ignore -
// no more images could have come into view.
if ( currentDocumentHeight === documentHeight ) {
return;
}
// Cache the new document height.
documentHeight = currentDocumentHeight;
startRenderTimer();
}
// I check the lazy-load images that have yet to
// be rendered.
function checkImages() {
// Log here so we can see how often this
// gets called during page activity.
console.log( "Checking for visible images..." );
var visible = [];
var hidden = [];
// Determine the window dimensions.
var windowHeight = win.height();
var scrollTop = win.scrollTop();
// Calculate the viewport offsets.
var topFoldOffset = scrollTop;
var bottomFoldOffset = ( topFoldOffset + windowHeight );
// Query the DOM for layout and seperate the
// images into two different categories: those
// that are now in the viewport and those that
// still remain hidden.
for ( var i = 0 ; i < images.length ; i++ ) {
var image = images[ i ];
if ( image.isVisible( topFoldOffset, bottomFoldOffset ) ) {
visible.push( image );
} else {
hidden.push( image );
}
}
// Update the DOM with new image source values.
for ( var i = 0 ; i < visible.length ; i++ ) {
visible[ i ].render();
}
// Keep the still-hidden images as the new
// image queue to be monitored.
images = hidden;
// Clear the render timer so that it can be set
// again in response to window changes.
clearRenderTimer();
// If we've rendered all the images, then stop
// monitoring the window for changes.
if ( ! images.length ) {
stopWatchingWindow();
}
}
// I clear the render timer so that we can easily
// check to see if the timer is running.
function clearRenderTimer() {
clearTimeout( renderTimer );
renderTimer = null;
}
// I start the render time, allowing more images to
// be added to the images queue before the render
// action is executed.
function startRenderTimer() {
renderTimer = setTimeout( checkImages, renderDelay );
}
// I start watching the window for changes in dimension.
function startWatchingWindow() {
isWatchingWindow = true;
// Listen for window changes.
win.on( "resize.bnLazySrc", windowChanged );
win.on( "scroll.bnLazySrc", windowChanged );
// Set up a timer to watch for document-height changes.
documentTimer = setInterval( checkDocumentHeight, documentDelay );
}
// I stop watching the window for changes in dimension.
function stopWatchingWindow() {
isWatchingWindow = false;
// Stop watching for window changes.
win.off( "resize.bnLazySrc" );
win.off( "scroll.bnLazySrc" );
// Stop watching for document changes.
clearInterval( documentTimer );
}
// I start the render time if the window changes.
function windowChanged() {
if ( ! renderTimer ) {
startRenderTimer();
}
}
// Return the public API.
return({
addImage: addImage,
removeImage: removeImage
});
})();
// ------------------------------------------ //
// ------------------------------------------ //
// I represent a single lazy-load image.
function LazyImage( element ) {
// I am the interpolated LAZY SRC attribute of
// the image as reported by AngularJS.
var source = null;
// I determine if the image has already been
// rendered (ie, that it has been exposed to the
// viewport and the source had been loaded).
var isRendered = false;
// I am the cached height of the element. We are
// going to assume that the image doesn't change
// height over time.
var height = null;
// ---
// PUBLIC METHODS.
// ---
// I determine if the element is above the given
// fold of the page.
function isVisible( topFoldOffset, bottomFoldOffset ) {
// If the element is not visible because it
// is hidden, don't bother testing it.
if ( ! element.is( ":visible" ) ) {
return( false );
}
// If the height has not yet been calculated,
// the cache it for the duration of the page.
if ( height === null ) {
height = element.height();
}
// Update the dimensions of the element.
var top = element.offset().top;
var bottom = ( top + height );
// Return true if the element is:
// 1. The top offset is in view.
// 2. The bottom offset is in view.
// 3. The element is overlapping the viewport.
return(
(
( top <= bottomFoldOffset ) &&
( top >= topFoldOffset )
)
||
(
( bottom <= bottomFoldOffset ) &&
( bottom >= topFoldOffset )
)
||
(
( top <= topFoldOffset ) &&
( bottom >= bottomFoldOffset )
)
);
}
// I move the cached source into the live source.
function render() {
isRendered = true;
renderSource();
}
// I set the interpolated source value reported
// by the directive / AngularJS.
function setSource( newSource ) {
source = newSource;
if ( isRendered ) {
renderSource();
}
}
// ---
// PRIVATE METHODS.
// ---
// I load the lazy source value into the actual
// source value of the image element.
function renderSource() {
element[ 0 ].src = source;
}
// Return the public API.
return({
isVisible: isVisible,
render: render,
setSource: setSource
});
}
// ------------------------------------------ //
// ------------------------------------------ //
// I bind the UI events to the scope.
function link( $scope, element, attributes ) {
var lazyImage = new LazyImage( element );
// Start watching the image for changes in its
// visibility.
lazyLoader.addImage( lazyImage );
// Since the lazy-src will likely need some sort
// of string interpolation, we don't want to
attributes.$observe(
"bnLazySrc",
function( newSource ) {
lazyImage.setSource( newSource );
}
);
// When the scope is destroyed, we need to remove
// the image from the render queue.
$scope.$on(
"$destroy",
function() {
lazyLoader.removeImage( lazyImage );
}
);
}
// Return the directive configuration.
return({
link: link,
restrict: "A"
});
});
}());
Because you need to annotate your functions with the names of the dependencies.
See the documentation.

Double click on a map object in amMaps using AngularJS

I am working on an application which is using ammaps. I have a number of points located on the map based on longitude and latitude value. I have achieved single click functionality by using the following code:
map.addListener("clickMapObject", function (event) {
$scope.$apply(function(){
$scope.colorPoints();
$scope.selectedRow = event.mapObject.idBase;
});
});
I want to achieve the functionality of double click. Could anyone let me know how I could do that in amMaps.
Technically, amMap does not support double-click events. However, you can simulate it with a clickMapObject event.
For that you'll need to ignore the first click. If the subsequent clickMapObject happens within 500ms or so, you register it as double-click.
Something like this:
map.addListener( "clickMapObject", function( event ) {
if ( false !== map.clickedObject && map.clickedObject === event.mapObject ) {
// doubleckick
map.clickedObject = false;
$scope.$apply( function() {
$scope.colorPoints();
$scope.selectedRow = event.mapObject.idBase;
} );
} else {
clearTimeout( map.clickedObjectTimeout );
map.clickedObject = event.mapObject;
map.clickedObjectTimeout = setTimeout( function() {
map.clickedObject = false;
}, 500 );
}
} );

Backbone.js - model.save() not firing a PUT request

I have a basic application using Backbone.js that is not making PUT calls (updating model). From the front-end, I calling a models save function doesn't make a PUT call; however, if I replace it with destroy, it does make a DELETE call to the back-end. Anyone have any idea what might be the issue? The function that is not firing a PUT request is the saveTask function.
App.Views.Task = Backbone.View.extend({
template: _.template("<label>ID:</label><input type='text' id='taskId' name='id' value='<%= _id %>' disabled /><br><label>Title:</label><input type='text' id='title' name='title' value='<%= title %>' required/><br><label>Content:</label><input type='text' id='content' name='content' value='<%= content %>'/><br><button class='save'>Save</button>"),
events: {
"change input":"change",
"click .save":"saveTask"
},
render: function(eventName){
$(this.el).html(this.template(this.model.toJSON()));
//console.log(this.generateTemplate());
return this;
},
change: function(event){
var target = event.target;
console.log('changing ' + target.id + ' from: ' + target.defaultValue + ' to: ' + target.value);
change[target.name] = target.value;
this.model.set(change);*/
},
saveTask: function(){
this.model.set({
title:$("#title").val(),
content:$("#content").val()
});
if(this.model.isNew()){
App.taskList.create(this.model);
} else {
this.model.save({});
}
}
});
If your model is new, then at the time you save it it will fire a post method.
If your model however is not new and you are updating it, it will fire a PUT.
if this is not working for you it may be because your model does not have an id property, in case you are using an id with a different name, for example taskID, then in your model you have to set the idAttribute to taskID so backbone uses this property as the Id and everything will be normal.
like this:
var Task= Backbone.Model.extend({
idAttribute: "taskId"
});
here is the link to the documentation on Idattibute
http://backbonejs.org/#Model-idAttribute
also another problem could be the {} in your save call
try just
this.model.save();
instead of
this.model.save({});
I believe model is always expecting options parameter and also probably the callbacks
this.model.save(null, {
success: function (model, response) {
//
},
error: function () {
//
}
});
If you look at Backbone src, you will notice that too...
======
// Set a hash of model attributes, and sync the model to the server.
// If the server returns an attributes hash that differs, the model's
// state will be `set` again.
save: function (key, val, options) {
var attrs, method, xhr, attributes = this.attributes;
// Handle both `"key", value` and `{key: value}` -style arguments.
if (key == null || typeof key === 'object') {
attrs = key;
options = val;
} else {
(attrs = {})[key] = val;
}
options = _.extend({
validate: true
}, options);
// If we're not waiting and attributes exist, save acts as
// `set(attr).save(null, opts)` with validation. Otherwise, check if
// the model will be valid when the attributes, if any, are set.
if (attrs && !options.wait) {
if (!this.set(attrs, options)) return false;
} else {
if (!this._validate(attrs, options)) return false;
}
// Set temporary attributes if `{wait: true}`.
if (attrs && options.wait) {
this.attributes = _.extend({}, attributes, attrs);
}
// After a successful server-side save, the client is (optionally)
// updated with the server-side state.
if (options.parse === void 0) options.parse = true;
var model = this;
var success = options.success;
options.success = function (resp) {
// Ensure attributes are restored during synchronous saves.
model.attributes = attributes;
var serverAttrs = model.parse(resp, options);
if (options.wait) serverAttrs = _.extend(attrs || {}, serverAttrs);
if (_.isObject(serverAttrs) && !model.set(serverAttrs, options)) {
return false;
}
if (success) success(model, resp, options);
model.trigger('sync', model, resp, options);
};
wrapError(this, options);
method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update');
if (method === 'patch') options.attrs = attrs;
xhr = this.sync(method, this, options);
// Restore attributes.
if (attrs && options.wait) this.attributes = attributes;
return xhr;
},
In my case it fails due to validations.As i save the model it validates all the attributes of the model and the collection which i am using for listing interface doesn't required all the attributes of the model.
I was facing the same issues and search in Google and found your question and read the solution and comments.Than i realize that in updated backbone specifications it is mentioned that when model.save() executes before model requests,it first call validate and if validate succeeds than it will go ahead other wise fails, and that is the reason why it doesn't showing any network request in chrome debugger network tab.
I have write the solution for the case which i am facing,other might be facing different issues.
Backbone's sync function is what I wound up using. You have to pass in 'update' as the first parameter (the 'method' parameter).

Backbone.js — Call method before/after a route is fired

I want a setup/teardown method to be called before and after a route is fired in my Backbone.js router, respectively. Has anyone created an elegant way of doing this?
_.wrap is not a solution, if You have for example 20 routes you have to wrap them all.
But you can do this with metaprogramming
class Backbone.FlexRouter extends Backbone.Router
route: (route, name, handler) ->
super route, name, ->
#trigger "route:before"
handler()
#trigger "route:after"
UPD: I believe in JS it should be something like this (but I didn't tested it)
var rp = Backbone.Router.prototype
rp.routeWithoutEvents = rp.route
rp.route = function(route, name, handler){
var that = this
this.routeWithoutEvents(route, name, function(){
that.trigger("route:before")
handler()
that.trigger("route:after")
})
}
Have you considered _.wrap?
Here is the simple one, overriding the Backbone.Router itself
(function () {
_.extend(Backbone.Router.prototype, Backbone.Events, {
route: function (route, name, callback) {
if (!_.isRegExp(route)) route = this._routeToRegExp(route);
if (!callback) callback = this[name];
Backbone.history.route(route, _.bind(function (fragment) {
var args = this._extractParameters(route, fragment);
if (this.before && _.isFunction(this.before)) {
this.before(fragment);
}
callback && callback.apply(this, args);
this.trigger.apply(this, ['route:' + name].concat(args));
if (this.after && _.isFunction(this.after)) {
this.after(fragment);
}
Backbone.history.trigger('route', this, name, args);
}, this));
return this;
}
});
}).call(this);
Focus on the lines
if (this.before && _.isFunction(this.before)) {
this.before(fragment);
}
AND
if (this.after && _.isFunction(this.after)) {
this.after(fragment);
}
You can modify the lines according to your needs
And here is the client code using the new Backbone.Router class
var appRouter = Backbone.Router.extend({
routes: {},
before: function(){
//your code here
return true;
}
});
Alexey's answer is almost right, but there are a few subtle things that are missing.
class ApplicationRouter extends Backbone.Router
route: (route, name, callback = null) ->
callback = #[name] if ! callback
super route, name, ->
#trigger 'route:before'
result = callback && callback.apply(#, arguments)
#trigger 'route:after'
return result
This plugin does what you want. It works with 0.5.3. I'm not certain if it works with 0.9.1 yet or not.
https://github.com/angelo0000/backbone_filters
I came across this problem earlier and I thought I would share my solution for inserting "middleware" into the Backbone routing flow. The goal was to reroute users to various flows depending on some condition, e.g., feature flags, session handling, etc..
Backbone.ProtectedRouter = Backbone.Router.extend({
/*
* Subclass of Router that monkeypatches route in order to protect certain
* routes.
*
* If you want to add a protected route, add it to the protectedRoutes
* object in this form:
* route: { method: fn, assertion: fn, args: [args..] }
*
* * method => the method to call if the assertion is true (the route should
* be protected in the given scenario)
*
* * assertion => the function that decides whether or not the route
* should be rendered
*
* * args => the arguments to be passed to method
*/
route: function(route, name, handler) {
var _this = this;
Backbone.Router.prototype.route(route, name, function(){
var boundHandler = _.bind(handler, _this),
attrs, method, args, dfd;
attrs = _.has(_this.protectedRoutes, route) ? _this.protectedRoutes[route] : null;
if ( attrs && !attrs.assertion() ) {
// In this scenario my flows all return Deferreds
// you can make this event based as well.
dfd = _this[attrs.method].apply(_this, attrs.args.concat([route]));
dfd.then(boundHandler);
} else
boundHandler.apply(_this, arguments);
});
}
});
From there you can simply extend the Backbone.ProtectedRouter with a protectedRoutes hash as so:
var router = Backbone.ProtectedRouter.extend({
protectedRoutes: {
'home': {
assertion: function() { return is_logged_in; },
method: 'renderLogin',
args: ['some_arg']
}
},
routes: {
'home': 'renderHome'
},
...
});
In this scenario, if a request is made for the home route and is_logged_in is false, the renderLogin method is invoked and passed 'some_arg'. After the flow, renderLogin would return a resolved Deferred that causes the original handler (renderHome) to be invoked.
I hope this helps. I'm very open to suggestions as well! :)
I came across this need recently (to check user is authenticated). Unfortunately Backbone doesn't give us a before/after event, so you will need to overwrite or extend the Router.route. Doesn't feel very clean since you have to copy from source code and edit there, but is the only way I found. Below Backbone default code (1.0.0) and marked my custom code:
Backbone.Router.prototype.route = function(route, name, callback) {
if (!_.isRegExp(route)) route = this._routeToRegExp(route);
if (_.isFunction(name)) {
callback = name;
name = '';
}
if (!callback) callback = this[name];
// here my custom code
callback = _.wrap(callback, _.bind(function(cb) {
if (name == 'login' || sessionModel.authenticated()) {
_.bind(cb, this)();
} else {
this.navigate('login', {trigger: true});
}
}, this));
// finish my custom code
var router = this;
Backbone.history.route(route, function(fragment) {
var args = router._extractParameters(route, fragment);
callback && callback.apply(router, args);
router.trigger.apply(router, ['route:' + name].concat(args));
router.trigger('route', name, args);
Backbone.history.trigger('route', router, name, args);
});
return this;
};
Notice _.wrap and _.bind so this is the one that you would expect when using the router. Otherwise I was getting a "this is undefined" error.
ethnagnawl and Alexey are both correct; _.wrap is the right solution but if you have a bunch of routes and write them in the normal backbone fashion it'll be a pain. I realized you can do this:
var Pages = {}
Pages.loginPage = function(){ ... }
Pages.mainPage = function(){ ... }
Instead of defining your route handlers directly in Router.extend, load them into an object and then do this:
_.map(Pages,function(func,name){
Pages[name] = _.wrap(func,function(funky){
// Save original arguments
var args = Array.prototype.slice.call(arguments,1);
// Do stuff before the route
funky(args);
// Do stuff after the route
});
});
This also makes it pretty easy to check for the function name if you need to treat a subset of them differently or something. Then, because it's just an object, you can do this:
var myRouter = Backbone.Router.extend({
routes: ... /* as usual */
}).extend(Pages);
And you're done.
One nice advantage of this is it involves no messing with the Backbone prototypes, so even if a version update changes something it won't bite you.
after doing lot more manipulations. i came to a solution that i have given below......
Here ur original root function ...
route: function(route, name, callback) {
if (!_.isRegExp(route)) route = this._routeToRegExp(route);
if (_.isFunction(name)) {
callback = name;
name = '';
}
if (!callback) callback = this[name];
var router = this;
Backbone.history.route(route, function(fragment) {
var args = router._extractParameters(route, fragment);
callback && callback.apply(router, args);
router.trigger.apply(router, ['route:' + name].concat(args));
router.trigger('route', name, args);
Backbone.history.trigger('route', router, name, args);
});
return this;
}
Now look at this code & change the "route" function to your original Backbone.js...
route: function(route, name, callback) {
if (!_.isRegExp(route)) route = this._routeToRegExp(route);
if (_.isFunction(name)) {
callback = name;
name = '';
}
if (!callback) callback = this[name];
var router = this;
Backbone.history.route(route, function(fragment) {
// takes matched route & fragment as like 'route1'
var args = router._extractParameters(route, fragment);
// extracts arguments if exists
// here yours self invoking function or other function starts....
(function(){
// do something
if ( true ) // condition satisfies then route to the given Route
{
callback && callback.apply(router, args);
}
else{
name='route2'; // change name of route
window.location.hash = 'route2';
callback= function(){
// optional callback if u want
}
callback && callback.apply(router, args); // route to ur custome Route
}
})();
});
return this;
}
----- Thank You --------
Love 2 write Dirty Codes !
#xy....
Here is a JavaScript version that works with what I've got;
var rp = Backbone.Router.prototype;
rp.routeWithoutEvents = rp.route;
rp.route = function(route, name, callback) {
if (!callback) callback = this[name];
this.routeWithoutEvents(route, name, function() {
this.before.apply(this);
callback.apply(this,arguments);
this.after.apply(this);
});
};
It's based on Alexey Petrushin's and Jonathan Tran's solutions.
I could not find an easy way to intercept the routing event before the route handler is called.
My solution is to extend the Router component, adding a registerBeforeRouting method and editing the route method (I took it from the Backbone 1.0 and it worked, YMMV with different Backbone versions).
Before the router is created:
var rp = Backbone.Router.prototype;
rp.registerBeforeRouting = function (callback) {
this._beforeRoutingCallback = callback;
};
rp.route = function (route, name, callback) {
if (!_.isRegExp(route)) route = this._routeToRegExp(route);
if (_.isFunction(name)) {
callback = name;
name = '';
}
if (!callback) callback = this[name];
var router = this;
Backbone.history.route(route, function(fragment) {
var args = router._extractParameters(route, fragment);
// Edit starts here
// This will trigger the callback previously set
if (typeof router._beforeRoutingCallback === 'function') {
router._beforeRoutingCallback();
}
// Edit stops here.
callback && callback.apply(router, args);
router.trigger.apply(router, ['route:' + name].concat(args));
router.trigger('route', name, args);
Backbone.history.trigger('route', router, name, args);
});
return this;
}
Then, during router initialization:
this.registerBeforeRouting(function() {
console.log("Hello world");
});
I tried the aforementioned approaches, and they somehow just didn't work for me (probably for my lack of in depth understanding of neither backbone, nor javascript in general).
I did manage to do the trick in some other manner, if that's of any interest to anyone out there:
What I actually end up doing was simply extending the View and overriding the render function just one time.
MyApp.BindedView = Backbone.View.extend({
_realRender : null,
initialize : function(){
//validating user is logged in:
if(Backbone.history.fragment != 'login' && !myUser.authenticated())
{
console.log('not authorized, redirecting');
var self = this;
this._realRender = this.render;
this.render = function(route,name,callback){
appRouter.navigate('login');
self.render = self._realRender;
}
return;
}
this.delegateEvents();
}
});
The execute method was added to be overridden for this purpose. See this example extracted from the backbonejs homepage:
var Router = Backbone.Router.extend({
execute: function(callback, args, name) {
if (!loggedIn) {
goToLogin();
return false;
}
args.push(parseQueryString(args.pop()));
if (callback) callback.apply(this, args);
}
});

Resources