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:
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.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 =...
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.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...
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...
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...
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...
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:...
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:...
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...
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>...
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.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([...
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...
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...
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...
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...
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=""...
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();...
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...
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?:...
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?...
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...
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...
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,...
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...
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...
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...
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
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,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...
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',...
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...
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...
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...
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:...
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...
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...
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...
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,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...
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,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...
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'...
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...
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...
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...
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...
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...
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...