hobo_jquery 1.4.0.pre2

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.
@@ -0,0 +1,39 @@
1
+ /* hjq-sortable-collection */
2
+ (function($) {
3
+ var methods = {
4
+ init: function(annotations) {
5
+ var options = $.extend({update: methods.update}, this.hjq('getOptions', annotations));
6
+ this.sortable(options);
7
+ },
8
+
9
+ update: function() {
10
+ var that=$(this);
11
+ var annotations=that.data('rapid')['sortable-collection'];
12
+ var roptions = that.hjq('buildRequest', {type: 'post',
13
+ attrs: annotations.ajax_attrs
14
+ });
15
+ roptions.data['authenticity_token']=that.hjq('pageData').form_auth_token.value;
16
+ roptions.data=$.param(roptions.data);
17
+ that.children("*[data-rapid-context]").each(function(i) {
18
+ roptions.data = roptions.data+"&"+annotations.reorder_parameter+"[]="+$(this).hjq('contextId');
19
+ });
20
+
21
+ $.ajax(annotations.reorder_url, roptions);
22
+ return that;
23
+ }
24
+
25
+ };
26
+
27
+
28
+ $.fn.hjq_sortable_collection = function( method ) {
29
+
30
+ if ( methods[method] ) {
31
+ return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
32
+ } else if ( typeof method === 'object' || ! method ) {
33
+ return methods.init.apply( this, arguments );
34
+ } else {
35
+ $.error( 'Method ' + method + ' does not exist on hjq_sortable_collection' );
36
+ }
37
+ };
38
+
39
+ })( jQuery );
@@ -0,0 +1,87 @@
1
+ /* spinner */
2
+ (function($) {
3
+ var default_options = undefined;
4
+
5
+ // old min_time functionality removed -- using an effect on the
6
+ // removal ensures it stays on screen long enough to be visible.
7
+
8
+ var methods = {
9
+ /* without any options, $(foo).hjq_spinner() places a spinner
10
+ to the left of foo until you remove it via
11
+ $(foo).hjq_spinner('remove');
12
+
13
+ options:
14
+ - spinner-next-to: DOM id of the element to place the spinner next to.
15
+ - spinner-at: selector for the element to place the spinner next to.
16
+ - no-spinner: if set, the spinner is not displayed.
17
+ - spinner-options: passed to [jQuery-UI's position](http://jqueryui.com/demos/position/). Defaults are `{my: 'left center', at: 'right center', offset: '5 0'}`
18
+ - message: the message to display inside the spinner
19
+
20
+ If options.message is false-ish, default_message is displayed.
21
+ */
22
+ init: function(options, default_message) {
23
+ var original=$("#ajax-progress");
24
+ if (original.length==0) return this;
25
+
26
+ options = $.extend({}, defaultOptions.call(this), options);
27
+ if(options['no-spinner']) return this;
28
+
29
+ var clone=original.clone();
30
+ this.data('hjq-spinner', clone);
31
+ clone.data('source', this);
32
+
33
+ clone.find("span").text(options.message || default_message || "");
34
+
35
+ var pos_options = $.extend({}, defaultOptions()['spinner-options'], options['spinner-options']);
36
+
37
+ pos_options.of = this;
38
+ if(options['spinner-at']) pos_options.of=$(options['spinner-at']);
39
+ else if(options['spinner-next-to']) pos_options.of=$("#"+options['spinner-next-to']);
40
+
41
+ clone.insertBefore(original).show().position(pos_options);
42
+ return this;
43
+ },
44
+
45
+ remove: function() {
46
+ var clone = this.data('hjq-spinner');
47
+ var that=this;
48
+ if(!clone) {
49
+ $(".ajax-progress").each(function() {
50
+ if($(this).data('source')[0]==that[0]) {
51
+ clone=$(this);
52
+ return false;
53
+ }
54
+ });
55
+ }
56
+ if(!clone) return this;
57
+ clone.hide('fast');
58
+ return this;
59
+ },
60
+ };
61
+
62
+ var defaultOptions = function() {
63
+ if(default_options) return default_options;
64
+ page_options = this.hjq('pageData');
65
+ default_options = {};
66
+ default_options['spinner-next-to'] = page_options['spinner-next-to'];
67
+ default_options['spinner-at'] = page_options['spinner-at'];
68
+ default_options['no-spinner'] = page_options['no-spinner'];
69
+ default_options['spinner-options'] = page_options['spinner-options'] || {
70
+ my: "right bottom",
71
+ at: "left top"
72
+ };
73
+ default_options['message'] = page_options['message'];
74
+ };
75
+
76
+ $.fn.hjq_spinner = function( method ) {
77
+
78
+ if ( methods[method] ) {
79
+ return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
80
+ } else if ( typeof method === 'object' || ! method ) {
81
+ return methods.init.apply( this, arguments );
82
+ } else {
83
+ $.error( 'Method ' + method + ' does not exist on hjq_spinner' );
84
+ }
85
+ };
86
+
87
+ })( jQuery );
@@ -0,0 +1,319 @@
1
+ /* hobo-jQuery initialization & utility functions */
2
+
3
+ (function($) {
4
+ var page_data = {};
5
+
6
+ //used for javascript testing.
7
+ var num_updates = 0;
8
+
9
+ var methods = {
10
+
11
+ init : function() {
12
+ var top = this;
13
+ this.find("[data-rapid-page-data]").each(function() {
14
+ page_data = $(this).data('rapid-page-data');
15
+ });
16
+ this.find("[data-rapid]").each(function() {
17
+ var that = jQuery(this);
18
+ jQuery.each(jQuery(this).data('rapid'), function(tag, annotations) {
19
+ tag = "hjq_"+tag.replace(/-/g, '_');
20
+ if(that[tag]) {
21
+ that[tag](annotations);
22
+ }
23
+ });
24
+ });
25
+ return top;
26
+ },
27
+
28
+ /* return the ID from the typed-id in the data-rapid-context attribute */
29
+ contextId: function() {
30
+ return this.data('rapid-context').split(":")[1];
31
+ },
32
+
33
+ /* given annotations, turns the values in the _events_ object into functions, merges them into _options_ and returns _options_ */
34
+ getOptions: function(annotations) {
35
+ for(var key in annotations.events) {
36
+ if(annotations.events.hasOwnProperty(key)) {
37
+ annotations.options[key] = methods.createFunction.call(this, annotations.events[key]);
38
+ }
39
+ }
40
+ return annotations.options;
41
+ },
42
+
43
+ /* return the global page_data: hobo_parts, form_auth_token, etc. */
44
+ pageData: function() { return page_data; },
45
+
46
+ /* return the number of current updates. Useful for
47
+ javascript/integration testing */
48
+ numUpdates: function() { return num_updates; },
49
+
50
+ /* this function is called on an update of a part via Ajax. */
51
+ update: function(innerHtml) {
52
+ num_updates += 1;
53
+ var that=this;
54
+ var replacement=this.clone().html(innerHtml).hide();
55
+ var hide_o, show_o;
56
+ if(this.data('hjq-ajax')) {
57
+ hide_o = this.data('hjq-ajax')['hide'];
58
+ show_o = this.data('hjq-ajax')['show'];
59
+ }
60
+ methods.hideAndRemove.call(this, hide_o, function () {
61
+ that.before(replacement);
62
+ methods.show.call(replacement, show_o, function() {num_updates -= 1;});
63
+ });
64
+ methods.init.call(replacement);
65
+ return replacement;
66
+ },
67
+
68
+ /* this function is called on ajax update to update part
69
+ context information */
70
+ updatePartContexts: function(contexts) {
71
+ $.extend(page_data.hobo_parts, contexts);
72
+ },
73
+
74
+ /* hide and removes the element. options is an array or
75
+ * comma-separated string corresponding to the jQuery-UI hide
76
+ * arguments: effect, options, speed & callback. The callback
77
+ * argument is an additional callback called after the one in
78
+ * the options hash. Removal is done after both callbacks. */
79
+ hideAndRemove: function(o, callback) {
80
+ methods.hide.call(this, o, callback, true);
81
+ },
82
+
83
+ /* hides the element. options is an array or
84
+ * comma-separated string corresponding to the jQuery-UI hide
85
+ * arguments: effect, options, speed & callback. The callback
86
+ * argument is an additional callback called after the one in
87
+ * the options hash. Removal is done after both callbacks. */
88
+ hide: function(o, callback, andRemove) {
89
+ var that=this;
90
+ var args = o;
91
+ if(args===undefined) args=page_data.hide;
92
+ if(args===undefined) args=[];
93
+ if (typeof args=='string') args=args.split(',');
94
+ else if($.isArray(args)) args=args.slice(0); //shallow clone
95
+ else args=[];
96
+ o_cb = args[3];
97
+ args[3] = function() {
98
+ if(o_cb) methods.createFunction.call(that, o_cb).apply(this, arguments);
99
+ if(callback) callback.apply(this, arguments);
100
+ if(andRemove) that.remove();
101
+ };
102
+ if(args[0]) {
103
+ that.hide.apply(that, args);
104
+ } else {
105
+ that.hide();
106
+ args[3].call(that);
107
+ }
108
+ return this;
109
+ },
110
+ /* show the element. options is an array or
111
+ * comma-separated string corresponding to the jQuery-UI show
112
+ * arguments: effect, options, speed & callback. The callback
113
+ * argument is an additional callback called after the one in
114
+ * the options hash. */
115
+ show: function(o, callback) {
116
+ var that=this;
117
+ var args = o;
118
+ if(args===undefined) args=page_data.show;
119
+ if(args===undefined) args=[];
120
+ if (typeof args=='string') args=args.split(',');
121
+ else if($.isArray(args)) args=args.slice(0); //shallow clone
122
+ else args=[];
123
+ o_cb = args[3];
124
+ args[3] = function() {
125
+ if(o_cb) methods.createFunction.call(that, o_cb).apply(this, arguments);
126
+ if(callback) callback.apply(this, arguments);
127
+ };
128
+ if(args[0]) {
129
+ that.show.apply(that, args);
130
+ } else {
131
+ that.show();
132
+ args[3].call(that);
133
+ }
134
+ return this;
135
+ },
136
+
137
+ /* given a global function name, find the function */
138
+ functionByName: function(name) {
139
+ var descend = window; // find function by name on the root object
140
+ jQuery.each(name.split("."), function() {
141
+ if(descend) descend = descend[this];
142
+ });
143
+ return descend;
144
+ },
145
+
146
+ /* Given a function name or javascript fragment, return a function */
147
+ createFunction: function(script) {
148
+ if(!script) return function() {};
149
+ if($.isFunction(script)) return script;
150
+ var f=methods.functionByName.call(this, script);
151
+ if(f) return f;
152
+ return function() { return eval(script); };
153
+ },
154
+
155
+ /* Build an options object suitable for sending to
156
+ * jQuery.ajax. (Note that the before & confirm callbacks
157
+ * are called from this function, and the spinner is shown)
158
+ *
159
+ * The returned object will include a 'data' value
160
+ * populated with a hash.
161
+ *
162
+ * Options:
163
+ * type: POST, GET
164
+ * attrs: a hash containing the standard Hobo ajax attributes & callbacks
165
+ * extra_options: merged into the hash sent to jQuery.ajax
166
+ * extra_callbacks: the callbacks in attrs are generally specified by the DRYML; this allows the framework to add their own
167
+ * function: passed to Hobo's ajax_update_response
168
+ * preamble: passed to Hobo's ajax_update_response
169
+ * postamble: passed to Hobo's ajax_update_response
170
+ * content_type: passed to Hobo's ajax_update_response
171
+ *
172
+ */
173
+ buildRequest: function(o) {
174
+ var that = this;
175
+ if (!o.attrs) o.attrs = {};
176
+ if (!o.extra_callbacks) o.extra_callbacks = {};
177
+ var options = {};
178
+
179
+ if(o.attrs.before) {
180
+ if(!methods.createFunction.call(that, o.attrs.before).call(this)) {
181
+ return false;
182
+ }
183
+ }
184
+
185
+ var before_evt=jQuery.Event("rapid:ajax:before");
186
+ that.trigger(before_evt, [that]);
187
+ if(before_evt.isPropagationStopped()) {
188
+ return false;
189
+ }
190
+
191
+ if(o.attrs.confirm) {
192
+ if(!confirm(o.attrs.confirm)) {
193
+ return false;
194
+ }
195
+ }
196
+
197
+ options.context = this;
198
+ options.type = o.type || 'GET';
199
+ options.data = {"render_options[preamble]": o.preamble || '',
200
+ "render_options[contexts_function]": 'hjq.ajax.updatePartContexts'
201
+ };
202
+ if(o.postamble) options.data["render_options[postamble]"] = o.postamble;
203
+ if(o.content_type) options.data["render_options[content_type]"] = o.content_type;
204
+ if(o.attrs.errors_ok) options.data["render_options[errors_ok]"] = 1;
205
+ options.dataType = 'script';
206
+ o.spec = jQuery.extend({'function': 'hjq.ajax.update', preamble: ''}, o.spec);
207
+
208
+ var part_data = {};
209
+ if(o.attrs.hide!==undefined) part_data.hide = o.attrs.hide;
210
+ if(o.attrs.show!==undefined) part_data.show = o.attrs.show;
211
+ if($.isEmptyObject(part_data)) part_data = undefined;
212
+
213
+ // we tell our controller which parts to return by sending it a "render" array.
214
+ var ids=methods.getUpdateIds.call(this, o.attrs);
215
+ for(var i=0; i<ids.length; i++) {
216
+ if(part_data) $("#"+ids[i]).data('hjq-ajax', part_data);
217
+ options.data["render["+i+"][part_context]"] = page_data.hobo_parts[ids[i]];
218
+ options.data["render["+i+"][id]"] = ids[i];
219
+ options.data["render["+i+"][function]"] = o['function'] || 'hjq.ajax.update';
220
+ }
221
+
222
+ this.hjq_spinner(o.attrs, "Saving...");
223
+
224
+ var success_dfd = jQuery.Deferred();
225
+ if(o.attrs.success) success_dfd.done(methods.createFunction.call(that, o.attrs.success));
226
+ if(o.extra_callbacks.success) success_dfd.done(methods.createFunction.call(that, o.extra_callbacks.success));
227
+ success_dfd.done(function() {
228
+ if(o.attrs.reset_form) that[0].reset();
229
+ // if we've been removed, all event handlers on us
230
+ // have already been removed and we don't bubble
231
+ // up, so triggering on that won't do any good
232
+ if(that.parents("body").length==0) $(document).trigger('rapid:ajax:success', [that]);
233
+ else that.trigger('rapid:ajax:success', [that]);
234
+ });
235
+ options.success = success_dfd.resolve;
236
+
237
+ var error_dfd = jQuery.Deferred();
238
+ if(o.attrs.error) error_dfd.done(methods.createFunction.call(that, o.attrs.error));
239
+ if(o.extra_callbacks.error) error_dfd.done(methods.createFunction.call(that, o.extra_callbacks.error));
240
+ error_dfd.done(function() {
241
+ if(that.parents("body").length==0) $(document).trigger('rapid:ajax:error', [that]);
242
+ else that.trigger('rapid:ajax:error', [that]);
243
+ });
244
+ options.error = error_dfd.resolve;
245
+
246
+ var complete_dfd = jQuery.Deferred();
247
+ if(o.attrs.complete) complete_dfd.done(methods.createFunction.call(that, o.attrs.complete));
248
+ if(o.extra_callbacks.complete) complete_dfd.done(methods.createFunction.call(that, o.extra_callbacks.complete));
249
+ complete_dfd.done(function() {
250
+ if(that.parents("body").length==0) $(document).trigger('rapid:ajax:complete', [that]);
251
+ else that.trigger('rapid:ajax:complete', [that]);
252
+ that.hjq_spinner('remove');
253
+ if(o.attrs.refocus_form) that.find(":input[type!=hidden]:first").focus();
254
+ });
255
+ options.complete = complete_dfd.resolve;
256
+
257
+ jQuery.extend(options, o.extra_options);
258
+
259
+ return options;
260
+ },
261
+
262
+ // given ajax_attrs (update, updates and/or ajax), return DOM id's.
263
+ getUpdateIds: function(attrs) {
264
+ var ids = attrs.update || [];
265
+ if (typeof ids=='string') ids=ids.split(',');
266
+
267
+ jQuery(attrs.updates).each(function () {
268
+ ids.push(jQuery(this).attr('id'));
269
+ });
270
+
271
+ if(attrs.ajax) {
272
+ for(var el=this; el.length && !page_data.hobo_parts[el.attr("id")]; el=el.parent());
273
+ if(el.length) ids.push(el.attr('id'));
274
+ }
275
+
276
+ // validate
277
+ for (var i=0; i<ids.length; i++) {
278
+ if(!page_data.hobo_parts[ids[i]]) {
279
+ ids.splice(i, 1);
280
+ i -= 1;
281
+ }
282
+ }
283
+
284
+ return ids;
285
+ }
286
+
287
+
288
+ };
289
+
290
+
291
+ $.fn.hjq = function( method ) {
292
+
293
+ if ( methods[method] ) {
294
+ return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
295
+ } else if ( typeof method === 'object' || ! method ) {
296
+ return methods.init.apply( this, arguments );
297
+ } else {
298
+ $.error( 'Method ' + method + ' does not exist on hjq' );
299
+ }
300
+ };
301
+
302
+ })( jQuery );
303
+
304
+
305
+ // to make the Ajax interface cleaner, these provide direct access to
306
+ // a couple of plugin functions.
307
+ var hjq=(function($) {
308
+ return {
309
+ ajax: {
310
+ update: function (dom_id, innerHtml) {
311
+ $("#"+dom_id).hjq('update',innerHtml);
312
+ },
313
+
314
+ updatePartContexts: function(contexts) {
315
+ $(document).hjq('updatePartContexts', contexts);
316
+ }
317
+ }
318
+ };
319
+ })(jQuery);
@@ -0,0 +1,5 @@
1
+ //= require_tree .
2
+
3
+ jQuery(document).ready(function() {
4
+ jQuery(document).hjq();
5
+ });