backbone.js,browser-history,pushstate,backbone-routing , Preventing page navigation inside a Backbone-driven SPA


Preventing page navigation inside a Backbone-driven SPA

Question:

Tag: backbone.js,browser-history,pushstate,backbone-routing

The justification

In my BB app, I allow rapid input from users which gets queued & sent off periodically in the background to the server. The problem I currently have is if a user leaves the page they effectively discard any pending changes sitting in the queue.

So basically what I want to do is inform the user before they leave to give them the opportunity to wait for the changes to be saved rather than just exiting & discarding.

The nitty gritty

So for the general cases where the user refreshes or attempts to navigate to an external URL we can handle the onbeforeunload event. Where it becomes slightly tricky is when we are in the context of an SPA whereby switching between pages does not cause a page refresh.

My immediate thought was to use a global click event handler for all anchors and validate whether or not I want to allow the click, which would work for in-site link navigation. However, where this falls over is navigating via the browsers Back/Forward buttons.

I also had a look at Backbone.routefilter, which at first glance appeared to do exactly what I needed. However, using the simple case as described in the docs, the route was still being executed.

The question

How do we intercept navigation for all scenarios within a Backbone SPA?


Answer:

Direct link navigation

Use a global event handler to capture all click events

$(document).on('click', 'a[href^="/"]', function (e) {
    var href = $(e.currentTarget).attr('href');
    e.preventDefault();
    if (doSomeValidation()) {
        router.navigate(href, { trigger: true });
    }
});

Page refreshing / external URL navigation

Handle the onbeforeunload event on the window

$(window).on('beforeunload', function (e) {
    if (!doSomeValidation()) {
        return 'Leaving now will may result in data loss';
    }
});

Browser back/forward button navigation

Behind the scenes Backbone.Router uses the Backbone.history which ultimately leverages the HTML5 pushstate API. Depending on what options you pass to Backbone.history.start, and what your browser is capable of, the API will hook into either the onhashchange event or the onpopstate event.

Delving into the source for Backbone.history.start it becomes apparent that regardless of whether you are using push state or not, the same event handler is used i.e. checkUrl.

if (this._hasPushState) {
    addEventListener('popstate', this.checkUrl, false);
} else if (this._wantsHashChange && this._hasHashChange && !this.iframe) {
    addEventListener('hashchange', this.checkUrl, false);
} else if (this._wantsHashChange) {
    this._checkUrlInterval = setInterval(this.checkUrl, this.interval);
}

Therefore, we can override this method & perform our validation in there

var originalCheckUrl = Backbone.history.checkUrl;
Backbone.history.checkUrl = function (e) {
    if (doSomeValidation()) {
        return originalCheckUrl.call(this, e);
    } else {
        // re-push the current page into the history (at this stage it's been popped)
        window.history.pushState({}, document.title, Backbone.history.fragment);
        // cancel the original event
        return false;
    }
};

Related:


Handlebars: return hash from helper


javascript,backbone.js,coffeescript,handlebars.js,handlebars
Can i return hash from Handlebars helper? I tried this: In my view: initialize: -> super this.hash = {key1: 'test1', key2: 'test2'} Handlebars.registerHelper 'show', => return this.hash In template: {{show.key1}} What am i doing wrong? Thanks!...

Backbone.Deferred.Model: Why the unittest is not run?


backbone.js,coffeescript,phantomjs,mocha,chai
Here is the code in question. define (require) -> Backbone = require 'backbone' require 'backbone-deferred' class Data extends Backbone.Deferred.Model urlRoot: 'data' parse: (resp) -> resp.record or resp isValid: -> @get 'valid' # Newly introduced dataUrl: -> @get('data_url')?.replace /abc/, '' And here is the unit test define (require) -> Data =...

Persisting data client side for event driven approach


javascript,backbone.js
I have an application that renders activities and looks like this: The map should render markers based on some criteria (date_start, date_end, map_bounds). Activities are loaded from a REST api with ajax. The front end approach is event driven (using Backbone / Marionette); activities are dynamically udpated when the date...

Backbone localstorage - A “url” must be specified (without view)


