drogus-gadgeteer 0.3.0
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.
- data/LICENSE +1 -0
- data/README.rdoc +49 -0
- data/Rakefile +42 -0
- data/VERSION.yml +4 -0
- data/bin/gadgeteer +229 -0
- data/javascripts/jquery.form.js +643 -0
- data/javascripts/jquery.gadgeteer.js +372 -0
- data/javascripts/jquery.livequery.js +226 -0
- data/javascripts/opensocial-jquery.js +5588 -0
- data/lib/gadgeteer.rb +107 -0
- data/lib/sinatra/gadgeteer.rb +3 -0
- data/rails/init.rb +3 -0
- data/templates/canvas.haml +24 -0
- data/templates/gadget.haml +11 -0
- data/templates/gadget.js +9 -0
- data/templates/gadget.rb +7 -0
- data/templates/gadget.yml +24 -0
- data/templates/gadgets_controller.rb +6 -0
- data/test/gadgeteer_test.rb +7 -0
- data/test/test_helper.rb +10 -0
- metadata +82 -0
@@ -0,0 +1,372 @@
|
|
1
|
+
/*! Copyright (c) 2009 László Bácsi (http://icanscale.com)
|
2
|
+
* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
|
3
|
+
*
|
4
|
+
* Version: 0.3
|
5
|
+
* Requires opensocial-jQuery 1.0.4+
|
6
|
+
*/
|
7
|
+
|
8
|
+
(function($) {
|
9
|
+
|
10
|
+
$.gadgeteer = function(callback, options) {
|
11
|
+
// If called with callback, notify it if we're ready
|
12
|
+
if ($.isFunction(callback)) {
|
13
|
+
if ($.gadgeteer.options) {
|
14
|
+
return false;
|
15
|
+
} else {
|
16
|
+
$.gadgeteer.options = options = options || {};
|
17
|
+
}
|
18
|
+
$.gadgeteer.defaultTarget = options.defaultTarget || '#page';
|
19
|
+
$.gadgeteer.host = options.host || '';
|
20
|
+
|
21
|
+
// Setup link behaviours
|
22
|
+
$.gadgeteer.linkBehaviours = options.linkBehaviours || {};
|
23
|
+
if (!options.noAjaxLinks) {
|
24
|
+
$('a').livequery('click', function(e) {
|
25
|
+
$.gadgeteer.handleLinkBehaviour.call($(this), e);
|
26
|
+
}).removeAttr('onclick');
|
27
|
+
}
|
28
|
+
|
29
|
+
if (!options.noAjaxForms) {
|
30
|
+
// Making sure submit input element values are submitted
|
31
|
+
$('form input[type=submit]').livequery('click', function(e) {
|
32
|
+
$(this).parents('form:eq(0)').data('submitClicked', $(this));
|
33
|
+
});
|
34
|
+
// All forms will submit through an ajax call
|
35
|
+
$('form').livequery('submit', function(e) {
|
36
|
+
e.preventDefault();
|
37
|
+
var form = $(this);
|
38
|
+
var action = form.attr('action');
|
39
|
+
var target = form.hasClass('silent') ? null : $.gadgeteer.defaultTarget;
|
40
|
+
var params = [$.param(form.formToArray()), $.param($.gadgeteer.viewer.osParams()), $.param($.gadgeteer.owner.osParams())];
|
41
|
+
var submit = form.data('submitClicked');
|
42
|
+
if (submit) {
|
43
|
+
if (submit.attr('name')) {
|
44
|
+
var param = {};
|
45
|
+
param[submit.attr('name')] = submit.val();
|
46
|
+
params.push($.param(param));
|
47
|
+
}
|
48
|
+
if ($.gadgeteer.options.submitSendingMessage) {
|
49
|
+
submit.data('oldValue', submit.val());
|
50
|
+
submit.val($.gadgeteer.options.submitSendingMessage).get(0).disabled = true;
|
51
|
+
}
|
52
|
+
form.data('submitClicked', null);
|
53
|
+
}
|
54
|
+
action = $.gadgeteer.expandUri(action);
|
55
|
+
$.ajax({
|
56
|
+
url: action,
|
57
|
+
type: form.attr('method') || 'GET',
|
58
|
+
data: params.join("&"),
|
59
|
+
dataType: 'html',
|
60
|
+
oauth: 'signed',
|
61
|
+
target: target,
|
62
|
+
complete: function(request, status) {
|
63
|
+
if (submit) {
|
64
|
+
var oldValue = submit.data('oldValue');
|
65
|
+
if (oldValue) {
|
66
|
+
submit.val(oldValue).get(0).disabled = false;
|
67
|
+
submit.data('oldValue', null);
|
68
|
+
}
|
69
|
+
}
|
70
|
+
}
|
71
|
+
});
|
72
|
+
});
|
73
|
+
}
|
74
|
+
|
75
|
+
// Setup ajax event callbacks
|
76
|
+
$(document).ajaxSend(function(e, request, settings) {
|
77
|
+
if (settings.target && $.gadgeteer.options.loadingMessage) {
|
78
|
+
$(settings.target).append($.gadgeteer.loadingElem());
|
79
|
+
}
|
80
|
+
}).ajaxSuccess(function(e, request, settings) {
|
81
|
+
$.gadgeteer.currentUrl = request.url;
|
82
|
+
if (settings.target) {
|
83
|
+
var html = request.responseText;
|
84
|
+
$(settings.target).html(html);
|
85
|
+
}
|
86
|
+
// !iframe
|
87
|
+
$(window).adjustHeight();
|
88
|
+
// Do another adjustHeight in 250ms just to be sure
|
89
|
+
setTimeout(function() {$(window).adjustHeight();}, 250);
|
90
|
+
}).ajaxError(function(e, request, settings, exception) {
|
91
|
+
if (settings.target && request.status.toString().charAt(0) != '3') {
|
92
|
+
var html = request.responseText;
|
93
|
+
$(settings.target).html(html);
|
94
|
+
// !iframe
|
95
|
+
$(window).adjustHeight();
|
96
|
+
// Do another adjustHeight in 250ms just to be sure
|
97
|
+
setTimeout(function() {$(window).adjustHeight();}, 250);
|
98
|
+
}
|
99
|
+
}).ajaxComplete(function(e, request, settings) {
|
100
|
+
if (request.status.toString().charAt(0) == '3') {
|
101
|
+
var href = request.getResponseHeader('Location') || request.getResponseHeader('location');
|
102
|
+
// hackish way to determine if we have an array (depends on the fact that the real href must be longer than 1 char)
|
103
|
+
if (!href.charAt) href = href[0];
|
104
|
+
href = $.gadgeteer.expandUri(href);
|
105
|
+
var params = '';
|
106
|
+
if (settings.auth == 'signed' || !$.gadgeteer.options.dontAddOsParams) {
|
107
|
+
params = $.param($.gadgeteer.viewer.osParams()) + '&' + $.param($.gadgeteer.owner.osParams())
|
108
|
+
}
|
109
|
+
$.ajax({
|
110
|
+
url: href,
|
111
|
+
type: 'GET',
|
112
|
+
data: params,
|
113
|
+
dataType: 'html',
|
114
|
+
oauth: settings.auth,
|
115
|
+
target: settings.target
|
116
|
+
});
|
117
|
+
}
|
118
|
+
});
|
119
|
+
|
120
|
+
// Wait for everything to load then call the callback
|
121
|
+
setTimeout(function() {
|
122
|
+
if ($.gadgeteer.viewer && $.gadgeteer.owner && $.gadgeteer.data && $.gadgeteer.owner.data) {
|
123
|
+
// Navigate away if params tell so
|
124
|
+
var params = gadgets.views.getParams();
|
125
|
+
var navTo = params.navigateTo;
|
126
|
+
if (navTo) {
|
127
|
+
// Tell the callback that we're navigating away
|
128
|
+
callback(true);
|
129
|
+
$.gadgeteer.simpleRequest(navTo, {signed: params.signedNavigate});
|
130
|
+
} else {
|
131
|
+
callback();
|
132
|
+
}
|
133
|
+
} else {
|
134
|
+
setTimeout(arguments.callee, 50);
|
135
|
+
}
|
136
|
+
}, 50);
|
137
|
+
}
|
138
|
+
}
|
139
|
+
|
140
|
+
$.extend($.gadgeteer, {
|
141
|
+
loadingElem: function() {
|
142
|
+
if ($.gadgeteer.LOADING_ELEM) return $.gadgeteer.LOADING_ELEM;
|
143
|
+
|
144
|
+
var loading = $('#loading');
|
145
|
+
if (loading.length < 1) {
|
146
|
+
loading = $('<div id="loading">'+$.gadgeteer.options.loadingMessage+'</div>');
|
147
|
+
}
|
148
|
+
return $.gadgeteer.LOADING_ELEM = loading;
|
149
|
+
},
|
150
|
+
|
151
|
+
expandUri: function(uri, options) {
|
152
|
+
if (uri.charAt(0) == '/') uri = $.gadgeteer.host + uri;
|
153
|
+
if (!options) options = {};
|
154
|
+
if (!$.gadgeteer.options.dontExpand) {
|
155
|
+
if ($.gadgeteer.viewer) {
|
156
|
+
uri = uri.replace(/(?:(\/)|{)viewer(?:}|([\/\?#]|$))/g, '$1'+$.gadgeteer.viewer.backendId+'$2');
|
157
|
+
}
|
158
|
+
if ($.gadgeteer.owner) {
|
159
|
+
uri = uri.replace(/(?:(\/)|{)owner(?:}|([\/\?#]|$))/g, '$1'+$.gadgeteer.owner.backendId+'$2');
|
160
|
+
}
|
161
|
+
}
|
162
|
+
if (options.addParams) {
|
163
|
+
var params = $.param($.extend(false, $.gadgeteer.viewer.osParams(), $.gadgeteer.owner.osParams()));
|
164
|
+
uri += (uri.indexOf('?') != -1 ? '&' : '?') + params;
|
165
|
+
} else if (options.addProfileIds) {
|
166
|
+
var params = {};
|
167
|
+
if (uri.indexOf('os_viewer_id') == -1) params.os_viewer_id = $.gadgeteer.viewer.id;
|
168
|
+
if (uri.indexOf('os_owner_id') == -1) params.os_owner_id = $.gadgeteer.owner.id;
|
169
|
+
uri += (uri.indexOf('?') != -1 ? '&' : '?') + $.param(params);
|
170
|
+
}
|
171
|
+
return uri;
|
172
|
+
},
|
173
|
+
|
174
|
+
simpleRequest: function(href, options) {
|
175
|
+
var params = (options.data === undefined ? {} : options.data);
|
176
|
+
if (options === undefined) options = {};
|
177
|
+
if (options.addProfileIds) {
|
178
|
+
if (href.indexOf('os_viewer_id') == -1) params.os_viewer_id = $.gadgeteer.viewer.id;
|
179
|
+
if (href.indexOf('os_owner_id') == -1) params.os_owner_id = $.gadgeteer.owner.id;
|
180
|
+
}
|
181
|
+
if (options.signed) {
|
182
|
+
params = $.extend(false, params, $.gadgeteer.viewer.osParams(), $.gadgeteer.owner.osParams());
|
183
|
+
}
|
184
|
+
href = $.gadgeteer.expandUri(href);
|
185
|
+
options = $.extend(
|
186
|
+
{ // defaults
|
187
|
+
type: 'GET',
|
188
|
+
dataType: 'html'
|
189
|
+
}, options, { // force options
|
190
|
+
data: $.param(params),
|
191
|
+
url: href,
|
192
|
+
oauth: options.signed && 'signed',
|
193
|
+
target: options.target === undefined ? $($.gadgeteer.defaultTarget) : options.target
|
194
|
+
}
|
195
|
+
);
|
196
|
+
$.ajax(options);
|
197
|
+
},
|
198
|
+
|
199
|
+
regularRequest: function(e) {
|
200
|
+
// regular request (i.e. normal anchor click through) is a no-op
|
201
|
+
},
|
202
|
+
|
203
|
+
ajaxRequest: function(e) {
|
204
|
+
e.preventDefault();
|
205
|
+
var host = document.location.host;
|
206
|
+
var link = $(this);
|
207
|
+
var href = link.attr('href');
|
208
|
+
var _href = link[0].getAttribute('href');
|
209
|
+
|
210
|
+
//hack for IE href attr bug
|
211
|
+
if (_href.match(host)) {
|
212
|
+
var l = _href.search(host)+host.length;
|
213
|
+
href = _href.substring(l);
|
214
|
+
}
|
215
|
+
|
216
|
+
var params = {};
|
217
|
+
var method = link.hasClass('post') ? 'post' : link.hasClass('put') ? 'put' : link.hasClass('delete') ? 'delete' : 'get';
|
218
|
+
if (method != 'get') params._method = method;
|
219
|
+
if (link.hasClass('signed')) {
|
220
|
+
params = $.extend(false, params, $.gadgeteer.viewer.osParams(), $.gadgeteer.owner.osParams());
|
221
|
+
} else if (!$.gadgeteer.options.dontAddOsParams) {
|
222
|
+
params = $.extend(false, params, {os_viewer_id: $.gadgeteer.viewer.id, os_owner_id: $.gadgeteer.owner.id});
|
223
|
+
}
|
224
|
+
|
225
|
+
var target = link.hasClass('silent') ? null : $.gadgeteer.defaultTarget;
|
226
|
+
href = $.gadgeteer.expandUri(href);
|
227
|
+
$.ajax({
|
228
|
+
type: method == 'get' ? 'GET' : 'POST',
|
229
|
+
url: href,
|
230
|
+
data: params,
|
231
|
+
dataType: target ? 'html' : null,
|
232
|
+
oauth: link.hasClass('signed') ? 'signed' : null,
|
233
|
+
target: target
|
234
|
+
});
|
235
|
+
},
|
236
|
+
|
237
|
+
navigateRequest: function(view, params, ownerId, e) {
|
238
|
+
if (e !== undefined) {
|
239
|
+
e.preventDefault();
|
240
|
+
}
|
241
|
+
view = gadgets.views.getSupportedViews()[view];
|
242
|
+
gadgets.views.requestNavigateTo(view, params, ownerId);
|
243
|
+
},
|
244
|
+
|
245
|
+
handleLinkBehaviour: function(e) {
|
246
|
+
var link = $(this);
|
247
|
+
var matched = false;
|
248
|
+
$.each($.gadgeteer.linkBehaviours, function(behaviour, callback) {
|
249
|
+
var match;
|
250
|
+
if ($.isFunction(callback) && (match = callback.call(link, e))) {
|
251
|
+
var params = match === true ? [] : ($.isFunction(match.push) ? match : Array(match));
|
252
|
+
params.push(e);
|
253
|
+
//console.log('calling ', behaviour, ' link behaviour for ', link, ' with ', params);
|
254
|
+
var handler = behaviour+'Request';
|
255
|
+
handler = $.gadgeteer.linkBehaviours.handlers && $.gadgeteer.linkBehaviours.handlers[handler] || $.gadgeteer[handler];
|
256
|
+
handler.apply(link, params);
|
257
|
+
matched = true;
|
258
|
+
return false;
|
259
|
+
}
|
260
|
+
});
|
261
|
+
if (!matched) {
|
262
|
+
var def = $.gadgeteer.linkBehaviours.defaultBehavior || 'ajax';
|
263
|
+
//console.log('calling DEFAULT ', def, ' link behaviour for ', link, ' with ', e);
|
264
|
+
$.gadgeteer[def+'Request'].call(link, e);
|
265
|
+
}
|
266
|
+
},
|
267
|
+
|
268
|
+
appLink: function(parameters) {
|
269
|
+
return gadgets.views.bind(gadgets.config.get('views')['canvas'].urlTemplate, {
|
270
|
+
appId: document.location.host.match(/(\d+)\./)[1],
|
271
|
+
viewParams: encodeURIComponent(gadgets.json.stringify(parameters))
|
272
|
+
});
|
273
|
+
}
|
274
|
+
});
|
275
|
+
|
276
|
+
// Initialize gadgeteer
|
277
|
+
$(function() {
|
278
|
+
// Get information about the viewer and owner
|
279
|
+
var osd = opensocial.data.DataContext;
|
280
|
+
function finalizeData(person, data, fromosd) {
|
281
|
+
for (var id in data) {
|
282
|
+
data = data[id];
|
283
|
+
break;
|
284
|
+
}
|
285
|
+
if (fromosd) {
|
286
|
+
for (var key in data) {
|
287
|
+
data[key] = gadgets.json.parse(data[key]);
|
288
|
+
}
|
289
|
+
}
|
290
|
+
$.gadgeteer[person].data = function(key, value, cb) {
|
291
|
+
if (value === undefined) {
|
292
|
+
return data[key];
|
293
|
+
} else {
|
294
|
+
var oldValue = data[key];
|
295
|
+
data[key] = value;
|
296
|
+
var params = {};
|
297
|
+
params[key] = value;
|
298
|
+
var tries = 3;
|
299
|
+
(function() {
|
300
|
+
var callee = arguments.callee;
|
301
|
+
$.ajax({
|
302
|
+
type: 'POST', url: '/appdata/@'+person, data: params,
|
303
|
+
dataType: 'data', success: cb,
|
304
|
+
error: function(event, request, settings, thrownError) {
|
305
|
+
console.warn('error requesting appdata update (try #'+(3-tries+1)+')', event, request, settings, thrownError);
|
306
|
+
if (tries--) {
|
307
|
+
callee();
|
308
|
+
} else { // resetting old value
|
309
|
+
data[key] = oldValue;
|
310
|
+
cb(null, 'failure');
|
311
|
+
}
|
312
|
+
}
|
313
|
+
});
|
314
|
+
})();
|
315
|
+
return value;
|
316
|
+
}
|
317
|
+
};
|
318
|
+
if (person == 'viewer') {
|
319
|
+
$.gadgeteer.data = $.gadgeteer[person].data;
|
320
|
+
}
|
321
|
+
}
|
322
|
+
function finalizePerson(person) {
|
323
|
+
$.gadgeteer[person].osParams = function() {
|
324
|
+
var params = {};
|
325
|
+
for (var attr in $.gadgeteer[person]) {
|
326
|
+
if (!$.isFunction($.gadgeteer[person][attr])) {
|
327
|
+
var underscore = attr.replace(/([A-Z])/, '_$1').toLowerCase();
|
328
|
+
if (typeof $.gadgeteer[person][attr] == "object") {
|
329
|
+
for (subattr in $.gadgeteer[person][attr]) {
|
330
|
+
var subus = subattr.replace(/([A-Z])/, '_$1').toLowerCase();
|
331
|
+
params['os_'+person+'_'+underscore+'['+subus+']'] = $.gadgeteer[person][attr][subattr];
|
332
|
+
}
|
333
|
+
} else {
|
334
|
+
params['os_'+person+'_'+underscore] = $.gadgeteer[person][attr];
|
335
|
+
}
|
336
|
+
}
|
337
|
+
}
|
338
|
+
return params;
|
339
|
+
};
|
340
|
+
if (!$.gadgeteer.options.dontSwapDots) {
|
341
|
+
$.gadgeteer[person].backendId = $.gadgeteer[person].id.replace(/\./g, '-');
|
342
|
+
} else {
|
343
|
+
$.gadgeteer[person].backendId = $.gadgeteer[person].id;
|
344
|
+
}
|
345
|
+
var data;
|
346
|
+
if (osd && (data = osd.getDataSet(person+'Data'))) {
|
347
|
+
finalizeData(person, data, true);
|
348
|
+
} else {
|
349
|
+
$.getData('/appdata/@'+person, function(data, status) {
|
350
|
+
finalizeData(person, data);
|
351
|
+
});
|
352
|
+
}
|
353
|
+
}
|
354
|
+
function setupPerson(person) {
|
355
|
+
if (osd && ($.gadgeteer[person] = osd.getDataSet(person))) {
|
356
|
+
finalizePerson(person);
|
357
|
+
} else {
|
358
|
+
$.getData('/people/@'+person+'/@self', function(data, status) {
|
359
|
+
$.gadgeteer[person] = data[0];
|
360
|
+
finalizePerson(person);
|
361
|
+
});
|
362
|
+
}
|
363
|
+
}
|
364
|
+
setupPerson('viewer');
|
365
|
+
setupPerson('owner');
|
366
|
+
});
|
367
|
+
|
368
|
+
if (typeof $g == "undefined") {
|
369
|
+
$g = $.gadgeteer;
|
370
|
+
}
|
371
|
+
|
372
|
+
})(jQuery);
|
@@ -0,0 +1,226 @@
|
|
1
|
+
/*! Copyright (c) 2009 Brandon Aaron (http://brandonaaron.net)
|
2
|
+
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
|
3
|
+
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
|
4
|
+
*
|
5
|
+
* Version: 1.1.0-pre
|
6
|
+
* Requires jQuery 1.3+
|
7
|
+
* Docs: http://docs.jquery.com/Plugins/livequery
|
8
|
+
*/
|
9
|
+
|
10
|
+
(function($) {
|
11
|
+
|
12
|
+
$.extend($.fn, {
|
13
|
+
livequery: function(type, fn, fn2) {
|
14
|
+
var self = this, q;
|
15
|
+
|
16
|
+
// Handle different call patterns
|
17
|
+
if ($.isFunction(type))
|
18
|
+
fn2 = fn, fn = type, type = undefined;
|
19
|
+
|
20
|
+
// See if Live Query already exists
|
21
|
+
$.each( $.livequery.queries, function(i, query) {
|
22
|
+
if ( self.selector == query.selector && self.context == query.context &&
|
23
|
+
type == query.type && (!fn || fn.$lqguid == query.fn.$lqguid) && (!fn2 || fn2.$lqguid == query.fn2.$lqguid) )
|
24
|
+
// Found the query, exit the each loop
|
25
|
+
return (q = query) && false;
|
26
|
+
});
|
27
|
+
|
28
|
+
// Create new Live Query if it wasn't found
|
29
|
+
q = q || new $.livequery(this.selector, this.context, type, fn, fn2);
|
30
|
+
|
31
|
+
// Make sure it is running
|
32
|
+
q.stopped = false;
|
33
|
+
|
34
|
+
// Run it immediately for the first time
|
35
|
+
q.run();
|
36
|
+
|
37
|
+
// Contnue the chain
|
38
|
+
return this;
|
39
|
+
},
|
40
|
+
|
41
|
+
expire: function(type, fn, fn2) {
|
42
|
+
var self = this;
|
43
|
+
|
44
|
+
// Handle different call patterns
|
45
|
+
if ($.isFunction(type))
|
46
|
+
fn2 = fn, fn = type, type = undefined;
|
47
|
+
|
48
|
+
// Find the Live Query based on arguments and stop it
|
49
|
+
$.each( $.livequery.queries, function(i, query) {
|
50
|
+
if ( self.selector == query.selector && self.context == query.context &&
|
51
|
+
(!type || type == query.type) && (!fn || fn.$lqguid == query.fn.$lqguid) && (!fn2 || fn2.$lqguid == query.fn2.$lqguid) && !this.stopped )
|
52
|
+
$.livequery.stop(query.id);
|
53
|
+
});
|
54
|
+
|
55
|
+
// Continue the chain
|
56
|
+
return this;
|
57
|
+
}
|
58
|
+
});
|
59
|
+
|
60
|
+
$.livequery = function(selector, context, type, fn, fn2) {
|
61
|
+
this.selector = selector;
|
62
|
+
this.context = context;
|
63
|
+
this.type = type;
|
64
|
+
this.fn = fn;
|
65
|
+
this.fn2 = fn2;
|
66
|
+
this.elements = [];
|
67
|
+
this.stopped = false;
|
68
|
+
|
69
|
+
// The id is the index of the Live Query in $.livequery.queries
|
70
|
+
this.id = $.livequery.queries.push(this)-1;
|
71
|
+
|
72
|
+
// Mark the functions for matching later on
|
73
|
+
fn.$lqguid = fn.$lqguid || $.livequery.guid++;
|
74
|
+
if (fn2) fn2.$lqguid = fn2.$lqguid || $.livequery.guid++;
|
75
|
+
|
76
|
+
// Return the Live Query
|
77
|
+
return this;
|
78
|
+
};
|
79
|
+
|
80
|
+
$.livequery.prototype = {
|
81
|
+
stop: function() {
|
82
|
+
var query = this;
|
83
|
+
|
84
|
+
if ( this.type )
|
85
|
+
// Unbind all bound events
|
86
|
+
this.elements.unbind(this.type, this.fn);
|
87
|
+
else if (this.fn2)
|
88
|
+
// Call the second function for all matched elements
|
89
|
+
this.elements.each(function(i, el) {
|
90
|
+
query.fn2.apply(el);
|
91
|
+
});
|
92
|
+
|
93
|
+
// Clear out matched elements
|
94
|
+
this.elements = [];
|
95
|
+
|
96
|
+
// Stop the Live Query from running until restarted
|
97
|
+
this.stopped = true;
|
98
|
+
},
|
99
|
+
|
100
|
+
run: function() {
|
101
|
+
// Short-circuit if stopped
|
102
|
+
if ( this.stopped ) return;
|
103
|
+
var query = this;
|
104
|
+
|
105
|
+
var oEls = this.elements,
|
106
|
+
els = $(this.selector, this.context),
|
107
|
+
nEls = els.not(oEls);
|
108
|
+
|
109
|
+
// Set elements to the latest set of matched elements
|
110
|
+
this.elements = els;
|
111
|
+
|
112
|
+
if (this.type) {
|
113
|
+
// Bind events to newly matched elements
|
114
|
+
nEls.bind(this.type, this.fn);
|
115
|
+
|
116
|
+
// Unbind events to elements no longer matched
|
117
|
+
if (oEls.length > 0)
|
118
|
+
$.each(oEls, function(i, el) {
|
119
|
+
if ( $.inArray(el, els) < 0 )
|
120
|
+
$.event.remove(el, query.type, query.fn);
|
121
|
+
});
|
122
|
+
}
|
123
|
+
else {
|
124
|
+
// Call the first function for newly matched elements
|
125
|
+
nEls.each(function() {
|
126
|
+
query.fn.apply(this);
|
127
|
+
});
|
128
|
+
|
129
|
+
// Call the second function for elements no longer matched
|
130
|
+
if ( this.fn2 && oEls.length > 0 )
|
131
|
+
$.each(oEls, function(i, el) {
|
132
|
+
if ( $.inArray(el, els) < 0 )
|
133
|
+
query.fn2.apply(el);
|
134
|
+
});
|
135
|
+
}
|
136
|
+
}
|
137
|
+
};
|
138
|
+
|
139
|
+
$.extend($.livequery, {
|
140
|
+
guid: 0,
|
141
|
+
queries: [],
|
142
|
+
queue: [],
|
143
|
+
running: false,
|
144
|
+
timeout: null,
|
145
|
+
|
146
|
+
checkQueue: function() {
|
147
|
+
if ( $.livequery.running && $.livequery.queue.length ) {
|
148
|
+
var length = $.livequery.queue.length;
|
149
|
+
// Run each Live Query currently in the queue
|
150
|
+
while ( length-- )
|
151
|
+
$.livequery.queries[ $.livequery.queue.shift() ].run();
|
152
|
+
}
|
153
|
+
},
|
154
|
+
|
155
|
+
pause: function() {
|
156
|
+
// Don't run anymore Live Queries until restarted
|
157
|
+
$.livequery.running = false;
|
158
|
+
},
|
159
|
+
|
160
|
+
play: function() {
|
161
|
+
// Restart Live Queries
|
162
|
+
$.livequery.running = true;
|
163
|
+
// Request a run of the Live Queries
|
164
|
+
$.livequery.run();
|
165
|
+
},
|
166
|
+
|
167
|
+
registerPlugin: function() {
|
168
|
+
$.each( arguments, function(i,n) {
|
169
|
+
// Short-circuit if the method doesn't exist
|
170
|
+
if (!$.fn[n]) return;
|
171
|
+
|
172
|
+
// Save a reference to the original method
|
173
|
+
var old = $.fn[n];
|
174
|
+
|
175
|
+
// Create a new method
|
176
|
+
$.fn[n] = function() {
|
177
|
+
// Call the original method
|
178
|
+
var r = old.apply(this, arguments);
|
179
|
+
|
180
|
+
// Request a run of the Live Queries
|
181
|
+
$.livequery.run();
|
182
|
+
|
183
|
+
// Return the original methods result
|
184
|
+
return r;
|
185
|
+
}
|
186
|
+
});
|
187
|
+
},
|
188
|
+
|
189
|
+
run: function(id) {
|
190
|
+
if (id != undefined) {
|
191
|
+
// Put the particular Live Query in the queue if it doesn't already exist
|
192
|
+
if ( $.inArray(id, $.livequery.queue) < 0 )
|
193
|
+
$.livequery.queue.push( id );
|
194
|
+
}
|
195
|
+
else
|
196
|
+
// Put each Live Query in the queue if it doesn't already exist
|
197
|
+
$.each( $.livequery.queries, function(id) {
|
198
|
+
if ( $.inArray(id, $.livequery.queue) < 0 )
|
199
|
+
$.livequery.queue.push( id );
|
200
|
+
});
|
201
|
+
|
202
|
+
// Clear timeout if it already exists
|
203
|
+
if ($.livequery.timeout) clearTimeout($.livequery.timeout);
|
204
|
+
// Create a timeout to check the queue and actually run the Live Queries
|
205
|
+
$.livequery.timeout = setTimeout($.livequery.checkQueue, 20);
|
206
|
+
},
|
207
|
+
|
208
|
+
stop: function(id) {
|
209
|
+
if (id != undefined)
|
210
|
+
// Stop are particular Live Query
|
211
|
+
$.livequery.queries[ id ].stop();
|
212
|
+
else
|
213
|
+
// Stop all Live Queries
|
214
|
+
$.each( $.livequery.queries, function(id) {
|
215
|
+
$.livequery.queries[ id ].stop();
|
216
|
+
});
|
217
|
+
}
|
218
|
+
});
|
219
|
+
|
220
|
+
// Register core DOM manipulation methods
|
221
|
+
$.livequery.registerPlugin('append', 'prepend', 'after', 'before', 'wrap', 'attr', 'removeAttr', 'addClass', 'removeClass', 'toggleClass', 'empty', 'remove');
|
222
|
+
|
223
|
+
// Run Live Queries when the Document is ready
|
224
|
+
$(function() { $.livequery.play(); });
|
225
|
+
|
226
|
+
})(jQuery);
|