appetizer-ui 0.7.1 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/appetizer-ui.gemspec +1 -1
- data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/appetizerExtensions.spec.js +54 -0
- data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/checkboxConventionBindings.spec.js +110 -0
- data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/configurableBindingAttributes.spec.js +117 -0
- data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/configureAllBindingAttributes.spec.js +139 -0
- data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/customConvention.spec.js +53 -0
- data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/dataBindConvention.spec.js +151 -0
- data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/dataBindMultiple.spec.js +36 -0
- data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/dataBindSubstitutions.spec.js +137 -0
- data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/globalConfiguraAllBindingAttributes.spec.js +124 -0
- data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/globalConfigurableBindingAttributes.spec.js +36 -0
- data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/helpers/SpecHelper.js +4 -0
- data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/helpers/sample.backbone.app.js +159 -0
- data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/html5inputConventionBinding.spec.js +142 -0
- data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/modelUnbinding.spec.js +73 -0
- data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/noConflict.spec.js +36 -0
- data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/radioButtonConventionBinding.spec.js +41 -0
- data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/selectboxConventionBindings.spec.js +60 -0
- data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/textareaConventionBinding.spec.js +29 -0
- data/lib/appetizer/ui/jasmine/js/backbone.modelbinding/textboxConventionBinding.spec.js +66 -0
- data/lib/appetizer/ui/jasmine/js/jasmine-jquery-matchers.js +1 -1
- data/lib/appetizer/ui/jasmine/js/spec-runner.coffee +1 -0
- data/lib/appetizer/ui/vendor/js/backbone.modelbinding.js +68 -10
- metadata +45 -26
data/.gitignore
CHANGED
data/appetizer-ui.gemspec
CHANGED
@@ -0,0 +1,54 @@
|
|
1
|
+
describe("appetizer-ui extensions", function(){
|
2
|
+
beforeEach(function(){
|
3
|
+
this.model = new AModel({
|
4
|
+
villain: "mrMonster",
|
5
|
+
niceDude: "Dr No",
|
6
|
+
pet: { smelly: "dog" }
|
7
|
+
});
|
8
|
+
this.model.villain = function () { return "Le Grand Mechant Loup" };
|
9
|
+
this.model.niceDude = "James Bond";
|
10
|
+
this.model.country = new AModel({
|
11
|
+
withFood: { hasWine: "France" }
|
12
|
+
});
|
13
|
+
this.view = new AppetizerView({model: this.model});
|
14
|
+
this.view.render();
|
15
|
+
});
|
16
|
+
|
17
|
+
it("grabs attribute from methods, if existing", function(){
|
18
|
+
var el = $(this.view.el).find("#villain");
|
19
|
+
expect(el.text()).toBe("Le Grand Mechant Loup");
|
20
|
+
});
|
21
|
+
|
22
|
+
it("grabs attribute from values, if existing", function(){
|
23
|
+
var el = $(this.view.el).find("#mrNice");
|
24
|
+
expect(el.text()).toBe("James Bond");
|
25
|
+
});
|
26
|
+
|
27
|
+
it("grabs attribute from object attributes.", function(){
|
28
|
+
var el = $(this.view.el).find("#pet");
|
29
|
+
expect(el.text()).toBe("dog");
|
30
|
+
});
|
31
|
+
|
32
|
+
it("sets attribute from object attributes.", function(){
|
33
|
+
var el = this.view.$("#cat");
|
34
|
+
el.val("cat");
|
35
|
+
el.trigger("change");
|
36
|
+
|
37
|
+
expect(this.model.get("pet").smelly).toBe("dog");
|
38
|
+
expect(this.model.get("pet").fluffy).toBe("cat");
|
39
|
+
});
|
40
|
+
|
41
|
+
it("grabs attribute from associated models.", function(){
|
42
|
+
var el = $(this.view.el).find("#country");
|
43
|
+
expect(el.text()).toBe("France");
|
44
|
+
});
|
45
|
+
|
46
|
+
it("sets attribute from associated objects.", function(){
|
47
|
+
var el = this.view.$("#usa");
|
48
|
+
el.val("USA");
|
49
|
+
el.trigger("change");
|
50
|
+
|
51
|
+
expect(this.model.country.get("withFood").hasWine).toBe("France");
|
52
|
+
expect(this.model.country.get("withFood").hasBurgers).toBe("USA");
|
53
|
+
});
|
54
|
+
});
|
@@ -0,0 +1,110 @@
|
|
1
|
+
describe("checkbox convention bindings", function(){
|
2
|
+
|
3
|
+
describe("checkbox element binding", function(){
|
4
|
+
beforeEach(function(){
|
5
|
+
this.model = new AModel({
|
6
|
+
drivers_license: true,
|
7
|
+
motorcycle_license: false,
|
8
|
+
});
|
9
|
+
this.view = new AView({model: this.model});
|
10
|
+
this.view.render();
|
11
|
+
});
|
12
|
+
|
13
|
+
it("bind view changes to the model's field", function(){
|
14
|
+
var el = this.view.$("#drivers_license");
|
15
|
+
el.removeAttr("checked");
|
16
|
+
el.trigger('change');
|
17
|
+
expect(this.model.get('drivers_license')).toBeFalsy();
|
18
|
+
});
|
19
|
+
|
20
|
+
it("bind model field changes to the form input", function(){
|
21
|
+
var el = this.view.$("#drivers_license");
|
22
|
+
|
23
|
+
// uncheck it
|
24
|
+
this.model.set({drivers_license: false});
|
25
|
+
var selected = el.attr("checked");
|
26
|
+
expect(selected).toBeFalsy();
|
27
|
+
|
28
|
+
// then check it
|
29
|
+
this.model.set({drivers_license: true});
|
30
|
+
var selected = el.attr("checked");
|
31
|
+
expect(selected).toBeTruthy();
|
32
|
+
});
|
33
|
+
|
34
|
+
it("checks the box for a truthy value, on render", function(){
|
35
|
+
var el = this.view.$("#drivers_license");
|
36
|
+
var selected = el.attr("checked");
|
37
|
+
|
38
|
+
expect(selected).toBeTruthy();
|
39
|
+
});
|
40
|
+
|
41
|
+
it("unchecks the box for a falsy value, on render", function(){
|
42
|
+
var el = this.view.$("#motorcycle_license");
|
43
|
+
var selected = el.attr("checked");
|
44
|
+
|
45
|
+
expect(selected).toBeFalsy();
|
46
|
+
});
|
47
|
+
});
|
48
|
+
|
49
|
+
describe("when binding a 1 to a checkbox", function(){
|
50
|
+
beforeEach(function(){
|
51
|
+
this.model = new AModel({
|
52
|
+
binary_checkbox: 1
|
53
|
+
});
|
54
|
+
this.view = new AView({model: this.model});
|
55
|
+
this.view.render();
|
56
|
+
this.el = this.view.$("#binary_checkbox");
|
57
|
+
});
|
58
|
+
|
59
|
+
it("checks the box for a 1 (one) value, on render", function(){
|
60
|
+
var selected = this.el.attr("checked");
|
61
|
+
expect(selected).toBeTruthy();
|
62
|
+
});
|
63
|
+
|
64
|
+
it("unchecks the box when the value is changed to a 0 (zero)", function(){
|
65
|
+
this.model.set({binary_checkbox: 0});
|
66
|
+
var selected = this.el.attr("checked");
|
67
|
+
expect(selected).toBeFalsy();
|
68
|
+
});
|
69
|
+
|
70
|
+
});
|
71
|
+
|
72
|
+
describe("when binding a 0 to a checkbox", function(){
|
73
|
+
beforeEach(function(){
|
74
|
+
this.model = new AModel({
|
75
|
+
binary_checkbox: 0
|
76
|
+
});
|
77
|
+
this.view = new AView({model: this.model});
|
78
|
+
this.view.render();
|
79
|
+
this.el = this.view.$("#binary_checkbox");
|
80
|
+
});
|
81
|
+
|
82
|
+
it("unchecks the box for a 0 (zero) value, on render", function(){
|
83
|
+
var selected = this.el.attr("checked");
|
84
|
+
expect(selected).toBeFalsy();
|
85
|
+
});
|
86
|
+
|
87
|
+
it("checks the box when the value is changed to a 1 (one)", function(){
|
88
|
+
this.model.set({binary_checkbox: 1});
|
89
|
+
var selected = this.el.attr("checked");
|
90
|
+
expect(selected).toBeTruthy();
|
91
|
+
});
|
92
|
+
});
|
93
|
+
|
94
|
+
describe("when there is no value in the model", function(){
|
95
|
+
beforeEach(function(){
|
96
|
+
this.model = new AModel();
|
97
|
+
this.view = new AView({model: this.model});
|
98
|
+
this.view.render();
|
99
|
+
});
|
100
|
+
|
101
|
+
it("bind an unchecked checkbox value to the model, on render", function(){
|
102
|
+
expect(this.model.get('drivers_license')).toBeFalsy();
|
103
|
+
});
|
104
|
+
|
105
|
+
it("bind a checked checkbox value to the model, on render", function(){
|
106
|
+
expect(this.model.get('motorcycle_license')).toBeTruthy();
|
107
|
+
});
|
108
|
+
});
|
109
|
+
|
110
|
+
});
|
@@ -0,0 +1,117 @@
|
|
1
|
+
describe("configurableBindingAttributes", function(){
|
2
|
+
beforeEach(function(){
|
3
|
+
this.model = new AModel({
|
4
|
+
super_power: "mega pooping",
|
5
|
+
education: "graduate",
|
6
|
+
graduated: "maybe",
|
7
|
+
drivers_license: true
|
8
|
+
});
|
9
|
+
|
10
|
+
this.view = new AnotherView({model: this.model});
|
11
|
+
this.view.render();
|
12
|
+
});
|
13
|
+
|
14
|
+
describe("text element binding using configurable attribute", function(){
|
15
|
+
it("bind view changes to the model's field, by configurable convention", function(){
|
16
|
+
var el = this.view.$(".super_power");
|
17
|
+
el.val("x ray vision");
|
18
|
+
el.trigger('change');
|
19
|
+
|
20
|
+
expect(this.model.get('super_power')).toEqual("x ray vision");
|
21
|
+
});
|
22
|
+
|
23
|
+
it("bind model field changes to the form input, by convention of id", function(){
|
24
|
+
this.model.set({super_power: "eating raw vegetables"});
|
25
|
+
var el = this.view.$(".super_power");
|
26
|
+
expect(el.val()).toEqual("eating raw vegetables");
|
27
|
+
});
|
28
|
+
|
29
|
+
it("binds the model's value to the form field on render", function(){
|
30
|
+
var el = this.view.$(".super_power");
|
31
|
+
expect(el.val()).toEqual("mega pooping");
|
32
|
+
});
|
33
|
+
});
|
34
|
+
|
35
|
+
describe("radio element binding using configurable attribute", function(){
|
36
|
+
it("bind view changes to the model's field, by configurable convention", function(){
|
37
|
+
var el = $(this.view.el).find("#graduated_no");
|
38
|
+
el.attr("checked", "checked");
|
39
|
+
el.trigger('change');
|
40
|
+
expect(this.model.get('graduated')).toEqual("no");
|
41
|
+
});
|
42
|
+
|
43
|
+
it("bind model field changes to the form input, by configurable convention", function(){
|
44
|
+
this.model.set({graduated: "yes"});
|
45
|
+
var el = this.view.$("#graduated_yes");
|
46
|
+
var selected = el.attr("checked");
|
47
|
+
|
48
|
+
expect(selected).toBeTruthy();
|
49
|
+
});
|
50
|
+
|
51
|
+
it("binds the model's value to the form field on render", function(){
|
52
|
+
var el = this.view.$("input[type=radio][class=graduated]:checked");
|
53
|
+
var selected = el.val();
|
54
|
+
|
55
|
+
expect(selected).toBe("maybe");
|
56
|
+
});
|
57
|
+
});
|
58
|
+
|
59
|
+
describe("select element binding using configurable attribute", function(){
|
60
|
+
it("bind view changes to the model's field, by configurable convention", function(){
|
61
|
+
var el = this.view.$(".education");
|
62
|
+
el.val("college");
|
63
|
+
el.trigger('change');
|
64
|
+
|
65
|
+
expect(this.model.get('education')).toEqual("college");
|
66
|
+
});
|
67
|
+
|
68
|
+
it("bind model field changes to the form input, by configurable convention", function(){
|
69
|
+
this.model.set({education: "high school"});
|
70
|
+
var el = this.view.$(".education");
|
71
|
+
expect(el.val()).toEqual("high school");
|
72
|
+
});
|
73
|
+
|
74
|
+
it("binds the model's value to the form field on render", function(){
|
75
|
+
var el = this.view.$(".education");
|
76
|
+
expect(el.val()).toEqual("graduate");
|
77
|
+
});
|
78
|
+
|
79
|
+
it("applies the text of the selection to the model", function(){
|
80
|
+
var el = this.view.$(".education");
|
81
|
+
el.val("grade_school");
|
82
|
+
el.trigger('change');
|
83
|
+
|
84
|
+
expect(this.model.get('education_text')).toEqual("i dun learned at grade skool");
|
85
|
+
});
|
86
|
+
});
|
87
|
+
|
88
|
+
describe("checkbox element binding using configurable attribute", function(){
|
89
|
+
it("bind view changes to the model's field", function(){
|
90
|
+
var el = this.view.$(".drivers_license");
|
91
|
+
el.removeAttr("checked");
|
92
|
+
el.trigger('change');
|
93
|
+
expect(this.model.get('drivers_license')).toBeFalsy();
|
94
|
+
});
|
95
|
+
|
96
|
+
it("bind model field changes to the form input", function(){
|
97
|
+
var el = this.view.$(".drivers_license");
|
98
|
+
|
99
|
+
// uncheck it
|
100
|
+
this.model.set({drivers_license: false});
|
101
|
+
var selected = el.attr("checked");
|
102
|
+
expect(selected).toBeFalsy();
|
103
|
+
|
104
|
+
// then check it
|
105
|
+
this.model.set({drivers_license: true});
|
106
|
+
var selected = el.attr("checked");
|
107
|
+
expect(selected).toBeTruthy();
|
108
|
+
});
|
109
|
+
|
110
|
+
it("binds the model's value to the form field on render", function(){
|
111
|
+
var el = this.view.$(".drivers_license");
|
112
|
+
var selected = el.attr("checked");
|
113
|
+
|
114
|
+
expect(selected).toBeTruthy();
|
115
|
+
});
|
116
|
+
});
|
117
|
+
});
|
@@ -0,0 +1,139 @@
|
|
1
|
+
describe("configure all binding attributes", function(){
|
2
|
+
beforeEach(function(){
|
3
|
+
this.model = new AModel({
|
4
|
+
name: "some dude",
|
5
|
+
bio: "not much",
|
6
|
+
education: "graduate",
|
7
|
+
graduated: "maybe",
|
8
|
+
drivers_license: true
|
9
|
+
});
|
10
|
+
|
11
|
+
this.view = new AllBindingAttributesView({model: this.model});
|
12
|
+
this.view.render();
|
13
|
+
});
|
14
|
+
|
15
|
+
describe("text element binding using configurable attribute", function(){
|
16
|
+
it("bind view changes to the model's field, by configurable convention", function(){
|
17
|
+
var el = this.view.$("#v_name");
|
18
|
+
el.val("that guy");
|
19
|
+
el.trigger('change');
|
20
|
+
|
21
|
+
expect(this.model.get('name')).toEqual("that guy");
|
22
|
+
});
|
23
|
+
|
24
|
+
it("bind model field changes to the form input, by convention of id", function(){
|
25
|
+
this.model.set({name: "joe bob"});
|
26
|
+
var el = this.view.$("#v_name");
|
27
|
+
expect(el.val()).toEqual("joe bob");
|
28
|
+
});
|
29
|
+
|
30
|
+
it("binds the model's value to the form field on render", function(){
|
31
|
+
var el = this.view.$("#v_name");
|
32
|
+
expect(el.val()).toEqual("some dude");
|
33
|
+
});
|
34
|
+
});
|
35
|
+
|
36
|
+
describe("textarea element binding using configurable attribute", function(){
|
37
|
+
it("bind view changes to the model's field, by configurable convention", function(){
|
38
|
+
var el = this.view.$("#v_bio");
|
39
|
+
el.val("biography");
|
40
|
+
el.trigger('change');
|
41
|
+
|
42
|
+
expect(this.model.get('bio')).toEqual("biography");
|
43
|
+
});
|
44
|
+
|
45
|
+
it("bind model field changes to the form input, by convention of id", function(){
|
46
|
+
this.model.set({bio: "biography, schmiography"});
|
47
|
+
var el = this.view.$("#v_bio");
|
48
|
+
expect(el.val()).toEqual("biography, schmiography");
|
49
|
+
});
|
50
|
+
|
51
|
+
it("binds the model's value to the form field on render", function(){
|
52
|
+
var el = this.view.$("#v_bio");
|
53
|
+
expect(el.val()).toEqual("not much");
|
54
|
+
});
|
55
|
+
});
|
56
|
+
|
57
|
+
describe("radio element binding using configurable attribute", function(){
|
58
|
+
it("bind view changes to the model's field, by configurable convention", function(){
|
59
|
+
var el = $(this.view.el).find("#graduated_no");
|
60
|
+
el.attr("checked", "checked");
|
61
|
+
el.trigger('change');
|
62
|
+
expect(this.model.get('graduated')).toEqual("no");
|
63
|
+
});
|
64
|
+
|
65
|
+
it("bind model field changes to the form input, by configurable convention", function(){
|
66
|
+
this.model.set({graduated: "yes"});
|
67
|
+
var el = this.view.$("#graduated_yes");
|
68
|
+
var selected = el.attr("checked");
|
69
|
+
|
70
|
+
expect(selected).toBeTruthy();
|
71
|
+
});
|
72
|
+
|
73
|
+
it("binds the model's value to the form field on render", function(){
|
74
|
+
var el = this.view.$("input[type=radio][class=graduated]:checked");
|
75
|
+
var selected = el.val();
|
76
|
+
|
77
|
+
expect(selected).toBe("maybe");
|
78
|
+
});
|
79
|
+
});
|
80
|
+
|
81
|
+
describe("select element binding using configurable attribute", function(){
|
82
|
+
it("bind view changes to the model's field, by configurable convention", function(){
|
83
|
+
var el = this.view.$(".education");
|
84
|
+
el.val("college");
|
85
|
+
el.trigger('change');
|
86
|
+
|
87
|
+
expect(this.model.get('education')).toEqual("college");
|
88
|
+
});
|
89
|
+
|
90
|
+
it("bind model field changes to the form input, by configurable convention", function(){
|
91
|
+
this.model.set({education: "high school"});
|
92
|
+
var el = this.view.$(".education");
|
93
|
+
expect(el.val()).toEqual("high school");
|
94
|
+
});
|
95
|
+
|
96
|
+
it("binds the model's value to the form field on render", function(){
|
97
|
+
var el = this.view.$(".education");
|
98
|
+
expect(el.val()).toEqual("graduate");
|
99
|
+
});
|
100
|
+
|
101
|
+
it("applies the text of the selection to the model", function(){
|
102
|
+
var el = this.view.$(".education");
|
103
|
+
el.val("grade_school");
|
104
|
+
el.trigger('change');
|
105
|
+
|
106
|
+
expect(this.model.get('education_text')).toEqual("i dun learned at grade skool");
|
107
|
+
});
|
108
|
+
});
|
109
|
+
|
110
|
+
describe("checkbox element binding using configurable attribute", function(){
|
111
|
+
it("bind view changes to the model's field", function(){
|
112
|
+
var el = this.view.$(".drivers_license");
|
113
|
+
el.removeAttr("checked");
|
114
|
+
el.trigger('change');
|
115
|
+
expect(this.model.get('drivers_license')).toBeFalsy();
|
116
|
+
});
|
117
|
+
|
118
|
+
it("bind model field changes to the form input", function(){
|
119
|
+
var el = this.view.$(".drivers_license");
|
120
|
+
|
121
|
+
// uncheck it
|
122
|
+
this.model.set({drivers_license: false});
|
123
|
+
var selected = el.attr("checked");
|
124
|
+
expect(selected).toBeFalsy();
|
125
|
+
|
126
|
+
// then check it
|
127
|
+
this.model.set({drivers_license: true});
|
128
|
+
var selected = el.attr("checked");
|
129
|
+
expect(selected).toBeTruthy();
|
130
|
+
});
|
131
|
+
|
132
|
+
it("binds the model's value to the form field on render", function(){
|
133
|
+
var el = this.view.$(".drivers_license");
|
134
|
+
var selected = el.attr("checked");
|
135
|
+
|
136
|
+
expect(selected).toBeTruthy();
|
137
|
+
});
|
138
|
+
});
|
139
|
+
});
|
@@ -0,0 +1,53 @@
|
|
1
|
+
describe("custom conventions", function(){
|
2
|
+
beforeEach(function(){
|
3
|
+
this.model = new AModel({});
|
4
|
+
this.view = new AView({model: this.model});
|
5
|
+
this.oldHandler = Backbone.ModelBinding.Conventions.text.handler;
|
6
|
+
|
7
|
+
});
|
8
|
+
|
9
|
+
afterEach(function(){
|
10
|
+
Backbone.ModelBinding.Conventions.text.handler = this.oldHandler;
|
11
|
+
});
|
12
|
+
|
13
|
+
describe("replace the text input handler", function(){
|
14
|
+
beforeEach(function(){
|
15
|
+
var nameSettingsHandler = {
|
16
|
+
bind: function(selector, view, model){
|
17
|
+
view.$("#name").val("a custom convention supplied this name");
|
18
|
+
}
|
19
|
+
};
|
20
|
+
|
21
|
+
Backbone.ModelBinding.Conventions.text.handler = nameSettingsHandler;
|
22
|
+
this.view.render();
|
23
|
+
});
|
24
|
+
|
25
|
+
it("should set the custom field value when rendered", function(){
|
26
|
+
expect(this.view.$("#name").val()).toBe("a custom convention supplied this name");
|
27
|
+
});
|
28
|
+
});
|
29
|
+
|
30
|
+
describe("add a brand new convention for paragraph tags", function(){
|
31
|
+
beforeEach(function(){
|
32
|
+
var PConvention = {
|
33
|
+
selector: "p",
|
34
|
+
handler: {
|
35
|
+
bind: function(selector, view, model){
|
36
|
+
view.$(selector).each(function(index){
|
37
|
+
var name = model.get("name");
|
38
|
+
$(this).html(name);
|
39
|
+
});
|
40
|
+
}
|
41
|
+
}
|
42
|
+
};
|
43
|
+
|
44
|
+
Backbone.ModelBinding.Conventions.paragraphs = PConvention;
|
45
|
+
});
|
46
|
+
|
47
|
+
it("should display the model name in the paragraph", function(){
|
48
|
+
this.model.set({name: "Gandalf Wizard"});
|
49
|
+
this.view.render();
|
50
|
+
expect(this.view.$("#aParagraph").html()).toBe("Gandalf Wizard");
|
51
|
+
});
|
52
|
+
});
|
53
|
+
});
|