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 (https://github.com/jquery/jquery/blob/master/MIT-LICENSE.txt) 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} 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 - z A - Z 0 - 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 ( / ^ n e w D a t e \( ( .* ) \) $ / ) ) {
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 ) ;
0 commit comments