1/* Simple JavaScript Inheritance 2 * By John Resig http://ejohn.org/ 3 * MIT Licensed. 4 */ 5// Inspired by base2 and Prototype 6(function(){ 7 var initializing = false; 8 9 // The base JQClass implementation (does nothing) 10 window.JQClass = function(){}; 11 12 // Collection of derived classes 13 JQClass.classes = {}; 14 15 // Create a new JQClass that inherits from this class 16 JQClass.extend = function extender(prop) { 17 var base = this.prototype; 18 19 // Instantiate a base class (but only create the instance, 20 // don't run the init constructor) 21 initializing = true; 22 var prototype = new this(); 23 initializing = false; 24 25 // Copy the properties over onto the new prototype 26 for (var name in prop) { 27 // Check if we're overwriting an existing function 28 prototype[name] = typeof prop[name] == 'function' && 29 typeof base[name] == 'function' ? 30 (function(name, fn){ 31 return function() { 32 var __super = this._super; 33 34 // Add a new ._super() method that is the same method 35 // but on the super-class 36 this._super = function(args) { 37 return base[name].apply(this, args || []); 38 }; 39 40 var ret = fn.apply(this, arguments); 41 42 // The method only need to be bound temporarily, so we 43 // remove it when we're done executing 44 this._super = __super; 45 46 return ret; 47 }; 48 })(name, prop[name]) : 49 prop[name]; 50 } 51 52 // The dummy class constructor 53 function JQClass() { 54 // All construction is actually done in the init method 55 if (!initializing && this._init) { 56 this._init.apply(this, arguments); 57 } 58 } 59 60 // Populate our constructed prototype object 61 JQClass.prototype = prototype; 62 63 // Enforce the constructor to be what we expect 64 JQClass.prototype.constructor = JQClass; 65 66 // And make this class extendable 67 JQClass.extend = extender; 68 69 return JQClass; 70 }; 71})(); 72 73(function($) { // Ensure $, encapsulate 74 75 /** Abstract base class for collection plugins v1.0.1. 76 Written by Keith Wood (kbwood{at}iinet.com.au) December 2013. 77 Licensed under the MIT (http://keith-wood.name/licence.html) license. 78 @module $.JQPlugin 79 @abstract */ 80 JQClass.classes.JQPlugin = JQClass.extend({ 81 82 /** Name to identify this plugin. 83 @example name: 'tabs' */ 84 name: 'plugin', 85 86 /** Default options for instances of this plugin (default: {}). 87 @example defaultOptions: { 88 selectedClass: 'selected', 89 triggers: 'click' 90 } */ 91 defaultOptions: {}, 92 93 /** Options dependent on the locale. 94 Indexed by language and (optional) country code, with '' denoting the default language (English/US). 95 @example regionalOptions: { 96 '': { 97 greeting: 'Hi' 98 } 99 } */ 100 regionalOptions: {}, 101 102 /** Names of getter methods - those that can't be chained (default: []). 103 @example _getters: ['activeTab'] */ 104 _getters: [], 105 106 /** Retrieve a marker class for affected elements. 107 @private 108 @return {string} The marker class. */ 109 _getMarker: function() { 110 return 'is-' + this.name; 111 }, 112 113 /** Initialise the plugin. 114 Create the jQuery bridge - plugin name <code>xyz</code> 115 produces <code>$.xyz</code> and <code>$.fn.xyz</code>. */ 116 _init: function() { 117 // Apply default localisations 118 $.extend(this.defaultOptions, (this.regionalOptions && this.regionalOptions['']) || {}); 119 // Camel-case the name 120 var jqName = camelCase(this.name); 121 // Expose jQuery singleton manager 122 $[jqName] = this; 123 // Expose jQuery collection plugin 124 $.fn[jqName] = function(options) { 125 var otherArgs = Array.prototype.slice.call(arguments, 1); 126 if ($[jqName]._isNotChained(options, otherArgs)) { 127 return $[jqName][options].apply($[jqName], [this[0]].concat(otherArgs)); 128 } 129 return this.each(function() { 130 if (typeof options === 'string') { 131 if (options[0] === '_' || !$[jqName][options]) { 132 throw 'Unknown method: ' + options; 133 } 134 $[jqName][options].apply($[jqName], [this].concat(otherArgs)); 135 } 136 else { 137 $[jqName]._attach(this, options); 138 } 139 }); 140 }; 141 }, 142 143 /** Set default values for all subsequent instances. 144 @param options {object} The new default options. 145 @example $.plugin.setDefauls({name: value}) */ 146 setDefaults: function(options) { 147 $.extend(this.defaultOptions, options || {}); 148 }, 149 150 /** Determine whether a method is a getter and doesn't permit chaining. 151 @private 152 @param name {string}
152 The method name. 153 @param otherArgs {any[]} Any other arguments for the method. 154 @return {boolean} True if this method is a getter, false otherwise. */ 155 _isNotChained: function(name, otherArgs) { 156 if (name === 'option' && (otherArgs.length === 0 || 157 (otherArgs.length === 1 && typeof otherArgs[0] === 'string'))) { 158 return true; 159 } 160 return $.inArray(name, this._getters) > -1; 161 }, 162 163 /** Initialise an element. Called internally only. 164 Adds an instance object as data named for the plugin. 165 @param elem {Element} The element to enhance. 166 @param options {object} Overriding settings. */ 167 _attach: function(elem, options) { 168 elem = $(elem); 169 if (elem.hasClass(this._getMarker())) { 170 return; 171 } 172 elem.addClass(this._getMarker()); 173 options = $.extend({}, this.defaultOptions, this._getMetadata(elem), options || {}); 174 var inst = $.extend({name: this.name, elem: elem, options: options}, 175 this._instSettings(elem, options)); 176 elem.data(this.name, inst); // Save instance against element 177 this._postAttach(elem, inst); 178 this.option(elem, options); 179 }, 180 181 /** Retrieve additional instance settings. 182 Override this in a sub-class to provide extra settings. 183 @param elem {jQuery} The current jQuery element. 184 @param options {object} The instance options. 185 @return {object} Any extra instance values. 186 @example _instSettings: function(elem, options) { 187 return {nav: elem.find(options.navSelector)}; 188 } */ 189 _instSettings: function(elem, options) { 190 return {}; 191 }, 192 193 /** Plugin specific post initialisation. 194 Override this in a sub-class to perform extra activities. 195 @param elem {jQuery} The current jQuery element. 196 @param inst {object} The instance settings. 197 @example _postAttach: function(elem, inst) { 198 elem.on('click.' + this.name, function() { 199 ... 200 }); 201 } */ 202 _postAttach: function(elem, inst) { 203 }, 204 205 /** Retrieve metadata configuration from the element. 206 Metadata is specified as an attribute: 207 <code>data-<plugin name>="<setting name>: '<value>', ..."</code>. 208 Dates should be specified as strings in this format: 'new Date(y, m-1, d)'. 209 @private 210 @param elem {jQuery} The source element. 211 @return {object} The inline configuration or {}. */ 212 _getMetadata: function(elem) { 213 try { 214 var data = elem.data(this.name.toLowerCase()) || ''; 215 data = data.replace(/'/g, '"'); 216 data = data.replace(/([a-zA-Z0-9]+):/g, function(match, group, i) { 217 var count = data.substring(0, i).match(/"/g); // Handle embedded ':' 218 return (!count || count.length % 2 === 0 ? '"' + group + '":' : group + ':'); 219 }); 220 data = $.parseJSON('{' + data + '}'); 221 for (var name in data) { // Convert dates 222 var value = data[name]; 223 if (typeof value === 'string' && value.match(/^new Date\((.*)\)$/)) { 224 data[name] = eval(value); 225 } 226 } 227 return data; 228 } 229 catch (e) { 230 return {}; 231 } 232 }, 233 234 /** Retrieve the instance data for element. 235 @param elem {Element} The source element. 236 @return {object} The instance data or {}. */ 237 _getInst: function(elem) { 238 return $(elem).data(this.name) || {}; 239 }, 240 241 /** Retrieve or reconfigure the settings for a plugin. 242 @param elem {Element} The source element. 243 @param name {object|string} The collection of new option values or the name of a single option. 244 @param [value] {any} The value for a single named option. 245 @return {any|object} If retrieving a single value or all options. 246 @example $(selector).plugin('option', 'name', value) 247 $(selector).plugin('option', {name: value, ...}) 248 var value = $(selector).plugin('option', 'name') 249 var options = $(selector).plugin('option') */ 250 option: function(elem, name, value) { 251 elem = $(elem); 252 var inst = elem.data(this.name); 253 if (!name || (typeof name === 'string' && value == null)) { 254 var options = (inst || {}).options; 255 return (options && name ? options[name] : options); 256 } 257 if (!elem.hasClass(this._getMarker())) { 258 return; 259 } 260 var options = name || {}; 261 if (typeof name === 'string') { 262 options = {}; 263 options[name] = value; 264 } 265 this._optionsChanged(elem, inst, options); 266 $.extend(inst.options, options); 267 }, 268 269 /** Plugin specific options processing. 270 Old value available in <code>inst.options[name]</code>, new value in <code>options[name]</code>. 271 Override this in a sub-class to perform extra activities. 272 @param elem {jQuery} The current jQuery element. 273 @param inst {object} The instance settings. 274 @param options {object} The new options. 275 @example _optionsChanged: function(elem, inst, options) { 276 if (options.name != inst.options.name) { 277 elem.removeClass(inst.options.name).addClass(options.name); 278 } 279 } */ 280 _optionsChanged: function(elem, inst, options) { 281 }, 282 283 /** Remove all trace of the plugin. 284 Override <code>_preDestroy</code> for plugin-specific processing. 285 @param elem {Element} The source element. 286 @example $(selector).plugin('destroy') */ 287 destroy: function(elem) { 288 elem = $(elem); 289 if (!elem.hasClass(this._getMarker())) { 290 return; 291 } 292 this._preDestroy(elem, this._getInst(elem)); 293 elem.removeData(this.name).removeClass(this._getMarker()); 294 }, 295 296 /** Plugin specific pre destruction. 297 Override this in a sub-class to perform extra activities and undo everything that was 298 done in the <code>_postAttach</code> or <code>_optionsChanged</code> functions. 299 @param elem {jQuery} The current jQuery element. 300 @param inst {object} The instance settings. 301 @example _preDestroy: function(elem, inst) { 302 elem.off('.' + this.name); 303 } */ 304 _preDestroy: function(elem, inst) { 305 } 306 }); 307 308 /** Convert names from hyphenated to camel-case. 309 @private 310 @param value {string} The original hyphenated name. 311 @return {string} The camel-case version. */ 312 function camelCase(name) { 313 return name.replace(/-([a-z])/g, function(match, group) { 314 return group.toUpperCase(); 315 }); 316 } 317 318 /** Expose the plugin base. 319 @namespace "$.JQPlugin" */ 320 $.JQPlugin = { 321 322 /** Create a new collection plugin. 323 @memberof "$.JQPlugin"
324 @param [superClass='JQPlugin'] {string} The name of the parent class to inherit from. 325 @param overrides {object} The property/function overrides for the new class. 326 @example $.JQPlugin.createPlugin({ 327 name: 'tabs', 328 defaultOptions: {selectedClass: 'selected'}, 329 _initSettings: function(elem, options) { return {...}; }, 330 _postAttach: function(elem, inst) { ... } 331 }); */ 332 createPlugin: function(superClass, overrides) { 333 if (typeof superClass === 'object') { 334 overrides = superClass; 335 superClass = 'JQPlugin'; 336 } 337 superClass = camelCase(superClass); 338 var className = camelCase(overrides.name); 339 JQClass.classes[className] = JQClass.classes[superClass].extend(overrides); 340 new JQClass.classes[className](); 341 } 342 }; 343 344})(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.