Code Monkey home page Code Monkey logo

backbone.trackit's Introduction

Backbone.trackit

A small, opinionated Backbone.js plugin that manages model changes that accrue between saves, giving a Model the ability to undo previous changes, trigger events when there are unsaved changes, and opt in to before unload route handling.

Introduction

At the heart of every JavaScript application is the model, and no frontend framework matches the extensible, well-featured model that Backbone provides. To stay unopinionated, Backbone's model only has a basic set of functionality for managing changes, where the current and previous change values are preserved until the next change. For example:

var model = new Backbone.Model({id:1, artist:'John Cage', 'work':'4\'33"'});

model.set('work', 'Amores');
console.log(model.changedAttributes());  // >> Object {work: "Amores"}
console.log(model.previous('work'));  // >> 4'33"

model.set('advisor', 'Arnold Schoenberg');
console.log(model.changedAttributes());  // >> Object {advisor: "Arnold Schoenberg"}

Backbone's change management handles well for most models, but the ability to manage multiple changes between successful save events is a common pattern, and that's what Backbone.trackit aims to provide. For example, the following demonstrates how to use the api to startTracking unsaved changes, get the accrued unsavedAttributes, and how a call to save the model resets the internal tracking:

var model = new Backbone.Model({id:1, artist:'Samuel Beckett', 'work':'Molloy'});
model.startTracking();

model.set('work', 'Malone Dies');
console.log(model.unsavedAttributes());  // >> Object {work: "Malone Dies"}

model.set('period', 'Modernism');
console.log(model.unsavedAttributes());  // >> Object {work: "Malone Dies", period: "Modernism"}

model.save({}, {
    success: function() {
        console.log(model.unsavedAttributes());  // >> false
    }
});

In addition, the library adds functionality to resetAttributes to their original state since the last save, triggers an event when the state of unsavedChanges is updated, and has options to opt into prompting to confirm before routing to a new context.

Download

0.1.0 min - 2.6k

0.1.0 gz - 1k

edge

API

startTracking - model.startTracking()

Start tracking attribute changes between saves.

restartTracking - model.restartTracking()

Restart the current internal tracking of attribute changes and state since tracking was started.

stopTracking - model.stopTracking()

Stop tracking attribute changes between saves.

If an unsaved configuration was defined, it is important to call this when a model goes unused/should be destroyed (see the unsaved configuration for more information).

unsavedAttributes - model.unsavedAttributes([attributes])

Symmetric to Backbone's model.changedAttributes(), except that this returns a hash of the model's attributes that have changed since the last save, or false if there are none. Like changedAttributes, an external attributes hash can be passed in, returning the attributes in that hash which differ from the model.

resetAttributes - model.resetAttributes()

Restores this model's attributes to their original values since the last call to startTracking, restartTracking, resetAttributes, or save.

unsavedChanges (event)

Triggered after any changes have been made to the state of unsaved attributes. Passed into the event callback is the boolean value for whether or not the model has unsaved changes, and a cloned hash of the unsaved changes. This event is only triggered after unsaved attribute tracking is started (startTracking) and will stop triggering after tracking is turned off (stopTracking).

model.on('unsavedChanges', function(hasChanges, unsavedAttrs, model) {
    ...
});

trackit_silent (option)

When passed as an option and set to true, trackit will not track changes when setting the model.

model.fetch({ ..., trackit_silent:true});
model.set({artist:'John Cage'}, {trackit_silent:true});
console.log(model.unsavedAttributes()); // false

unsaved (configuration) - model.unsaved

The unsaved configuration is optional, and is used to opt into and configure unload handling when route/browser navigation changes and the model has unsaved changes. Unload handling warns the user with a dialog prompt, where the user can choose to continue or stop navigation. Unfortunately, both handlers (browser and in-app; unloadWindowPrompt and unloadRouterPrompt) are needed becuase they are triggered in different scenarios.

Note: Any model that defines an unsaved configuration and uses startTracking should call stopTracking (when done and if there are unsaved changes) to remove any internal references used by the library so that it can be garbage collected.

prompt - default: "You have unsaved changes!"

When navigation is blocked because of unsaved changes, the given prompt message will be displayed to the user in a confirmation dialog. Note, Firefox (only) will not display customized prompt messages; instead, Firefox will prompt the user with a generic confirmation dialog.

unloadWindowPrompt - default: false

When true prompts the user on browser navigation (back, forward, refresh buttons) when there are unsaved changes. This property can be defined with a function callback that should return true or false depending on whether or not navigation should be blocked. Like most Backbone configuration, the callback may be either the name of a method on the model, or a direct function body.

