Permalink
Browse files

Improved the config page

  • Loading branch information...
1 parent 1f3d080 commit 554f1d459061f9a7c42d8be947903e66dadfe9fe @searls searls committed Apr 8, 2012
View
@@ -1,3 +1,4 @@
.bundle
.jhw-cache
-.DS_Store
+.DS_Store
+public/assets/*.gz
View
@@ -13,7 +13,7 @@ gem "eco"
gem 'rake'
group :development, :test do
- gem 'jasmine-headless-webkit', :git => "git://github.com/johnbintz/jasmine-headless-webkit.git"
+ gem 'jasmine-headless-webkit'#, :git => "git://github.com/johnbintz/jasmine-headless-webkit.git"
gem 'cucumber'
gem 'rspec'
View
@@ -1,15 +1,3 @@
-GIT
- remote: git://github.com/johnbintz/jasmine-headless-webkit.git
- revision: 724541a2cb3ee7d730dac4eb186b451a510bf11e
- specs:
- jasmine-headless-webkit (0.9.0.rc1)
- coffee-script
- jasmine-core
- multi_json
- rainbow
- sprockets
- sprockets-vendor_gems
-
GEM
remote: http://rubygems.org/
specs:
@@ -58,6 +46,12 @@ GEM
sprockets (~> 2.0)
hike (1.2.1)
jasmine-core (1.1.0)
+ jasmine-headless-webkit (0.8.4)
+ coffee-script
+ jasmine-core (~> 1.1)
+ multi_json
+ rainbow
+ sprockets (~> 2)
json (1.6.5)
mime-types (1.17.2)
multi_json (1.0.4)
@@ -96,7 +90,6 @@ GEM
multi_json (~> 1.0)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
- sprockets-vendor_gems (0.1.1)
term-ansicolor (1.0.7)
thor (0.14.6)
tilt (1.3.3)
@@ -121,7 +114,7 @@ DEPENDENCIES
guard
guard-jasmine-headless-webkit
guard-sprockets2
- jasmine-headless-webkit!
+ jasmine-headless-webkit
rake
rb-fsevent
rspec
@@ -1 +1,13 @@
class app.collections.DictionaryEntries extends Backbone.Collection
+ removeEmpties: ->
+ @remove(@empties())
+
+ ensureAnAvailableEntry: ->
+ if _(@empties()).isEmpty()
+ @add({})
+
+ #private
+
+ empties: ->
+ @filter (entry) ->
+ _(entry.get('original')).isEmpty() && _(entry.get('replacement')).isEmpty()
@@ -9,3 +9,7 @@ class app.models.Configuration extends Backbone.RelationalModel
defaults: ->
dictionary: new app.models.Dictionary
+
+ save: ->
+ @get('dictionary').removeEmptyEntries()
+ super
@@ -7,3 +7,7 @@ class app.models.Dictionary extends Backbone.RelationalModel
collectionType: 'app.collections.DictionaryEntries'
}
]
+
+ removeEmptyEntries: ->
+ @get('entries').removeEmpties()
+
@@ -8,7 +8,7 @@ class app.views.Configuration extends app.helpers.SuperView
@bind('rendered', @renderDictionary)
renderDictionary: ->
- @$('.fields').append(new app.views.Dictionary(model: @model.get('dictionary')).render().el)
+ @$('.js-fields').append(new app.views.Dictionary(model: @model.get('dictionary')).render().el)
save: (e) ->
e.preventDefault()
@@ -4,7 +4,8 @@ class app.views.DictionaryEntry extends app.helpers.SuperView
"click .js-remove": "handleRemove"
"change :input": "handleChange"
- handleRemove: ->
+ handleRemove: (e) ->
+ e.preventDefault()
@model.collection.remove(@model)
@remove()
@@ -1,20 +1,20 @@
class app.views.Dictionary extends app.helpers.SuperView
template: "templates/dictionary"
events:
- "click .js-add": "handleAdd"
+ "change :input": "ensureAvailableEntry"
initialize: ->
@bind('rendered', @renderItems)
+ @model.get('entries').bind('add', @renderItem)
+ @ensureAvailableEntry()
- handleAdd: (e) ->
- e.preventDefault()
- @model.get('entries').add({})
- @renderItem(@model.get('entries').last())
+ ensureAvailableEntry: ->
+ @model.get('entries').ensureAnAvailableEntry()
renderItems: ->
@model.get('entries').each (item) =>
@renderItem(item)
- renderItem: (item) ->
+ renderItem: (item) =>
entryView = new app.views.DictionaryEntry(model: item)
- @$el.append(entryView.render().el)
+ @$('.js-entries').append(entryView.render().el)
@@ -1,8 +1,10 @@
-<form class="form-inline">
- <div class="fields">
+<form class="form-inline span8">
+ <fieldset>
+ <legend>your words</legend>
+ <div class="control-group js-fields"></div>
+ </fieldset>
+ <div class="well">
+ <button class="btn js-save">Save</button>
+ <button class="btn btn-danger js-reset">Delete All</button>
</div>
- <div class="well">
- <button class="js-save">Save</button>
- <button class="js-reset">Delete</button>
- </div>
</form>
@@ -1,4 +1,5 @@
-<div>
- <input type="text" class="input" placeholder="replace this word" name="original" value="<%= @model.original %>" />
- <input type="text" class="input" placeholder="with this word" name="replacement" value="<%= @model.replacement %>" />
-</div>
+<p class="offset1 span6">
+ <input type="text" class="input-medium" placeholder="replace this word" name="original" value="<%= @model.original %>" />
+ <input type="text" class="input-medium" placeholder="with this word" name="replacement" value="<%= @model.replacement %>" />
+ <i class="js-remove icon-minus pointer"></i>
+</p>
@@ -1 +1 @@
-<button class="js-add">Add</button>
+<div class="js-entries"></div>
@@ -0,0 +1,3 @@
+.pointer {
+ cursor: pointer;
+}
@@ -1,3 +1,5 @@
+.pointer {
+ cursor: pointer; }
/*!
* Bootstrap v2.0.2
*
Binary file not shown.
@@ -2119,6 +2119,11 @@ Backbone.sync = function(method, model, options, error) {
};
};
+ Configuration.prototype.save = function() {
+ this.get('dictionary').removeEmptyEntries();
+ return Configuration.__super__.save.apply(this, arguments);
+ };
+
return Configuration;
})(Backbone.RelationalModel);
@@ -2162,6 +2167,10 @@ Backbone.sync = function(method, model, options, error) {
}
];
+ Dictionary.prototype.removeEmptyEntries = function() {
+ return this.get('entries').removeEmpties();
+ };
+
return Dictionary;
})(Backbone.RelationalModel);
@@ -2200,6 +2209,20 @@ Backbone.sync = function(method, model, options, error) {
DictionaryEntries.__super__.constructor.apply(this, arguments);
}
+ DictionaryEntries.prototype.removeEmpties = function() {
+ return this.remove(this.empties());
+ };
+
+ DictionaryEntries.prototype.ensureAnAvailableEntry = function() {
+ if (_(this.empties()).isEmpty()) return this.add({});
+ };
+
+ DictionaryEntries.prototype.empties = function() {
+ return this.filter(function(entry) {
+ return _(entry.get('original')).isEmpty() && _(entry.get('replacement')).isEmpty();
+ });
+ };
+
return DictionaryEntries;
})(Backbone.Collection);
@@ -2229,7 +2252,7 @@ Backbone.sync = function(method, model, options, error) {
};
Configuration.prototype.renderDictionary = function() {
- return this.$('.fields').append(new app.views.Dictionary({
+ return this.$('.js-fields').append(new app.views.Dictionary({
model: this.model.get('dictionary')
}).render().el);
};
@@ -2267,7 +2290,8 @@ Backbone.sync = function(method, model, options, error) {
"change :input": "handleChange"
};
- DictionaryEntry.prototype.handleRemove = function() {
+ DictionaryEntry.prototype.handleRemove = function(e) {
+ e.preventDefault();
this.model.collection.remove(this.model);
return this.remove();
};
@@ -2284,31 +2308,33 @@ Backbone.sync = function(method, model, options, error) {
}).call(this);
(function() {
- var __hasProp = Object.prototype.hasOwnProperty,
+ var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
+ __hasProp = Object.prototype.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
app.views.Dictionary = (function(_super) {
__extends(Dictionary, _super);
function Dictionary() {
+ this.renderItem = __bind(this.renderItem, this);
Dictionary.__super__.constructor.apply(this, arguments);
}
Dictionary.prototype.template = "templates/dictionary";
Dictionary.prototype.events = {
- "click .js-add": "handleAdd"
+ "change :input": "ensureAvailableEntry"
};
Dictionary.prototype.initialize = function() {
- return this.bind('rendered', this.renderItems);
+ this.bind('rendered', this.renderItems);
+ this.model.get('entries').bind('add', this.renderItem);
+ return this.ensureAvailableEntry();
};
- Dictionary.prototype.handleAdd = function(e) {
- e.preventDefault();
- this.model.get('entries').add({});
- return this.renderItem(this.model.get('entries').last());
+ Dictionary.prototype.ensureAvailableEntry = function() {
+ return this.model.get('entries').ensureAnAvailableEntry();
};
Dictionary.prototype.renderItems = function() {
@@ -2323,7 +2349,7 @@ Backbone.sync = function(method, model, options, error) {
entryView = new app.views.DictionaryEntry({
model: item
});
- return this.$el.append(entryView.render().el);
+ return this.$('.js-entries').append(entryView.render().el);
};
return Dictionary;
@@ -2517,7 +2543,7 @@ Backbone.sync = function(method, model, options, error) {
(function() {
(function() {
- __out.push('<form class="form-inline">\n <div class="fields">\n </div>\n\t<div class="well">\n\t\t<button class="js-save">Save</button>\n\t\t<button class="js-reset">Delete</button>\n\t</div>\n</form>\n');
+ __out.push('<form class="form-inline span8">\n <fieldset>\n <legend>your words</legend>\n <div class="control-group js-fields"></div>\n </fieldset>\n <div class="well">\n <button class="btn js-save">Save</button>\n <button class="btn btn-danger js-reset">Delete All</button>\n </div>\n</form>\n');
}).call(this);
@@ -2568,15 +2594,15 @@ Backbone.sync = function(method, model, options, error) {
(function() {
(function() {
- __out.push('<div>\n <input type="text" class="input" placeholder="replace this word" name="original" value="');
+ __out.push('<p class="offset1 span6">\n <input type="text" class="input-medium" placeholder="replace this word" name="original" value="');
__out.push(__sanitize(this.model.original));
- __out.push('" />\n <input type="text" class="input" placeholder="with this word" name="replacement" value="');
+ __out.push('" />\n <input type="text" class="input-medium" placeholder="with this word" name="replacement" value="');
__out.push(__sanitize(this.model.replacement));
- __out.push('" />\n</div>\n');
+ __out.push('" />\n <i class="js-remove icon-minus pointer"></i>\n</p>\n');
}).call(this);
@@ -2627,7 +2653,7 @@ Backbone.sync = function(method, model, options, error) {
(function() {
(function() {
- __out.push('<button class="js-add">Add</button>\n');
+ __out.push('<div class="js-entries"></div>\n');
}).call(this);
Binary file not shown.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -6,7 +6,7 @@
</head>
<body class="js-options-page">
- <div class="root">
+ <div class="container root">
</div>
</body>
</html>
@@ -0,0 +1,44 @@
+describe "app.collections.DictionaryEntries", ->
+ Given -> @subject = new app.collections.DictionaryEntries
+
+ describe "#removeEmpties", ->
+ context "no items", ->
+ When -> @subject.removeEmpties()
+ Then -> @subject.size() == 0
+
+ context "1 non-empty item", ->
+ Given -> @subject.add({original: "foo"})
+ When -> @subject.removeEmpties()
+ Then -> @subject.size() == 1
+
+ context "1 empty item", ->
+ Given -> @subject.add({})
+ When -> @subject.removeEmpties()
+ Then -> @subject.size() == 0
+
+ context "1 empty, 1 non-empty item", ->
+ Given -> @subject.add([{original: "foo"},{}])
+ When -> @subject.removeEmpties()
+ Then -> @subject.size() == 1
+
+ describe "#ensureAnAvailableEntry", ->
+ context "empty collection", ->
+ When -> @subject.ensureAnAvailableEntry()
+ Then -> @subject.size() == 1
+
+ context "one full item", ->
+ Given -> @subject.add({original: "a", replacement: "b"})
+ When -> @subject.ensureAnAvailableEntry()
+ Then -> @subject.size() == 2
+
+ context "one half-full item", ->
+ Given -> @subject.add({original: "a"})
+ When -> @subject.ensureAnAvailableEntry()
+ Then -> @subject.size() == 2
+
+ context "one empty item", ->
+ Given -> @subject.add({})
+ When -> @subject.ensureAnAvailableEntry()
+ Then -> @subject.size() == 1
+
+
@@ -20,7 +20,7 @@ describe "app.configuration.FetchesConfig", ->
describe "contracts with dependencies", ->
describe "saving nested models with backbone-localstorage & backbone-relational", ->
Given -> @config = new app.configuration.FetchesConfig().fetch()
- Given -> @config.get('dictionary').get('entries').add({foo: "bar"})
+ Given -> @config.get('dictionary').get('entries').add({original: "bad", replacement: "good"})
When -> @config.save()
- Then -> new app.configuration.FetchesConfig().fetch().get('dictionary').get('entries').first().get('foo') == "bar"
+ Then -> new app.configuration.FetchesConfig().fetch().get('dictionary').get('entries').first().get('original') == "bad"
Oops, something went wrong.

0 comments on commit 554f1d4

Please sign in to comment.