backbone.js
I know there are more similar questions like this, but I really couldn't find the answer to my problem.. Here is my jsfiddle: http://jsfiddle.net/ktyghnL1/3/ Code: var Todo = Backbone.Model.extend({ }); var Todos = Backbone.Collection.extend({ model: Todo, localStorage: new Backbone.LocalStorage('todos-backbone'), comparator: 'order' }); todos = new Todos(); I am only using...

Backbone datatypes - type casting?


javascript,backbone.js
It just took me over an hour to find out that a Backbone query on a collection was failing because I queried the wrong data type. So this query failed because I used the wrong data type for id: element = collection.findWhere({id: "123", att: true}); This one worked and returned...

How to detect model parameter change event in mithril.js?


javascript,backbone.js,mithril.js
I recently started learning mithril.js and I'm wondering how can I make very basic Model -> View one way data binding app. TestModel = function(data){ this.name = m.prop(data.name) } testModel = new TestModel({name: "John"}) code above declare a model and it works perfectly as getter/setter. but how can I set...

Can't call fetch directly in Backbone model listenTo


javascript,backbone.js,coffeescript
I'm trying to have a model listen to a collection and fetch itself when the collection changes: class Team extends Backbone.Model urlRoot: '/team', initialize: function(attributes, options) { this.listenTo(members, 'change', this.fetch) The fetch does seem to trigger, but the url is all messed up, and to get it to work I...

how to use bootstrap mergeCells dynamically in backbone.js


javascript,twitter-bootstrap,backbone.js,bootstrap-table
I have a function which creates a bootstrap table and i have to merge only specific columns in that table dynamically. this.$('#Table1').bootstrapTable({ striped: false, minimumCountColumns: 2, smartDisplay:true, clickToSelect: false, columns:[ { field:'Key2', title: $.t('report:'+code+'.Col2'), align: 'left', valign: 'middle', sortable: true, events : this.linkEvents formatter :this.linkFormatter } ] }); linkEvent function:...

Delete single model from collection in Backbone.View


