asset_host_core 2.0.0.beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ };