Created
June 14, 2013 16:03
-
-
Save tim-evans/5783095 to your computer and use it in GitHub Desktop.
Autosave pattern for Ember with Ember Data
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function () { | |
// Implement debounce until backburner implements a proper debounce | |
var debouncees = [], | |
pop = Array.prototype.pop; | |
var debounce = function (target, method /*, args, wait */) { | |
var self = Ember.run.backburner, | |
args = arguments, | |
wait = pop.call(args), | |
debouncee, | |
index = -1; | |
// Remove debouncee | |
for (var i = 0, l = debouncees.length; i < l; i++) { | |
debouncee = debouncees[i]; | |
if (debouncee[0] === target && debouncee[1] === method) { | |
index = i; | |
break; | |
} | |
} | |
if (index > -1) { | |
debouncees.splice(index, 1); | |
clearTimeout(debouncee[2]); | |
} | |
var timer = window.setTimeout(function () { | |
self.run.apply(self, args); | |
}, wait); | |
debouncees.push([target, method, timer]); | |
}; | |
var save = function () { | |
if (!this.get('isSaving') && | |
!this.get('isReloading')) { | |
this.get('content').save(); | |
} else { | |
this.get('content').one('isLoaded', this, save); | |
} | |
}; | |
Ember.Autosave = Ember.Mixin.create(/** @scope Ember.Autosave.prototype */{ | |
/** | |
A list of properties that shouldn't be automatically saved. | |
@property manuallySavedProperties | |
@type String[] | |
@default null | |
*/ | |
manuallySavedProperties: null, | |
/** | |
The number of seconds to wait for debouncing | |
@property wait | |
@type Number | |
@default 2000 | |
*/ | |
wait: 2000, | |
/** | |
Override setUnknownProperty on Em.ObjectControllers so | |
we can coalesce the property changes and bulk set them | |
when the record is ready to accept changes. | |
@method setUnknownProperty | |
@param key {String} The property being set | |
@param value {*} The new value of the property | |
*/ | |
setUnknownProperty: function (key, value) { | |
var willBeManuallySaved = Em.A(this.get('manuallySavedProperties')).indexOf(key); | |
if (willBeManuallySaved !== -1) { | |
return this._super(key, value); | |
} | |
// We can't set the value yet, since | |
// the model is in flight. | |
if (this.get('isSaving') || | |
this.get('isReloading')) { | |
if (this.__coalescedProperties__ == null) { | |
this.__coalescedProperties__ = {}; | |
} | |
this.__coalescedProperties__[key] = value; | |
this.get('content').one('isLoaded', this, this.setUnknownProperty); | |
// The model is loaded; | |
// Set the new property and any coalesced properties | |
// set on this object | |
} else { | |
var content = this.get('content'); | |
Ember.assert("Cannot delegate set('%@', %@) to the 'content' property of object proxy %@: its 'content' is undefined.".fmt(key, value, this), content); | |
if (this.__coalescedProperties__) { | |
this.__coalescedProperties__[key] = value; | |
content.setProperties(key, value); | |
this.__coalescedProperties__ = null; | |
} else { | |
content.set(key, value); | |
} | |
this.save(); | |
} | |
return value; | |
}, | |
/** | |
Save the underlying record, debouncing | |
with the interval defined in `wait`. | |
@method save | |
*/ | |
save: function () { | |
// Try to save at least a second after a property being set | |
debounce(this, save, this.get('wait')); | |
} | |
}); | |
}()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
nice +1