unloadRouterPrompt - default: false

When true prompts the user on in-app navigation (router.navigate('/path')) when there are unsaved changes. This property can be defined with a function callback that should return true or false depending on whether or not navigation should be blocked. Like most Backbone configuration, the callback may be either the name of a method on the model, or a direct function body.

var model = Backbone.Model.extend({
    unsaved: {
        prompt: 'Changes exist!',
        unloadWindowPrompt: true,
        unloadRouterPrompt: 'unloadRouter'
    },
    
    unloadRouter: function(fragment, options) {
        if (fragment == '/article/edit-body') return false;
        return true;
    }
});

FAQ

  • Is this an undo/redo plugin?
    No. If you are looking for an undo/redo plugin, check out backbone.memento

  • Why are there two unload handlers (unloadWindowPrompt, unloadRouterPrompt)?
    Since navigation can be triggered by the browser (forward, back, refresh buttons) or through pushstate/hashchange in the app (by Backbone), a handler needs to be created for both methods.

  • Why doesn't Firefox display my unload prompt?
    You can find out their reasoning and leave a message for Mozilla here.

Change log

Master

  • Added trackit_silent option that can be passed in options hashes so that attriubutes can be set into a model without being tracked.

  • Added ability for new models (without ids) to be notified of unsaved changes after a successful call to model.save().

  • Added model as third parameter to unsavedChanges event callback.

  • Added support for the patch method on model#save.

0.1.0

  • Initial version; extracted from an internal project (Blackbeard) that powers our News Services at The New York Times.

License

MIT

backbone.trackit's People

Contributors

delambo avatar groe avatar lalitkapoor avatar sdemjanenko avatar splars avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

backbone.trackit's Issues

Backbone Uncaught reference error

Getting Uncaught Reference error: Backbone is not defined when i compile with r.js optimizer using grunt. But when i change the anonymous function to a AMD function i.e.,

define(['backbone'], function(Backbone) { \\Contents of function }); the code is working properly.

Create a tag for first release?

For those of us who use bower it would be awesome if you could create a tag for the initial release so we don't have to be on master.

model.unsavedAttributes() question

Can model.unsavedAttributes() be used for PATCH operations? I am trying to minimize the conflicts between multiple users saving the same model, replacing an entire model on the server when only 1 attribute has changed. Since I am also using the wonderful stickit, my client side model changes a LOT, and is large. This increases the likelyhood of model saves overwriting other parts of the model that have changes by an order of magnitude. I thought that the patch:true would be my saving grace, but stickit gurantees that the changedAttributes hash only has one item in it.

So, can I do:

model.save(model.unsavedAttributes(),{patch:true});

Notwithstanding any server side changes I have to make to accommodate this.

0.2.0 release prep

It would be nice if someone prepped a pull request similar to #23 for a 0.2.0 release.

Add ability to work with Backbone-relational

Hi! backbone.trackit is really good then working with single model, but then you try to work with nested models (and especially then you working with nested collections of models) it soon become very hard as you have to track changes in each model and track all their relations by hand.

It will be really great to have ability to do so automatically.

For example:

1.I have model Book.
2. Book have fields like title, publisher and others.
3. also book can have one or more Authors.
4. All book meta, including Authors are edited on one page and I'd like to save and reset it automatically.
5. Now to do so, I need to use startTrcking() on each model, remember id''s of author's models and reset all of that than I need to reset model.

I understand, that it not a part of the default Backbone functional, but it will be great to be able to do it somehow.

More maintainers

I love using trackit but have run into some issues and it appears others have as well.
There are a bunch of forks, issues, and PRs.

Need some help?

changes to model not being tracked

I am using Backbone, Marionette, stickit, and just installed trackit to give me PATCH support on model.save. When my view loads, I do:

return Backbone.Marionette.ItemView.extend({
         initialize: function(){
            this.model.startTracking();
         },

and if I set a breakpoint inside startTracking, It gets hit at the proper time properly. Just before calling model.save, I do:

 var changes = this.model.unsavedAttributes();
 this.model.save(changes, {patch:true, wait:true})

but changes is always false, and a full copy of my model is sent with the save.

I set a break point in the Backbone.Model.prototype.set wrapper, and it never gets hit.

Could this be due to a conflict with stickit? Marionette? For some reason my model is getting updated just fine by stickit, but the set function in trackit is never called, leading me to believe something else is overloading Model.set.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.