asset_host_core 2.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (199) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.markdown +138 -0
  3. data/Rakefile +11 -0
  4. data/app/assets/images/asset_host_core/alert-overlay.png +0 -0
  5. data/app/assets/images/asset_host_core/arrow-left.gif +0 -0
  6. data/app/assets/images/asset_host_core/arrow-right.gif +0 -0
  7. data/app/assets/images/asset_host_core/fallback-img-rect.png +0 -0
  8. data/app/assets/images/asset_host_core/videoplayer-play.png +0 -0
  9. data/app/assets/images/asset_host_core/x.png +0 -0
  10. data/app/assets/javascripts/asset_host_core/admin/assets.js.coffee +221 -0
  11. data/app/assets/javascripts/asset_host_core/application.js +20 -0
  12. data/app/assets/javascripts/asset_host_core/assetadmin.js.coffee +56 -0
  13. data/app/assets/javascripts/asset_host_core/assethost.js.coffee.erb +17 -0
  14. data/app/assets/javascripts/asset_host_core/browserui.js.coffee +139 -0
  15. data/app/assets/javascripts/asset_host_core/chooserui.js.coffee +381 -0
  16. data/app/assets/javascripts/asset_host_core/client.js.coffee +29 -0
  17. data/app/assets/javascripts/asset_host_core/clients/BrightcoveVideo.js.coffee +64 -0
  18. data/app/assets/javascripts/asset_host_core/clients/templates/brightcove_embed.jst.eco +18 -0
  19. data/app/assets/javascripts/asset_host_core/clients/templates/vimeo_embed.jst.eco +1 -0
  20. data/app/assets/javascripts/asset_host_core/clients/templates/youtube_embed.jst.eco +1 -0
  21. data/app/assets/javascripts/asset_host_core/clients/vimeo_video.js.coffee +21 -0
  22. data/app/assets/javascripts/asset_host_core/clients/youtube_video.js.coffee +21 -0
  23. data/app/assets/javascripts/asset_host_core/cmsplugin.js.coffee +235 -0
  24. data/app/assets/javascripts/asset_host_core/models.js.coffee +586 -0
  25. data/app/assets/javascripts/asset_host_core/railsCMS.js.coffee +141 -0
  26. data/app/assets/javascripts/asset_host_core/slideshow.js.coffee +428 -0
  27. data/app/assets/javascripts/asset_host_core/templates/after_upload_button.jst.eco +3 -0
  28. data/app/assets/javascripts/asset_host_core/templates/asset_drop_asset.jst.eco +4 -0
  29. data/app/assets/javascripts/asset_host_core/templates/asset_modal.jst.eco +13 -0
  30. data/app/assets/javascripts/asset_host_core/templates/asset_preview.jst.eco +35 -0
  31. data/app/assets/javascripts/asset_host_core/templates/asset_search.jst.eco +2 -0
  32. data/app/assets/javascripts/asset_host_core/templates/browser_asset.jst.eco +1 -0
  33. data/app/assets/javascripts/asset_host_core/templates/browser_asset_tip.jst.eco +3 -0
  34. data/app/assets/javascripts/asset_host_core/templates/edit_modal.jst.eco +40 -0
  35. data/app/assets/javascripts/asset_host_core/templates/import_help.jst.eco +59 -0
  36. data/app/assets/javascripts/asset_host_core/templates/pagination_link.jst.eco +1 -0
  37. data/app/assets/javascripts/asset_host_core/templates/pagination_links.jst.eco +13 -0
  38. data/app/assets/javascripts/asset_host_core/templates/queued_file.jst.eco +11 -0
  39. data/app/assets/javascripts/asset_host_core/templates/save_and_close_view.jst.eco +4 -0
  40. data/app/assets/javascripts/asset_host_core/templates/upload_all_button.jst.eco +4 -0
  41. data/app/assets/javascripts/asset_host_core/templates/url_input.jst.eco +8 -0
  42. data/app/assets/stylesheets/asset_host_core/application.css.scss +384 -0
  43. data/app/assets/stylesheets/asset_host_core/jquery-ui.css +105 -0
  44. data/app/assets/stylesheets/asset_host_core/public.css.scss +204 -0
  45. data/app/assets/stylesheets/asset_host_core/slidetest.css.scss +93 -0
  46. data/app/controllers/asset_host_core/admin/api_users_controller.rb +72 -0
  47. data/app/controllers/asset_host_core/admin/assets_controller.rb +140 -0
  48. data/app/controllers/asset_host_core/admin/base_controller.rb +36 -0
  49. data/app/controllers/asset_host_core/admin/home_controller.rb +13 -0
  50. data/app/controllers/asset_host_core/admin/outputs_controller.rb +55 -0
  51. data/app/controllers/asset_host_core/api/assets_controller.rb +110 -0
  52. data/app/controllers/asset_host_core/api/base_controller.rb +43 -0
  53. data/app/controllers/asset_host_core/api/outputs_controller.rb +33 -0
  54. data/app/controllers/asset_host_core/application_controller.rb +43 -0
  55. data/app/controllers/asset_host_core/public_controller.rb +104 -0
  56. data/app/models/asset_host_core/api_user.rb +44 -0
  57. data/app/models/asset_host_core/api_user_permission.rb +6 -0
  58. data/app/models/asset_host_core/asset.rb +265 -0
  59. data/app/models/asset_host_core/asset_output.rb +69 -0
  60. data/app/models/asset_host_core/brightcove_video.rb +20 -0
  61. data/app/models/asset_host_core/output.rb +52 -0
  62. data/app/models/asset_host_core/permission.rb +19 -0
  63. data/app/models/asset_host_core/video.rb +8 -0
  64. data/app/models/asset_host_core/vimeo_video.rb +17 -0
  65. data/app/models/asset_host_core/youtube_video.rb +17 -0
  66. data/app/views/asset_host_core/admin/api_users/_form_fields.html.erb +5 -0
  67. data/app/views/asset_host_core/admin/api_users/edit.html.erb +26 -0
  68. data/app/views/asset_host_core/admin/api_users/index.html.erb +31 -0
  69. data/app/views/asset_host_core/admin/api_users/new.html.erb +17 -0
  70. data/app/views/asset_host_core/admin/api_users/show.html.erb +23 -0
  71. data/app/views/asset_host_core/admin/assets/index.html.erb +19 -0
  72. data/app/views/asset_host_core/admin/assets/metadata.html.erb +24 -0
  73. data/app/views/asset_host_core/admin/assets/show.html.erb +86 -0
  74. data/app/views/asset_host_core/admin/home/chooser.html.erb +49 -0
  75. data/app/views/asset_host_core/admin/outputs/_form_fields.html.erb +5 -0
  76. data/app/views/asset_host_core/admin/outputs/edit.html.erb +26 -0
  77. data/app/views/asset_host_core/admin/outputs/index.html.erb +27 -0
  78. data/app/views/asset_host_core/admin/outputs/new.html.erb +13 -0
  79. data/app/views/asset_host_core/admin/outputs/show.html.erb +17 -0
  80. data/app/views/asset_host_core/shared/_footerjs.html.erb +3 -0
  81. data/app/views/asset_host_core/shared/_navbar.html.erb +28 -0
  82. data/app/views/kaminari/_first_page.html.erb +3 -0
  83. data/app/views/kaminari/_gap.html.erb +3 -0
  84. data/app/views/kaminari/_last_page.html.erb +3 -0
  85. data/app/views/kaminari/_next_page.html.erb +3 -0
  86. data/app/views/kaminari/_page.html.erb +3 -0
  87. data/app/views/kaminari/_paginator.html.erb +17 -0
  88. data/app/views/kaminari/_prev_page.html.erb +3 -0
  89. data/app/views/layouts/asset_host_core/application.html.erb +54 -0
  90. data/app/views/layouts/asset_host_core/full_width.html.erb +32 -0
  91. data/app/views/layouts/asset_host_core/minimal.html.erb +45 -0
  92. data/config/initializers/simple_form.rb +142 -0
  93. data/config/initializers/simple_form_bootstrap.rb +45 -0
  94. data/config/locales/simple_form.en.yml +26 -0
  95. data/config/routes.rb +49 -0
  96. data/lib/asset_host_core.rb +38 -0
  97. data/lib/asset_host_core/config.rb +39 -0
  98. data/lib/asset_host_core/engine.rb +94 -0
  99. data/lib/asset_host_core/loaders.rb +34 -0
  100. data/lib/asset_host_core/loaders/asset_host.rb +30 -0
  101. data/lib/asset_host_core/loaders/base.rb +22 -0
  102. data/lib/asset_host_core/loaders/brightcove.rb +67 -0
  103. data/lib/asset_host_core/loaders/flickr.rb +114 -0
  104. data/lib/asset_host_core/loaders/url.rb +59 -0
  105. data/lib/asset_host_core/loaders/vimeo.rb +76 -0
  106. data/lib/asset_host_core/loaders/youtube.rb +90 -0
  107. data/lib/asset_host_core/model_methods.rb +61 -0
  108. data/lib/asset_host_core/paperclip.rb +4 -0
  109. data/lib/asset_host_core/paperclip/asset_thumbnail.rb +92 -0
  110. data/lib/asset_host_core/paperclip/attachment.rb +206 -0
  111. data/lib/asset_host_core/paperclip/trimmer.rb +33 -0
  112. data/lib/asset_host_core/resque_job.rb +13 -0
  113. data/lib/asset_host_core/version.rb +3 -0
  114. data/lib/tasks/asset_host_core_tasks.rake +4 -0
  115. data/spec/controllers/admin/api_users_controller_spec.rb +21 -0
  116. data/spec/controllers/admin/assets_controller_spec.rb +59 -0
  117. data/spec/controllers/admin/home_controller_spec.rb +4 -0
  118. data/spec/controllers/admin/outputs_controller_spec.rb +4 -0
  119. data/spec/controllers/api/assets_controller_spec.rb +133 -0
  120. data/spec/controllers/api/outputs_controller_spec.rb +51 -0
  121. data/spec/controllers/public_controller_spec.rb +4 -0
  122. data/spec/factories.rb +39 -0
  123. data/spec/features/api_users_spec.rb +78 -0
  124. data/spec/fixtures/api/brightcove/video.json +137 -0
  125. data/spec/fixtures/api/flickr/photos_getInfo.json +78 -0
  126. data/spec/fixtures/api/flickr/photos_getSizes.json +82 -0
  127. data/spec/fixtures/api/flickr/photos_licenses_getInfo.json +52 -0
  128. data/spec/fixtures/api/vimeo/video.json +28 -0
  129. data/spec/fixtures/api/youtube/discovery.json +5190 -0
  130. data/spec/fixtures/api/youtube/video.json +44 -0
  131. data/spec/fixtures/images/chipmunk.jpg +0 -0
  132. data/spec/fixtures/images/dude.jpg +0 -0
  133. data/spec/fixtures/images/ernie.jpg +0 -0
  134. data/spec/fixtures/images/fry.png +0 -0
  135. data/spec/fixtures/images/hat.jpg +0 -0
  136. data/spec/fixtures/images/spongebob.png +0 -0
  137. data/spec/fixtures/images/stars.jpg +0 -0
  138. data/spec/internal/app/controllers/application_controller.rb +16 -0
  139. data/spec/internal/app/controllers/sessions_controller.rb +24 -0
  140. data/spec/internal/app/models/user.rb +10 -0
  141. data/spec/internal/app/views/sessions/new.html.erb +14 -0
  142. data/spec/internal/config/database.yml +3 -0
  143. data/spec/internal/config/initializers/assethost_config.rb +57 -0
  144. data/spec/internal/config/routes.rb +7 -0
  145. data/spec/internal/db/combustion_test.sqlite +0 -0
  146. data/spec/internal/db/schema.rb +106 -0
  147. data/spec/internal/log/test.log +14769 -0
  148. data/spec/internal/public/favicon.ico +0 -0
  149. data/spec/internal/public/images/1_27f7745237849975ca90591c1fba5934_original. +0 -0
  150. data/spec/internal/public/images/1_7d33319deca787d5bb3f62ff06563ad2_original. +0 -0
  151. data/spec/internal/public/images/1_b6d48c8b1286104ce76649731e09645f_original. +0 -0
  152. data/spec/internal/public/images/1_b6d48c8b1286104ce76649731e09645f_original.jpg +0 -0
  153. data/spec/internal/public/images/1_b6d48c8b1286104ce76649731e09645f_original.txt +0 -0
  154. data/spec/internal/public/images/1_e179cbd27e07cb55042d0db36cdac095_original. +0 -0
  155. data/spec/internal/public/images/1_e669edd3dfd74be66fc38416e82e3a37_original. +0 -0
  156. data/spec/lib/asset_host_core/loaders/asset_host_spec.rb +33 -0
  157. data/spec/lib/asset_host_core/loaders/brightcove_spec.rb +51 -0
  158. data/spec/lib/asset_host_core/loaders/flickr_spec.rb +72 -0
  159. data/spec/lib/asset_host_core/loaders/url_spec.rb +42 -0
  160. data/spec/lib/asset_host_core/loaders/vimeo_spec.rb +51 -0
  161. data/spec/lib/asset_host_core/loaders/youtube_spec.rb +73 -0
  162. data/spec/lib/asset_host_core/loaders_spec.rb +4 -0
  163. data/spec/lib/asset_host_core/model_methods_spec.rb +4 -0
  164. data/spec/lib/asset_host_core/paperclip/asset_thumbnail_spec.rb +4 -0
  165. data/spec/lib/asset_host_core/paperclip/attachment_spec.rb +4 -0
  166. data/spec/lib/asset_host_core/resque_job_spec.rb +4 -0
  167. data/spec/lib/asset_host_core_spec.rb +4 -0
  168. data/spec/models/api_user_spec.rb +58 -0
  169. data/spec/models/asset_output_spec.rb +4 -0
  170. data/spec/models/asset_spec.rb +4 -0
  171. data/spec/models/output_spec.rb +4 -0
  172. data/spec/models/permission_spec.rb +4 -0
  173. data/spec/spec_helper.rb +30 -0
  174. data/spec/support/fixture_loader.rb +9 -0
  175. data/spec/support/param_helper.rb +14 -0
  176. data/spec/support/permission_matcher.rb +17 -0
  177. data/vendor/assets/images/jquery-ui/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  178. data/vendor/assets/images/jquery-ui/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  179. data/vendor/assets/images/jquery-ui/ui-bg_flat_10_000000_40x100.png +0 -0
  180. data/vendor/assets/images/jquery-ui/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  181. data/vendor/assets/images/jquery-ui/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  182. data/vendor/assets/images/jquery-ui/ui-bg_glass_65_ffffff_1x400.png +0 -0
  183. data/vendor/assets/images/jquery-ui/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  184. data/vendor/assets/images/jquery-ui/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  185. data/vendor/assets/images/jquery-ui/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  186. data/vendor/assets/images/jquery-ui/ui-icons_222222_256x240.png +0 -0
  187. data/vendor/assets/images/jquery-ui/ui-icons_228ef1_256x240.png +0 -0
  188. data/vendor/assets/images/jquery-ui/ui-icons_ef8c08_256x240.png +0 -0
  189. data/vendor/assets/images/jquery-ui/ui-icons_ffd27a_256x240.png +0 -0
  190. data/vendor/assets/images/jquery-ui/ui-icons_ffffff_256x240.png +0 -0
  191. data/vendor/assets/javascripts/backbone.js +1158 -0
  192. data/vendor/assets/javascripts/backbone.modelbinding.js +475 -0
  193. data/vendor/assets/javascripts/exif.js +695 -0
  194. data/vendor/assets/javascripts/jquery-ui.js +5614 -0
  195. data/vendor/assets/javascripts/simplemodal.js +698 -0
  196. data/vendor/assets/javascripts/spin.jquery.js +81 -0
  197. data/vendor/assets/javascripts/spin.min.js +1 -0
  198. data/vendor/assets/javascripts/underscore.min.js +1 -0
  199. metadata +658 -0
