first draft of Model#escape

This commit is contained in:
Jeremy Ashkenas
2010-11-29 12:58:47 -05:00
parent 9994d2bab8
commit 7ae0384120
2 changed files with 32 additions and 2 deletions

View File

@@ -116,6 +116,7 @@
attributes || (attributes = {});
if (this.defaults) attributes = _.extend({}, this.defaults, attributes);
this.attributes = {};
this._escapedAttributes = {};
this.cid = _.uniqueId('c');
this.set(attributes, {silent : true});
this._previousAttributes = _.clone(this.attributes);
@@ -147,6 +148,14 @@
return this.attributes[attr];
},
// Get the HTML-escaped value of an attribute.
escape : function(attr) {
var html;
if (html = this._escapedAttributes[attr]) return html;
var val = this.attributes[attr];
return this._escapedAttributes[attr] = escapeHTML(val == null ? '' : val);
},
// Set a hash of model attributes on the object, firing `"change"` unless you
// choose to silence it.
set : function(attrs, options) {
@@ -155,7 +164,7 @@
options || (options = {});
if (!attrs) return this;
if (attrs.attributes) attrs = attrs.attributes;
var now = this.attributes;
var now = this.attributes, escaped = this._escapedAttributes;
// Run validation.
if (!options.silent && this.validate && !this._performValidation(attrs, options)) return false;
@@ -168,6 +177,7 @@
var val = attrs[attr];
if (!_.isEqual(now[attr], val)) {
now[attr] = val;
delete escaped[attr];
if (!options.silent) {
this._changed = true;
this.trigger('change:' + attr, this, val);
@@ -193,6 +203,7 @@
// Remove the attribute.
delete this.attributes[attr];
delete this._escapedAttributes[attr];
if (!options.silent) {
this._changed = true;
this.trigger('change:' + attr, this);
@@ -213,6 +224,7 @@
if (!options.silent && this.validate && !this._performValidation(validObj, options)) return false;
this.attributes = {};
this._escapedAttributes = {};
if (!options.silent) {
this._changed = true;
for (attr in old) {
@@ -981,4 +993,12 @@
return _.isFunction(object.url) ? object.url() : object.url;
};
// Helper function to escape a string for HTML rendering.
var escapeHTML = function(string) {
return string.replace(/&(?!\w+;)/g, '&')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;');
};
})();

View File

@@ -94,6 +94,16 @@ $(document).ready(function() {
equals(doc.get('author'), 'Bill Shakespeare');
});
test("Model: escape", function() {
equals(doc.escape('title'), 'The Tempest');
doc.set({audience: 'Bill & Bob'});
equals(doc.escape('audience'), 'Bill &amp; Bob');
doc.set({audience: 'Tim > Joan'});
equals(doc.escape('audience'), 'Tim &gt; Joan');
doc.unset('audience');
equals(doc.escape('audience'), '');
});
test("Model: set and unset", function() {
attrs = { 'foo': 1, 'bar': 2, 'baz': 3};
a = new Backbone.Model(attrs);
@@ -151,7 +161,7 @@ $(document).ready(function() {
model.change();
equals(model.get('name'), 'Rob');
});
test("Model: save within change event", function () {
var model = new Backbone.Model({firstName : "Taylor", lastName: "Swift"});
model.bind('change', function () {