javascript,backbone.js,collections,model
var PlayersView = Backbone.View.extend({ collection: players, //collection of players el: "#playersList", //I bind to the class render: function () { this.$el.html(""); for (var i=0; i<this.collection.size(); i++) { var player = this.collection.at(i); this.$el.append("<li "+"value='"+player.get("id")+"'>"+player.get("names")[0]+" "+player.get("surnames")[0]+" <a href='#' class='edit'>[edit]</a>"+"</li>"); } //what I render is in the picture below return this; }, events:...

$(window).bind('load' … ); not triggering


javascript,jquery,backbone.js,requirejs
I'm currently working at making a web application only open one instance. This is being done with cookies that are being set/checked when the app is loaded and removed when the app is closed. My logic for setting the cookies I've already worked out, but I'm having a problem getting...

Marionette CompositeView - change in template each nth items


twitter-bootstrap,backbone.js,marionette,composite-view
I'm using Marionette for a while, but I'm not sure how I can do what I want, in a simple manner. I have a composite view, which renders something like this: <div class="row"> <div class="col-xs-12"> <div id="items"></div> </div> </div> Each of my item is being rendered as a: <div class="col-xs-3">foo</div>...

Where to format collections / objects


javascript,backbone.js,architecture,project-structure
From front end architectural point of view, what is the most common way to store scripts that perform transformations on collections of objects/models? In what folder would you store it, and what would you name the file / function? Currently I have models, views, controllers, repositories, presenters, components and services....

Backbone view listening to model, not firing on change or reset?


backbone.js,backbone-views,backbone-events,backbone-model
I am using a model to fetch location data from a service using POST. However I am struggling to get the view to listen to that model when it finally receives a response. Note I have overriden some model methods to fit the service I am using. Model code define([...

Backbone's success callback called before jquery's ajaxSuccess


jquery,ajax,backbone.js,callback
I would like to make sure that jQuery's ajaxSuccess callback is called before Backbone's success, which is not the case in my experience. I would like this someModel.fetch({ success: function() { console.log('2'); } }); $(document).ajaxSuccess(function(event, xhr, ajaxOptions) { console.log('1'); }); to log 1, 2 and not 2, 1. The reason...

What is the use of HTML5 pushState in Backbone History Start method


javascript,html5,backbone.js
I have a simple Backbone app. I am trying to understand the difference created by passing pusState: true when starting Backbone.History object. JavaScript var r = new (Backbone.Router.extend({ routes: { "users": "allUsers", "users/new": "createUser" }, allUsers: function () { v.render("showing all users"); }, createUser: function () { v.render("showing form for...

How to access Rails configuration info in Backbone View?


javascript,ruby-on-rails,backbone.js,stripe-payments
I'm trying to implement Stripe into a Rails app with a Backbone front end. In a normal rails view, I can do this: <%= form_tag charges_path do %> <article> <label class="amount"> <span>Amount: $5.00</span> </label> </article> <script src="https://checkout.stripe.com/checkout.js" class="stripe-button" data-key="<%= Rails.configuration.stripe[:publishable_key] %>" data-description="Launch Survey" data-amount="<%= @amount %>"></script> <% end %> And...

Do backbone marionette.js parent view bubble down?


javascript,backbone.js,marionette
I reference this question and document I know how to bubble up. But in my situation, I want to bubble down. Just like I click a button on parent view then trigger some function of all my childview. var parent = Marionette.CompositeView.extend({ triggers: { 'click #edit': "??" // trigger the...

Backbone render template in side el's nested id


javascript,jquery,backbone.js
I have my html setup like this. <div id="product-module"> <ul id="product"> <li><input name="product" type="radio"/></li> <li><input name="product" type="radio"/></li> <li><input name="product" type="radio"/></li> </ul> <table id="quantities"/> <script id="myTemplate" type="text/x-handlebars-template"> {{#each this}} <tr> <td class="quantity"> <label class="checked" for="quantity_{{id}}"> <input type="radio" value=""...

Marionette - listenTo a custom event triggered from a collection


javascript,backbone.js,marionette
I'm using a Event Aggregator(EA) to keep track of all events in my app. But there is one situation I could not make the EA listen to a custom event triggered from a collection. See more details below. eMgr (Event Manager i.e Event aggregator): define(['backbone.wreqr'],function(Wreqr){ "use strict"; return new Wreqr.EventAggregator();...

Truncate everything after first 120 characters and refresh


javascript,jquery,backbone.js
I'm quite new to UI development. I have a textfield. (input) where the user enters a string for SMS. I want to discard all the characters which are more than 120. I have written code for this one. Problem: if the user enters more than 120 characters, how do I...

View is not a constructor for Backbone under Typescript


javascript,backbone.js,typescript
I am trying to create a Backbone.js view in Typescript. I get the following error: TypeError: ExampleView is not a constructor in http://localhost:57258/Tests/spec/ExampleViewTest.js (line 17) My view is instantiated like this: var view = new ExampleView(); The view is declared like this: ///<reference path="../Scripts/typings/backbone/backbone.d.ts"/> class ExampleView extends Backbone.View { constructor(options?:...

CSS Selector Equivalent Of jQuery.find in backbone.js?


javascript,jquery,backbone.js,selector
I have a Marionette view that has the following code: onRender: { $('#someDiv').find('a').click(function(){ // some code here }); } But I want to refactor to something like this: events: { 'click [selector here]': 'executeCode' }, executeCode: function() { // some code here } Is this possible?...

passing backbone collection to view


grails,backbone.js,handlebars
I'm just starting out with backbone / grails and i've been struggling to figure out how to get everything to work. I'm building a pricing configurator where a user selects a product type from radio group A and radio group B containing the quantity / pricing / discount data will...

Why `init` of shim in my require.js configuration not called?


javascript,django,backbone.js,requirejs,csrf
Update: I was writing a small module to handle this csrf token problem in backbone until I got push notification of @Louis's answer. His answer is quite elegant and seems nice, but I'll leave a link to my backbone.csrf module github repo just for anyone who needs it. ==================================================================== I'm...

Can I use Backbone with React Native?


javascript,ios,backbone.js,reactjs,react-native
I have found several different examples of integrating React (View) with Backbone on the web, but not any to do the same with React Native. I was wondering if this was possible and also if there were any samples to play with. This (https://github.com/magalhas/backbone-react-component) also seemed a good starting point,...

Dropzone.js status is pending and not uploading a file


javascript,node.js,backbone.js,express,dropzone.js
I am using Multer in back-end to handle file upload and Dropzone.js in front-end. Everything is fine when I use Postman to test my back-end code, but in when I use Dropzone the status is pending and file not getting uploaded. Then after 4 minutes of waiting I get Timeout...

Backbone.js remove model from collection


javascript,backbone.js,backbone-collections
I'm learning Backbone and for the life of me I can't remove a model from a collection. The collection 'remove' event fires, but the collection appears to remain the same. Here's what I have so far: http://jsbin.com/becamo/edit?js,output I remove the model from the collection upon click. Then, the list view...

Changing URL as long as you are scrolling the webpage


javascript,html,url,browser,browser-history
I was seeing the NASA's press release / image gallery, (you can see it here) and it has come to my attention that as I'm scrolling down the webpage and seeing different posts, the URL in the address bar was changing (I was using chrome, but tried in Internet Explorer...

Backbone Collection only fetched after executing alert


node.js,backbone.js,express,handlebars.js,jade
Hey I am new to backbone and Handlebars and something strange is happening with my code that I cannot figure out. Basically my node app queries mongo for some data which is then used by backbone and handlebars to relay the data to the user. When I try to relay...

Backbone.js - Model's attribute is not getting passed to view correctly


backbone.js
I am very new to backbone and trying to understand why "title" is not getting passed to view and printing correctly. If I create model with title properties it passes to view and prints fine. Any pointer will be greatly appreciated. HTML: $(document).ready(function(){ //Model var Appointment = Backbone.Model.extend({ urlRoot :...

Backbone.js collection fetch not setting response objects as models


backbone.js,collections,fetch
When fetching a collection, my api response has 10 objects, but the resulting Backbone collection only has 1 model with an attributes array containing the 10 response objects....to put it another way, the fetch is not creating models out of the objects in my response...and I don't know why. Model...

BackboneJS : the model is fetched, but toJSON() and get() methods don't work [duplicate]


javascript,backbone.js
This question already has an answer here: View's collection only working in console.log 3 answers Still learning Backbone, here is my code const API_URL = 'http://api.brewerydb.com/v2'; const API_KEY = '********************************'; var Categories = Backbone.Model.extend({ url: API_URL + '/categories/?key=' + API_KEY }); var CategoriesView = Backbone.View.extend({ tagName: 'ul', id: 'categories',...

Backbone this.el is undefined


jquery,backbone.js
I've been following along to the a tutorial i found on youtube. https://www.youtube.com/watch?v=vPW1inIsln4 In the tutorial I don't see him defining el : ... but he's calling this.$el and it appears to be working. In jsfiddle, I have been following along, but get a js error saying Backone this.el is...

backbone stickit - reverting model changes


javascript,backbone.js,2-way-object-databinding
I'm now testing backbone stickit for two-way data binding. Is there a way to revert the changes, for example, while editing a model data through a form, the user press the cancel button, as in the pic below It seems the model was changed on the fly as we type...

What is the correct way to override Marionette compositeview render


backbone.js,marionette
I am showing a table view using Marionette's composite view. The composite view's template has a tbody with an initial which shows a loadding animation gif. Now, when the render method is called, I want to remove this initial row and then append the results of collection fetch. However the...

Underscore templates with Backbone


javascript,backbone.js,underscore.js,underscore.js-templating
I'm completely new in backbone framework. I have a model itemsOnSaleModel that contains an array of items and a View itemListView that render these items. The problem is that I can't figure out how to write the template correctly. Usually in this case I would have written something like this:...

Comparison Express JS, Angular JS vs Backbone JS [closed]


angularjs,backbone.js,express,requirements
I am starting to learn node js for a while and it seem amazing. When I start to apply nodejs to build a scalable website, I am wondering to do Express for back-end, BackBone Js or Angular JS for front-end, people said Express JS is very fast, while Backbone.js seem...

Add two events in backbone.js


javascript,jquery,backbone.js
I added two jQuery events, the second jQuery event is not triggering. What might be the issue? Here is my code : var ListView = Backbone.View.extend({ events: function() { $('#couponcheck2').click(function(e) { e.preventDefault(); $('#couponcheck').empty(); $('#couponcheck').append('<div class="col-xs-8"><input type="text" class="form-control" id="enterCoupon"></div>'); $('#couponcheck').append('<div class="col-xs-8"><button type="button" class="btn btn-success btn-sm" id="couponbutton"><span...

backbone persistent login - login removed on browser quit


javascript,rest,authentication,backbone.js,login
I am working on a backbone application that hooks into RESTful API. One problem I having at the moment, is that a user can be logged, they can then close there browser, reopen it go to my application and be logged out. Is is possible to make a login persistent...

How to let Webpack require a root node_module instead of an child package?


backbone.js,npm,webpack
I have installed backbone and backbone.babysitter trough npm. When I use backbone in my scripts like this: import Backbone from "backbone"; It loads the installed backbone version 1.2.1. This works fine until I want to use backbone.babysitter. When backbone.babysitter loads it needs to add properties to backbone itself. But the...

Javascript DOM elements hide class and the element not present are same?


javascript,backbone.js
I am currently working on a project where most of the code has been written by someone else . I was supposed to do some slight modifications in the existing script to incorporate changes in a new file. I came across a situation where it was very confusing . The...

CollectionView - collection data not being passed to childView


javascript,backbone.js,marionette
I'm trying to make the collectionView work , but I'm not really sure whether the CollectionView initiates the fetch method automatically and then populates the ChildViews with the fetched data. Or is it something I need to do manually? I have checked the Marionette doc page but I couldn't find...

Backbone JS - Combination of collection, views and models


backbone.js,backbone-views,backbone-collections,backbone-model
I had the following setup now in three different projects, so I thought maybe it's worth asking here. There's a chance I'm not the only guy wondering about this. So there it comes: I have a list of objects The list items have a special function like draggable or onClick-Events...

Grab data attribute from an event


javascript,jquery,backbone.js
I have a jQuery event which is part of a backbone class that I am trying to grab the data-attribute from called 'data-foreground' My function looks as follows.. foreground: function(e) { if (e.target.id === "") { this.findClickedElement(e, "li"); return false; } console.log(e.target.id); // this returns the id which is '115'...

Extend Coffeescript subclass function from parent in marionette


javascript,backbone.js,coffeescript,marionette
I've got a "FormView" class in my Marionette application that sets up a lot of things for form submissions around my app. I use it every time there is a form. I've also got some helpers that I want to pass into every form template via the templateHelpers method, but...

bacbone marionette pass variable to view method


javascript,backbone.js,marionette
I have simple situation and can't understand why variable that I pass to function always undefined. var ProjectItemView = Backbone.Marionette.ItemView.extend({ template: "#ProjectItemTemplate", initialize: function () { var id = this.model.get('project_id'); $.getJSON('service/api.php/projects/' + id + '/progress').done(function (data) { this.renderProgress('4'); //<== pass here }); }, renderProgress: function (why) { alert(why); //<== undefined...

How to inherit and add events in child in backbone.js


javascript,backbone.js
I have tried this solustion but couldn't get it working. So situation is there a parent which doesn't have any event defined. I can not make any change in parent. I can make changes only in child modules so I need to have two child modules both adding a different...

Merge two object arrays for Chart


javascript,arrays,backbone.js,lodash
I've two arrays which I'm going to merge and then load in chart. range = date array generated from moment.js, there is date of every day in example one month or specific date range with one another attribute count: "0" data = fetched data from database through backbone Now I...

Backbone.Marionette + Rails app redirects after form submission. Why?


javascript,ruby-on-rails,forms,backbone.js,marionette
I have a sample app that I'm working on that uses Ruby on Rails for the server backend and Backbone.Marionette for the client-side. The main functionality is a form to "order a widget". I'm using backbone-forms to create the form. The oddity that is throwing things off is that once...

backbone - preventing same view from overlapping


javascript,backbone.js
Let say a each row in a table got its own view and a model (CollectionViews). Each row got a button for editing the row data. When clicked an EditView is activated for the current row and model where a form is presented to the user with textfield and cancel...