@@ -0,0 +1,475 @@
1
+ // Backbone.ModelBinding v0.3.9
2
+ //
3
+ // Copyright (C)2011 Derick Bailey, Muted Solutions, LLC
4
+ // Distributed Under MIT Liscene
5
+ //
6
+ // Documentation and Full Licence Availabe at:
7
+ // http://github.com/derickbailey/backbone.modelbinding
8
+
9
+ // ----------------------------
10
+ // Backbone.ModelBinding
11
+ // ----------------------------
12
+ Backbone.ModelBinding = (function(){
13
+ function handleConventionBindings(view, model){
14
+ var conventions = Backbone.ModelBinding.Conventions;
15
+ for (var conventionName in conventions){
16
+ if (conventions.hasOwnProperty(conventionName)){
17
+ var conventionElement = conventions[conventionName];
18
+ var handler = conventionElement.handler;
19
+ var conventionSelector = conventionElement.selector;
20
+ handler.bind(conventionSelector, view, model);
21
+ }
22
+ }
23
+ }
24
+
25
+ function handleUnbinding(view, model){
26
+ var conventions = Backbone.ModelBinding.Conventions;
27
+ for (var conventionName in conventions){
28
+ if (conventions.hasOwnProperty(conventionName)){
29
+ var conventionElement = conventions[conventionName];
30
+ var handler = conventionElement.handler;
31
+ var conventionSelector = conventionElement.selector;
32
+ if (handler.unbind){
33
+ handler.unbind(conventionSelector, view, model);
34
+ }
35
+ }
36
+ }
37
+ }
38
+
39
+ return {
40
+ version: "0.3.9",
41
+
42
+ bind: function(view, options){
43
+ Backbone.ModelBinding.Configuration.configureBindingAttributes(options);
44
+ handleConventionBindings(view, view.model);
45
+ Backbone.ModelBinding.Configuration.restoreBindingAttrConfig();
46
+ },
47
+
48
+ unbind: function(view){
49
+ handleUnbinding(view, view.model);
50
+ }
51
+ }
52
+ })();
53
+
54
+ // ----------------------------
55
+ // Model Binding Configuration
56
+ // ----------------------------
57
+ Backbone.ModelBinding.Configuration = (function(){
58
+ var bindingAttrConfig = {
59
+ text: "id",
60
+ textarea: "id",
61
+ password: "id",
62
+ radio: "name",
63
+ checkbox: "id",
64
+ select: "id"
65
+ };
66
+
67
+ return {
68
+ configureBindingAttributes: function(options){
69
+ if (options) {
70
+ this.storeBindingAttrConfig();
71
+ if (options.all){
72
+ this.configureAllBindingAttributes(options.all);
73
+ delete options.all;
74
+ }
75
+ _.extend(bindingAttrConfig, options);
76
+ }
77
+ },
78
+
79
+ configureAllBindingAttributes: function(attribute){
80
+ this.storeBindingAttrConfig();
81
+ bindingAttrConfig.text = attribute;
82
+ bindingAttrConfig.textarea = attribute;
83
+ bindingAttrConfig.password = attribute;
84
+ bindingAttrConfig.radio = attribute;
85
+ bindingAttrConfig.checkbox = attribute;
86
+ bindingAttrConfig.select = attribute;
87
+ },
88
+
89
+ storeBindingAttrConfig: function(){
90
+ this._config = _.clone(bindingAttrConfig);
91
+ },
92
+
93
+ restoreBindingAttrConfig: function(){
94
+ if (this._config) {
95
+ bindingAttrConfig = this._config;
96
+ delete this._config;
97
+ }
98
+ },
99
+
100
+ getBindingAttr: function(type){ return bindingAttrConfig[type]; },
101
+
102
+ getBindingValue: function(element, type){
103
+ var bindingAttr = this.getBindingAttr(type);
104
+ return element.attr(bindingAttr);
105
+ }
106
+ }
107
+ })();
108
+
109
+ // ----------------------------
110
+ // Text, Textarea, and Password Bi-Directional Binding Methods
111
+ // ----------------------------
112
+ Backbone.ModelBinding.StandardBinding = (function(){
113
+ var methods = {};
114
+
115
+ methods._getElementType = function(element) {
116
+ var type = element[0].tagName.toLowerCase();
117
+ if (type == "input"){
118
+ type = element.attr("type");
119
+ if (type == undefined || type == ''){
120
+ type = 'text'
121
+ }
122
+ }
123
+ return type;
124
+ };
125
+
126
+ methods._modelChange = function(changed_model, val){
127
+ this.element.val(val);
128
+ };
129
+
130
+ methods.unbind = function(selector, view, model){
131
+ view.$(selector).each(function(index){
132
+ var element = view.$(this);
133
+ var attribute_name = Backbone.ModelBinding.Configuration.getBindingValue(element, methods._getElementType(element));
134
+ // unbind the model changes to the form elements
135
+ model.unbind("change:" + attribute_name, methods._modelChange);
136
+ });
137
+ };
138
+
139
+ methods.bind = function(selector, view, model){
140
+ view.$(selector).each(function(index){
141
+ var element = view.$(this);
142
+
143
+ var attribute_name = Backbone.ModelBinding.Configuration.getBindingValue(element, methods._getElementType(element));
144
+ // bind the model changes to the form elements
145
+ // force "this" to be our config object, so i can
146
+ // get the data that i need, during the callback.
147
+ // i have to do it this way because the unbinding
148
+ // that occurs a few lines above, in the "unbind" method
149
+ // requires the same instance of the callback method as
150
+ // was passed into the bind method here. however, i need
151
+ // more data in the callback than i'm able to get because
152
+ // it's a callback, limited to the model's "change" event.
153
+ // by passing in "config" as "this" for the callback, i
154
+ // can get all the data i need. you'll see this pattern
155
+ // repeated through the rest of the binding objects.
156
+ var config = {element: element};
157
+ model.bind("change:" + attribute_name, methods._modelChange, config);
158
+
159
+ // bind the form changes to the model
160
+ element.bind("change", function(ev){
161
+ var data = {};
162
+ data[attribute_name] = view.$(ev.target).val();
163
+ model.set(data);
164
+ });
165
+
166
+ // set the default value on the form, from the model
167
+ var attr_value = model.get(attribute_name);
168
+ if (typeof attr_value !== "undefined" && attr_value !== null) {
169
+ element.val(attr_value);
170
+ }
171
+ });
172
+ };
173
+
174
+ return methods;
175
+ })();
176
+
177
+ // ----------------------------
178
+ // Select Box Bi-Directional Binding Methods
179
+ // ----------------------------
180
+ Backbone.ModelBinding.SelectBoxBinding = (function(){
181
+ var methods = {};
182
+
183
+ methods._modelChange = function(changed_model, val){
184
+ this.element.val(val);
185
+ };
186
+
187
+ methods.unbind = function(selector, view, model){
188
+ view.$(selector).each(function(index){
189
+ var element = view.$(this);
190
+ var attribute_name = Backbone.ModelBinding.Configuration.getBindingValue(element, 'select');
191
+ model.unbind("change:" + attribute_name, methods._modelChange);
192
+ });
193
+ };
194
+
195
+ methods.bind = function(selector, view, model){
196
+ view.$(selector).each(function(index){
197
+ var element = view.$(this);
198
+ var attribute_name = Backbone.ModelBinding.Configuration.getBindingValue(element, 'select');
199
+
200
+ // bind the model changes to the form elements
201
+ var config = {element: element};
202
+ model.bind("change:" + attribute_name, methods._modelChange, config);
203
+
204
+ // bind the form changes to the model
205
+ element.bind("change", function(ev){
206
+ var data = {};
207
+ var targetEl = view.$(ev.target);
208
+ data[attribute_name] = targetEl.val();
209
+ data[attribute_name + "_text"] = targetEl.find(":selected").text();
210
+ model.set(data);
211
+ });
212
+
213
+ // set the default value on the form, from the model
214
+ var attr_value = model.get(attribute_name);
215
+ if (typeof attr_value !== "undefined" && attr_value !== null) {
216
+ element.val(attr_value);
217
+ }
218
+ });
219
+ };
220
+
221
+ return methods;
222
+ })();
223
+
224
+ // ----------------------------
225
+ // Radio Button Group Bi-Directional Binding Methods
226
+ // ----------------------------
227
+ Backbone.ModelBinding.RadioGroupBinding = (function(){
228
+ var methods = {};
229
+
230
+ methods._modelChange = function(model, val){
231
+ var value_selector = "input[type=radio][" + this.bindingAttr + "=" + this.group_name + "][value=" + val + "]";
232
+ this.view.$(value_selector).attr("checked", "checked");
233
+ };
234
+
235
+ methods.unbind = function(selector, view, model){
236
+ var foundElements = [];
237
+ view.$(selector).each(function(index){
238
+ var element = view.$(this);
239
+ var group_name = Backbone.ModelBinding.Configuration.getBindingValue(element, 'radio');
240
+ if (!foundElements[group_name]) {
241
+ foundElements[group_name] = true;
242
+ var bindingAttr = Backbone.ModelBinding.Configuration.getBindingAttr('radio');
243
+ model.unbind("change:" + group_name, methods._modelChange);
244
+ }
245
+ });
246
+ };
247
+
248
+ methods.bind = function(selector, view, model){
249
+ var foundElements = [];
250
+ view.$(selector).each(function(index){
251
+ var element = view.$(this);
252
+
253
+ var group_name = Backbone.ModelBinding.Configuration.getBindingValue(element, 'radio');
254
+ if (!foundElements[group_name]) {
255
+ foundElements[group_name] = true;
256
+ var bindingAttr = Backbone.ModelBinding.Configuration.getBindingAttr('radio');
257
+
258
+ // bind the model changes to the form elements
259
+ var config = {
260
+ bindingAttr: bindingAttr,
261
+ group_name: group_name,
262
+ view: view
263
+ };
264
+ model.bind("change:" + group_name, methods._modelChange, config);
265
+
266
+ // bind the form changes to the model
267
+ var group_selector = "input[type=radio][" + bindingAttr + "=" + group_name + "]";
268
+ view.$(group_selector).bind("change", function(ev){
269
+ var element = view.$(ev.currentTarget);
270
+ if (element.is(":checked")){
271
+ var data = {};
272
+ data[group_name] = element.val();
273
+ model.set(data);
274
+ }
275
+ });
276
+
277
+ // set the default value on the form, from the model
278
+ var attr_value = model.get(group_name);
279
+ if (typeof attr_value !== "undefined" && attr_value !== null) {
280
+ var value_selector = "input[type=radio][" + bindingAttr + "=" + group_name + "][value=" + attr_value + "]";
281
+ view.$(value_selector).attr("checked", "checked");
282
+ }
283
+ }
284
+ });
285
+ };
286
+
287
+ return methods;
288
+ })();
289
+
290
+ // ----------------------------
291
+ // Checkbox Bi-Directional Binding Methods
292
+ // ----------------------------
293
+ Backbone.ModelBinding.CheckboxBinding = (function(){
294
+ var methods = {};
295
+
296
+ methods._modelChange = function(model, val){
297
+ if (val){
298
+ this.element.attr("checked", "checked");
299
+ }
300
+ else{
301
+ this.element.removeAttr("checked");
302
+ }
303
+ };
304
+
305
+ methods.unbind = function(selector, view, model){
306
+ view.$(selector).each(function(index){
307
+ var element = view.$(this);
308
+ var attribute_name = Backbone.ModelBinding.Configuration.getBindingValue(element, 'checkbox');
309
+ model.unbind("change:" + attribute_name, methods._modelChange);
310
+ });
311
+ };
312
+
313
+ methods.bind = function(selector, view, model){
314
+ view.$(selector).each(function(index){
315
+ var element = view.$(this);
316
+ var attribute_name = Backbone.ModelBinding.Configuration.getBindingValue(element, 'checkbox');
317
+
318
+ // bind the model changes to the form elements
319
+ var config = {element: element};
320
+ model.bind("change:" + attribute_name, methods._modelChange, config);
321
+
322
+ // bind the form changes to the model
323
+ element.bind("change", function(ev){
324
+ var data = {};
325
+ var changedElement = view.$(ev.target);
326
+ var checked = changedElement.is(":checked")? true : false;
327
+ data[attribute_name] = checked;
328
+ model.set(data);
329
+ });
330
+
331
+ // set the default value on the form, from the model
332
+ var attr_exists = model.attributes.hasOwnProperty(attribute_name);
333
+ if (attr_exists) {
334
+ var attr_value = model.get(attribute_name);
335
+ if (typeof attr_value !== "undefined" && attr_value !== null && attr_value != false) {
336
+ element.attr("checked", "checked");
337
+ }
338
+ else{
339
+ element.removeAttr("checked");
340
+ }
341
+ }
342
+ });
343
+ };
344
+
345
+ return methods;
346
+ })();
347
+
348
+ // ----------------------------
349
+ // Data-Bind Binding Methods
350
+ // ----------------------------
351
+ Backbone.ModelBinding.DataBindBinding = (function(){
352
+ var methods = {};
353
+
354
+ var dataBindSubstConfig = {
355
+ "default": ""
356
+ };
357
+
358
+ Backbone.ModelBinding.Configuration.dataBindSubst = function(config){
359
+ this.storeDataBindSubstConfig();
360
+ _.extend(dataBindSubstConfig, config);
361
+ };
362
+
363
+ Backbone.ModelBinding.Configuration.storeDataBindSubstConfig = function(){
364
+ Backbone.ModelBinding.Configuration._dataBindSubstConfig = _.clone(dataBindSubstConfig);
365
+ };
366
+
367
+ Backbone.ModelBinding.Configuration.restoreDataBindSubstConfig = function(){
368
+ if (Backbone.ModelBinding.Configuration._dataBindSubstConfig){
369
+ dataBindSubstConfig = Backbone.ModelBinding.Configuration._dataBindSubstConfig;
370
+ delete Backbone.ModelBinding.Configuration._dataBindSubstConfig;
371
+ }
372
+ };
373
+
374
+ Backbone.ModelBinding.Configuration.getDataBindSubst = function(elementType, value){
375
+ var returnValue = value;
376
+ if (value === undefined){
377
+ if (dataBindSubstConfig.hasOwnProperty(elementType)){
378
+ returnValue = dataBindSubstConfig[elementType];
379
+ } else {
380
+ returnValue = dataBindSubstConfig["default"];
381
+ }
382
+ }
383
+ return returnValue;
384
+ };
385
+
386
+ methods._modelChange = function(model, val){
387
+ methods._setOnElement(this.element, this.elementAttr, val);
388
+ };
389
+
390
+ methods._setOnElement = function(element, attr, val){
391
+ var valBefore = val;
392
+ val = Backbone.ModelBinding.Configuration.getDataBindSubst(attr, val);
393
+ switch(attr){
394
+ case "html":
395
+ element.html(val);
396
+ break;
397
+ case "text":
398
+ element.text(val);
399
+ break;
400
+ case "enabled":
401
+ element.attr("disabled", !val);
402
+ break;
403
+ case "displayed":
404
+ element.css("display", val ? 'block' : 'none' );
405
+ break;
406
+ case "hidden":
407
+ element.css("display", val ? 'none' : 'block' );
408
+ break;
409
+ default:
410
+ element.attr(attr, val);
411
+ }
412
+ };
413
+
414
+ methods._splitBindingAttr = function(element)
415
+ {
416
+ var dataBindConfigList = [];
417
+ var databindList = element.attr("data-bind").split(";");
418
+ _.each(databindList, function(attrbind){
419
+ var databind = $.trim(attrbind).split(" ");
420
+
421
+ // make the default special case "text" if none specified
422
+ if( databind.length == 1 ) databind.unshift("text");
423
+
424
+ dataBindConfigList.push({
425
+ elementAttr: databind[0],
426
+ modelAttr: databind[1]
427
+ });
428
+ });
429
+ return dataBindConfigList;
430
+ };
431
+
432
+ methods.bind = function(selector, view, model){
433
+ view.$(selector).each(function(index){
434
+ var element = view.$(this);
435
+ var databindList = methods._splitBindingAttr(element);
436
+
437
+ _.each(databindList, function(databind){
438
+ var config = {
439
+ element: element,
440
+ elementAttr: databind.elementAttr
441
+ };
442
+ model.bind("change:" + databind.modelAttr, methods._modelChange, config);
443
+
444
+ // set default on data-bind element
445
+ methods._setOnElement(element, databind.elementAttr, model.get(databind.modelAttr));
446
+ });
447
+ });
448
+ };
449
+
450
+ methods.unbind = function(selector, view, model){
451
+ view.$(selector).each(function(index){
452
+ var element = view.$(this);
453
+ var databindList = methods._splitBindingAttr(element);
454
+ _.each(databindList, function(databind){
455
+ model.unbind("change:" + databind.modelAttr, methods._modelChange);
456
+ });
457
+ });
458
+ };
459
+
460
+ return methods;
461
+ })();
462
+
463
+
464
+ // ----------------------------
465
+ // Binding Conventions
466
+ // ----------------------------
467
+ Backbone.ModelBinding.Conventions = {
468
+ text: {selector: "input:text", handler: Backbone.ModelBinding.StandardBinding},
469
+ textarea: {selector: "textarea", handler: Backbone.ModelBinding.StandardBinding},
470
+ password: {selector: "input:password", handler: Backbone.ModelBinding.StandardBinding},
471
+ radio: {selector: "input:radio", handler: Backbone.ModelBinding.RadioGroupBinding},
472
+ checkbox: {selector: "input:checkbox", handler: Backbone.ModelBinding.CheckboxBinding},
473
+ select: {selector: "select", handler: Backbone.ModelBinding.SelectBoxBinding},
474
+ databind: { selector: "*[data-bind]", handler: Backbone.ModelBinding.DataBindBinding}
475
+ };