2 // http://alexsexton.com/blog/2010/02/using-inheritance-patterns-to-organize-large-jquery-applications/
3 // We will use John Resig's proposal
5 // http://pastie.org/517177
7 // NOTE: missing a destroy function
9 $.plugin = function(name, object) {
10 $.fn[name] = function(options) {
11 var args = Array.prototype.slice.call(arguments, 1);
12 return this.each(function() {
13 var instance = $.data(this, name);
15 instance[options].apply(instance, args);
17 instance = $.data(this, name, new object(options, this));
23 var Plugin = Class.extend({
25 init: function(options, element) {
26 // Mix in the passed in options with the default options
27 this.options = $.extend({}, this.default_options, options);
29 // Save the element reference, both as a jQuery
30 // reference and a normal reference
31 this.element = element;
32 this.$element = $(element);
34 // return this so we can chain/use the bridge with less code.
38 has_query_handler: function() {
39 return (typeof this.on_filter_added === 'function');
42 _query_handler: function(prefix, event_type, data) {
43 // We suppose this.query_handler_prefix has been defined if this
44 // callback is triggered
51 fn = 'filter_removed';
69 fn = 'on_' + prefix + fn;
70 if (typeof this[fn] === 'function') {
71 // call with data as parameter
72 // XXX implement anti loop
77 _record_handler: function(prefix, event_type, record) {
78 // We suppose this.query_handler_prefix has been defined if this
79 // callback is triggered
89 fn = 'query_in_progress';
94 case FIELD_STATE_CHANGED:
95 fn = 'field_state_changed';
101 fn = 'on_' + prefix + fn;
102 if (typeof this[fn] === 'function') {
103 // call with data as parameter
104 // XXX implement anti loop
109 get_handler_function: function(type, prefix) {
111 return $.proxy(function(e, event_type, record) {
112 return this['_' + type + '_handler'](prefix, event_type, record);
116 listen_query: function(query_uuid, prefix) {
117 // default: prefix = ''
118 prefix = (typeof prefix === 'undefined') ? '' : (prefix + '_');
120 this.$element.on(manifold.get_channel('query', query_uuid), this.get_handler_function('query', prefix));
121 this.$element.on(manifold.get_channel('record', query_uuid), this.get_handler_function('record', prefix));
126 /* Helper functions for naming HTML elements (ID, classes), with support for filters and fields */
129 var ret = this.options.plugin_uuid;
130 for (var i = 0; i < arguments.length; i++) {
131 ret = ret + manifold.separator + arguments[i];
137 if (arguments.length == 0) {
138 return $('#' + this.id());
140 // We make sure to search _inside_ the dom tag of the plugin
141 return $('#' + this.id.apply(this, arguments), this.elmt());
145 elts: function(cls) {
146 return $('.' + cls, this.elmt());
149 id_from_filter: function(filter, use_value) {
150 use_value = typeof use_value !== 'undefined' ? use_value : true;
154 var value = filter[2];
155 var op_str = this.getOperatorLabel(op);
156 var s = manifold.separator;
159 return 'filter' + s + key + s + op_str + s + value;
161 return 'filter' + s + key + s + op_str;
165 str_from_filter: function(filter) {
166 return filter[0] + ' ' + filter[1] + ' ' + filter[2];
169 array_from_id: function(id) {
170 var ret = id.split(manifold.separator);
171 ret.shift(); // remove plugin_uuid at the beginning
175 id_from_field: function(field) {
176 return 'field' + manifold.separator + field;
179 field_from_id: function(id) {
181 if (typeof id === 'string') {
182 array = id.split(manifold.separator);
183 } else { // We suppose we have an array ('object')
186 // array = ['field', FIELD_NAME]
190 id_from_key: function(key_field, value) {
192 return key_field + manifold.separator + this.escape_id(value).replace(/\\/g, '');
195 // we do not need to carry around all the nonsense about backslashing dots in hrns
196 // likewise, DOM ids do not like to have dots in them
197 // because "#foo.bar" matches an elem named foo with class bar - not an id that is foo.bar
198 // so this method gives you a valid DOMID but that cannot be 'reversed' back to retrieve an hrn or the like
200 // input=input="ple.aluiple.host147-82-static\\.93-94-b\\.business\\.telecomitalia\\.it"
201 // > "ple.aluiple.host147-82-static\.93-94-b\.business\.telecomitalia\.it"
203 // "ple-aluiple-host147-82-static-93-94-b-business-telecomitalia-it"
204 flat_id : function (id_in) {
205 return id_in.replace(/\\\./g,"-").replace(/\\/g,"-").replace(/\./g,"-");
208 // escape (read: backslashes) some meta-chars in input
209 escape_id: function(id) {
210 if( id !== undefined){
211 return id.replace( /(:|\.|\[|\])/g, "\\$1" );
213 return "undefined-id";
217 id_from_record: function(method, record) {
218 var keys = manifold.metadata.get_key(method);
225 switch (Object.toType(key)) {
227 if (!(key in record))
229 return this.id_from_key(key, record[key]);
232 throw 'Not implemented';
236 key_from_id: function(id) {
237 // NOTE this works only for simple keys
240 if (typeof id === 'string') {
241 array = id.split(manifold.separator);
242 } else { // We suppose we have an array ('object')
246 // arguments has the initial id but lacks the key field name (see id_from_key), so we are even
247 // we finally add +1 for the plugin_uuid at the beginning
248 return array[arguments.length + 1];
252 // plugin-helper.js is about managing toggled state
253 // it would be beneficial to merge it in here
254 toggle_on: function () { return this.toggle("true"); },
255 toggle_off: function () { return this.toggle("false"); },
256 toggle: function (status) {
257 plugin_helper.set_toggle_status (this.options.plugin_uuid,status);
263 manifold.spin(this.element);
267 manifold.spin(this.element, false);
272 load_template: function(name, ctx) {
273 return Mustache.render(this.elmt(name).html(), ctx);