1/* globals JQClass */ 2/*! Simple JavaScript Inheritance 3 * By John Resig http://ejohn.org/ 4 * MIT Licensed. 5 */ 6// Inspired by base2 and Prototype 7(function(){ 8 'use strict'; 9 var initializing = false; 10 11 // The base JQClass implementation (does nothing) 12 window.JQClass = function(){}; 13 14 // Collection of derived classes 15 JQClass.classes = {}; 16 17 // Create a new JQClass that inherits from this class 18 JQClass.extend = function extender(prop) { 19 var base = this.prototype; 20 21 // Instantiate a base class (but only create the instance, don't run the init constructor) 22 initializing = true; 23 var prototype = new this(); 24 initializing = false; 25 26 // Copy the properties over onto the new prototype 27 for (var name in prop) { // jshint loopfunc:true 28 // Check if we're overwriting an existing function 29 if (typeof prop[name] === 'function' && typeof base[name] === 'function') { 30 prototype[name] = (function (name, fn) { 31 return function () { 32 var __super = this._super; 33 // Add a new ._super() method that is the same method but on the super-class 34 this._super = function (args) { 35 return base[name].apply(this, args || []); 36 }; 37 var ret = fn.apply(this, arguments); 38 // The method only needs to be bound temporarily, so we remove it when we're done executing 39 this._super = __super; 40 return ret; 41 }; 42 })(name, prop[name]); 43 // Check if we're overwriting existing default options. 44 } else if (typeof prop[name] === 'object' && typeof base[name] === 'object' && name === 'defaultOptions') { 45 var obj1 = base[name]; 46 var obj2 = prop[name]; 47 var obj3 = {}; 48 var key; 49 for (key in obj1) { // jshint forin:false 50 obj3[key] = obj1[key]; 51 } 52 for (key in obj2) { // jshint forin:false 53 obj3[key] = obj2[key]; 54 } 55 prototype[name] = obj3; 56 } else { 57 prototype[name] = prop[name]; 58 } 59 } 60 61 // The dummy class constructor 62 function JQClass() { 63 // All construction is actually done in the init method 64 if (!initializing && this._init) { 65 this._init.apply(this, arguments); 66 } 67 } 68 69 // Populate our constructed prototype object 70 JQClass.prototype = prototype; 71 72 // Enforce the constructor to be what we expect 73 JQClass.prototype.constructor = JQClass; 74 75 // And make this class extendable 76 JQClass.extend = extender; 77 78 return JQClass; 79 }; 80})(); 81/*! Abstract base class for collection plugins v1.0.2. 82 Written by Keith Wood (wood.keith{at}optusnet.com.au) December 2013. 83 Licensed under the MIT license (http://keith-wood.name/licence.html). */ 84(function($) { // Ensure $, encapsulate 85 'use strict'; 86 87 /** <p>Abstract base class for collection plugins v1.0.2.</p> 88 <p>Written by Keith Wood (wood.keith{at}optusnet.com.au) December 2013.</p> 89 <p>Licensed under the MIT license (http://keith-wood.name/licence.html).</p> 90 <p>Use {@link $.JQPlugin.createPlugin} to create new plugins using this framework.</p> 91 <p>This base class provides common functionality such as:</p> 92 <ul> 93 <li>Creates jQuery bridge - allowing you to invoke your plugin on a collection of elements.</li> 94 <li>Handles initialisation including reading settings from metadata - 95 an instance object is attached to the affected element(s) containing all the necessary data.</li> 96 <li>Handles option retrieval and update - options can be set through default values, 97 through inline metadata, or through instantiation settings.<br> 98 Metadata is specified as an attribute on the element: 99 <code>data-<pluginName>="<option name>: '<value>', ..."</code>. 100 Dates should be specified as strings in this format: <code>'new Date(y, m-1, d)'</code>.</li> 101 <li>Handles method calling - inner functions starting with '_'are inaccessible, 102 whereas others can be called via <code>$(selector).pluginName('functionName')</code>.</li> 103 <li>Handles plugin destruction - removing all trace of the plugin.</li> 104 </ul> 105 @module JQPlugin 106 @abstract */ 107 JQClass.classes.JQPlugin = JQClass.extend({ 108 109 /** Name to identify this plugin. 110 @example name: 'tabs' */ 111 name: 'plugin', 112 113 /** Default options for instances of this plugin (default: {}). 114 @example defaultOptions: { 115 selectedClass: 'selected', 116 triggers: 'click' 117} */ 118 defaultOptions: {}, 119 120 /** Options dependent on the locale. 121 Indexed by language and (optional) country code, with '' denoting the default language (English/US). 122 Normally additional languages would be provided as separate files to all them to be included as needed. 123 @example regionalOptions: { 124 '': { 125 greeting: 'Hi' 126 } 127} */ 128 regionalOptions: {}, 129 130 /** Whether or not a deep merge should be performed when accumulating options. 131 The default is <code>true</code> but can be overridden in a sub-class. */ 132 deepMerge: true, 133 134 /** Retrieve a marker class for affected elements. 135 In the format: <code>is-<pluginName></code>. 136 @protected 137 @return {string} The marker class. */ 138 _getMarker: function() { 139 return 'is-' + this.name; 140 }, 141 142 /** Initialise the plugin. 143 Create the jQuery bridge - plugin name <code>xyz</code> 144 produces singleton <code>$.xyz</code> and collection function <code>$.fn.xyz</code>. 145 @protected */ 146 _init: function() { 147 // Apply default localisations 148 $.extend(this.defaultOptions, (this.regionalOptions && this.regionalOptions['']) || {}); 149 // Camel-case the name 150 var jqName = camelCase(this.name); 151 // Expose jQuery singleton manager 152 $[jqName] = this; 153 // Expose jQuery collection plugin 154 $.fn[jqName] = function(options) { 155 var otherArgs = Array.prototype.slice.call(arguments, 1); 156 var inst = this; 157 var returnValue = this; 158 this.each(function () { 159 if (typeof options === 'string') { 160 if (options[0] === '_' || !$[jqName][options]) { 161 throw 'Unknown method: ' + options; 162 } 163 var methodValue = $[jqName][options].apply($[jqName], [this].concat(otherArgs)); 164 if (methodValue !== inst && methodValue !== undefined) { 165 returnValue = methodValue; 166 return false; 167 } 168 } else { 169 $[jqName]._attach(this, options); 170 } 171 }); 172 return returnValue; 173 }; 174 }, 175 176 /** Set default options for all subsequent instances. 177 @param {object} options The new default options. 178 @example $.pluginName.setDefaults({name: value, ...}) */ 179 setDefaults: function(options) { 180 $.extend(this.defaultOptions, options || {}); 181 }, 182 183 /** Initialise an element. Called internally only. 184 Adds an instance object as data named for the plugin. 185 Override {@linkcode module:JQPlugin~_postAttach|_postAttach} for plugin-specific processing. 186 @private 187 @param {Element} elem The element to enhance. 188 @param {object} options Overriding settings. */ 189 _attach: function(elem, options) { 190 elem = $(elem); 191 if (elem.hasClass(this._getMarker())) { 192 return; 193 } 194 elem.addClass(this._getMarker()); 195 options = $.extend(this.deepMerge, {}, this.defaultOptions, this._getMetadata(elem), options || {}); 196 var inst = $.extend({name: this.name, elem: elem, options: options}, this._instSettings(elem, options)); 197 elem.data(this.name, inst); // Save instance against element 198 this._postAttach(elem, inst); 199 this.option(elem, options); 200 }, 201 202 /** Retrieve additional instance settings. 203 Override this in a sub-class to provide extra settings. 204 These are added directly to the instance object. 205 Default attributes of an instance object are shown as properties below: 206 @protected 207 @param {jQuery} elem The current jQuery element. 208 @param {object} options The instance options. 209 @return {object} Any extra instance values. 210 @property {Element} elem The element to which this instance applies. 211 @property {string} name The name of this plugin. 212 @property {object} options The accumulated options for this instance. 213 @example _instSettings: function(elem, options) { 214 return {nav: elem.find(options.navSelector)}; 215} */ 216 _instSettings: function(elem, options) { // jshint unused:false 217 return {}; 218 }, 219 220 /** Plugin specific post initialisation. 221 Override this in a sub-class to perform extra activities. 222 This is where you would implement your plugin's main functionality. 223 @protected 224 @param {jQuery} elem The current jQuery element. 225 @param {object} inst The instance settings. 226 @example _postAttach: function(elem, inst) { 227 elem.on('click.' + this.name, function() { 228 ... 229 }); 230} */ 231 _postAttach: function(elem, inst) { // jshint unused:false 232 }, 233 234 /** Retrieve metadata configuration from the element. 235 Metadata is specified as an attribute: 236 <code>data-<pluginName>="<option name>: '<value>', ..."</code>. 237 Dates should be specified as strings in this format: <code>'new Date(y, m-1, d)'</code>. 238 @private 239 @param {jQuery} elem The source element. 240 @return {object} The inline configuration or {}. */ 241 _getMetadata: function(elem) { 242 try { 243 var data = elem.data(this.name.toLowerCase()) || ''; 244 data = data.replace(/(\\?)'/g, function(e, t) { 245 return t ? '\'' : '"'; 246 }).replace(/([a-zA-Z0-9]+):/g, function(match, group, i) { 247 var count = data.substring(0, i).match(/"/g); // Handle embedded ':' 248 return (!count || count.length % 2 === 0 ? '"' + group + '":' : group + ':'); 249 }).replace(/\\:/g, ':'); 250 data = $.parseJSON('{' + data + '}'); 251 for (var key in data) { 252 if (data.hasOwnProperty(key)) { 253 var value = data[key]; 254 if (typeof value === 'string' && value.match(/^new Date\(([-0-9,\s]*)\)$/)) { // Convert dates 255 data[key] = eval(value); // jshint ignore:line 256 } 257 } 258 } 259 return data; 260 } 261 catch (e) { 262 return {}; 263 } 264 }, 265 266 /** Retrieve the instance data for element. 267 @protected 268 @param {Element} elem The source element. 269 @return {object} The instance data or <code>{}</code> if none. */ 270 _getInst: function(elem) { 271 return $(elem).data(this.name) || {}; 272 }, 273 274 /** Retrieve or reconfigure the settings for a plugin. 275 If new settings are provided they are applied to the instance options. 276 If an option name only is provided the value of that option is returned. 277 If no name or value is provided, all options are returned. 278 Override {@linkcode module:JQPlugin~_optionsChanged|_optionsChanged} 279 for plugin-specific processing when option values change. 280 @param {Element} elem The source element. 281 @param {object|string} [name] The collection of new option values or the name of a single option. 282 @param {any} [value] The value for a single named option. 283 @return {any|object} If retrieving a single value or all options. 284 @example $(selector).plugin('option', 'name', value) // Set one option
285$(selector).plugin('option', {name: value, ...}) // Set multiple options 286var value = $(selector).plugin('option', 'name') // Get one option 287var options = $(selector).plugin('option') // Get all options */ 288 option: function(elem, name, value) { 289 elem = $(elem); 290 var inst = elem.data(this.name); 291 var options = name || {}; 292 if (!name || (typeof name === 'string' && typeof value === 'undefined')) { 293 options = (inst || {}).options; 294 return (options && name ? options[name] : options); 295 } 296 if (!elem.hasClass(this._getMarker())) { 297 return; 298 } 299 if (typeof name === 'string') { 300 options = {}; 301 options[name] = value; 302 } 303 this._optionsChanged(elem, inst, options); 304 $.extend(inst.options, options); 305 }, 306 307 /** Plugin specific options processing. 308 Old value available in <code>inst.options[name]</code>, new value in <code>options[name]</code>. 309 Override this in a sub-class to perform extra activities. 310 @protected 311 @param {jQuery} elem The current jQuery element. 312 @param {object} inst The instance settings. 313 @param {object} options The new options. 314 @example _optionsChanged: function(elem, inst, options) { 315 if (options.name != inst.options.name) { 316 elem.removeClass(inst.options.name).addClass(options.name); 317 } 318} */ 319 _optionsChanged: function(elem, inst, options) { // jshint unused:false 320 }, 321 322 /** Remove all trace of the plugin. 323 Override {@linkcode module:JQPlugin~_preDestroy|_preDestroy} for plugin-specific processing. 324 @param {Element} elem The source element. 325 @example $(selector).plugin('destroy') */ 326 destroy: function(elem) { 327 elem = $(elem); 328 if (!elem.hasClass(this._getMarker())) { 329 return; 330 } 331 this._preDestroy(elem, this._getInst(elem)); 332 elem.removeData(this.name).removeClass(this._getMarker()); 333 }, 334 335 /** Plugin specific pre destruction. 336 It is invoked as part of the {@linkcode module:JQPlugin~destroy|destroy} processing. 337 Override this in a sub-class to perform extra activities and undo everything that was 338 done in the {@linkcode module:JQPlugin~_postAttach|_postAttach} or 339 {@linkcode module:JQPlugin~_optionsChanged|_optionsChanged} functions. 340 @protected 341 @param {jQuery} elem The current jQuery element. 342 @param {object} inst The instance settings. 343 @example _preDestroy: function(elem, inst) { 344 elem.off('.' + this.name); 345} */ 346 _preDestroy: function(elem, inst) { // jshint unused:false 347 } 348 }); 349 350 /** Convert names from hyphenated to camel-case. 351 @private 352 @param {string} value The original hyphenated name. 353 @return {string} The camel-case version. */ 354 function camelCase(name) { 355 return name.replace(/-([a-z])/g, function(match, group) { 356 return group.toUpperCase(); 357 }); 358 } 359 360 /** Expose the plugin base. 361 @namespace $.JQPlugin */ 362 $.JQPlugin = { 363 364 /** Create a new collection plugin. 365 @memberof $.JQPlugin 366 @param {string} [superClass='JQPlugin'] The name of the parent class to inherit from. 367 @param {object} overrides The property/function overrides for the new class. 368 See {@link module:JQPlugin|JQPlugin} for the base functionality. 369 @example $.JQPlugin.createPlugin({ // Define the plugin 370 name: 'tabs', 371 defaultOptions: {selectedClass: 'selected'}, 372 _initSettings: function(elem, options) { return {...}; }, 373 _postAttach: function(elem, inst) { ... } 374}); 375$('selector').tabs(); // And instantiate it */ 376 createPlugin: function(superClass, overrides) { 377 if (typeof superClass === 'object') { 378 overrides = superClass; 379 superClass = 'JQPlugin'; 380 } 381 superClass = camelCase(superClass); 382 var className = camelCase(overrides.name); 383 JQClass.classes[className] = JQClass.classes[superClass].extend(overrides); 384 new JQClass.classes[className](); // jshint ignore:line 385 } 386 }; 387 388})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.