/[projects]/misc/horsensspejder-web/jquery/jquery-ui-1.10.3/ui/jquery.ui.spinner.js
ViewVC logotype

Annotation of /misc/horsensspejder-web/jquery/jquery-ui-1.10.3/ui/jquery.ui.spinner.js

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2125 - (hide annotations) (download) (as text)
Wed Mar 12 19:30:05 2014 UTC (10 years, 4 months ago) by torben
File MIME type: application/javascript
File size: 12377 byte(s)
initial import
1 torben 2125 /*!
2     * jQuery UI Spinner 1.10.3
3     * http://jqueryui.com
4     *
5     * Copyright 2013 jQuery Foundation and other contributors
6     * Released under the MIT license.
7     * http://jquery.org/license
8     *
9     * http://api.jqueryui.com/spinner/
10     *
11     * Depends:
12     * jquery.ui.core.js
13     * jquery.ui.widget.js
14     * jquery.ui.button.js
15     */
16     (function( $ ) {
17    
18     function modifier( fn ) {
19     return function() {
20     var previous = this.element.val();
21     fn.apply( this, arguments );
22     this._refresh();
23     if ( previous !== this.element.val() ) {
24     this._trigger( "change" );
25     }
26     };
27     }
28    
29     $.widget( "ui.spinner", {
30     version: "1.10.3",
31     defaultElement: "<input>",
32     widgetEventPrefix: "spin",
33     options: {
34     culture: null,
35     icons: {
36     down: "ui-icon-triangle-1-s",
37     up: "ui-icon-triangle-1-n"
38     },
39     incremental: true,
40     max: null,
41     min: null,
42     numberFormat: null,
43     page: 10,
44     step: 1,
45    
46     change: null,
47     spin: null,
48     start: null,
49     stop: null
50     },
51    
52     _create: function() {
53     // handle string values that need to be parsed
54     this._setOption( "max", this.options.max );
55     this._setOption( "min", this.options.min );
56     this._setOption( "step", this.options.step );
57    
58     // format the value, but don't constrain
59     this._value( this.element.val(), true );
60    
61     this._draw();
62     this._on( this._events );
63     this._refresh();
64    
65     // turning off autocomplete prevents the browser from remembering the
66     // value when navigating through history, so we re-enable autocomplete
67     // if the page is unloaded before the widget is destroyed. #7790
68     this._on( this.window, {
69     beforeunload: function() {
70     this.element.removeAttr( "autocomplete" );
71     }
72     });
73     },
74    
75     _getCreateOptions: function() {
76     var options = {},
77     element = this.element;
78    
79     $.each( [ "min", "max", "step" ], function( i, option ) {
80     var value = element.attr( option );
81     if ( value !== undefined && value.length ) {
82     options[ option ] = value;
83     }
84     });
85    
86     return options;
87     },
88    
89     _events: {
90     keydown: function( event ) {
91     if ( this._start( event ) && this._keydown( event ) ) {
92     event.preventDefault();
93     }
94     },
95     keyup: "_stop",
96     focus: function() {
97     this.previous = this.element.val();
98     },
99     blur: function( event ) {
100     if ( this.cancelBlur ) {
101     delete this.cancelBlur;
102     return;
103     }
104    
105     this._stop();
106     this._refresh();
107     if ( this.previous !== this.element.val() ) {
108     this._trigger( "change", event );
109     }
110     },
111     mousewheel: function( event, delta ) {
112     if ( !delta ) {
113     return;
114     }
115     if ( !this.spinning && !this._start( event ) ) {
116     return false;
117     }
118    
119     this._spin( (delta > 0 ? 1 : -1) * this.options.step, event );
120     clearTimeout( this.mousewheelTimer );
121     this.mousewheelTimer = this._delay(function() {
122     if ( this.spinning ) {
123     this._stop( event );
124     }
125     }, 100 );
126     event.preventDefault();
127     },
128     "mousedown .ui-spinner-button": function( event ) {
129     var previous;
130    
131     // We never want the buttons to have focus; whenever the user is
132     // interacting with the spinner, the focus should be on the input.
133     // If the input is focused then this.previous is properly set from
134     // when the input first received focus. If the input is not focused
135     // then we need to set this.previous based on the value before spinning.
136     previous = this.element[0] === this.document[0].activeElement ?
137     this.previous : this.element.val();
138     function checkFocus() {
139     var isActive = this.element[0] === this.document[0].activeElement;
140     if ( !isActive ) {
141     this.element.focus();
142     this.previous = previous;
143     // support: IE
144     // IE sets focus asynchronously, so we need to check if focus
145     // moved off of the input because the user clicked on the button.
146     this._delay(function() {
147     this.previous = previous;
148     });
149     }
150     }
151    
152     // ensure focus is on (or stays on) the text field
153     event.preventDefault();
154     checkFocus.call( this );
155    
156     // support: IE
157     // IE doesn't prevent moving focus even with event.preventDefault()
158     // so we set a flag to know when we should ignore the blur event
159     // and check (again) if focus moved off of the input.
160     this.cancelBlur = true;
161     this._delay(function() {
162     delete this.cancelBlur;
163     checkFocus.call( this );
164     });
165    
166     if ( this._start( event ) === false ) {
167     return;
168     }
169    
170     this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
171     },
172     "mouseup .ui-spinner-button": "_stop",
173     "mouseenter .ui-spinner-button": function( event ) {
174     // button will add ui-state-active if mouse was down while mouseleave and kept down
175     if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
176     return;
177     }
178    
179     if ( this._start( event ) === false ) {
180     return false;
181     }
182     this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
183     },
184     // TODO: do we really want to consider this a stop?
185     // shouldn't we just stop the repeater and wait until mouseup before
186     // we trigger the stop event?
187     "mouseleave .ui-spinner-button": "_stop"
188     },
189    
190     _draw: function() {
191     var uiSpinner = this.uiSpinner = this.element
192     .addClass( "ui-spinner-input" )
193     .attr( "autocomplete", "off" )
194     .wrap( this._uiSpinnerHtml() )
195     .parent()
196     // add buttons
197     .append( this._buttonHtml() );
198    
199     this.element.attr( "role", "spinbutton" );
200    
201     // button bindings
202     this.buttons = uiSpinner.find( ".ui-spinner-button" )
203     .attr( "tabIndex", -1 )
204     .button()
205     .removeClass( "ui-corner-all" );
206    
207     // IE 6 doesn't understand height: 50% for the buttons
208     // unless the wrapper has an explicit height
209     if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&
210     uiSpinner.height() > 0 ) {
211     uiSpinner.height( uiSpinner.height() );
212     }
213    
214     // disable spinner if element was already disabled
215     if ( this.options.disabled ) {
216     this.disable();
217     }
218     },
219    
220     _keydown: function( event ) {
221     var options = this.options,
222     keyCode = $.ui.keyCode;
223    
224     switch ( event.keyCode ) {
225     case keyCode.UP:
226     this._repeat( null, 1, event );
227     return true;
228     case keyCode.DOWN:
229     this._repeat( null, -1, event );
230     return true;
231     case keyCode.PAGE_UP:
232     this._repeat( null, options.page, event );
233     return true;
234     case keyCode.PAGE_DOWN:
235     this._repeat( null, -options.page, event );
236     return true;
237     }
238    
239     return false;
240     },
241    
242     _uiSpinnerHtml: function() {
243     return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>";
244     },
245    
246     _buttonHtml: function() {
247     return "" +
248     "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" +
249     "<span class='ui-icon " + this.options.icons.up + "'>&#9650;</span>" +
250     "</a>" +
251     "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" +
252     "<span class='ui-icon " + this.options.icons.down + "'>&#9660;</span>" +
253     "</a>";
254     },
255    
256     _start: function( event ) {
257     if ( !this.spinning && this._trigger( "start", event ) === false ) {
258     return false;
259     }
260    
261     if ( !this.counter ) {
262     this.counter = 1;
263     }
264     this.spinning = true;
265     return true;
266     },
267    
268     _repeat: function( i, steps, event ) {
269     i = i || 500;
270    
271     clearTimeout( this.timer );
272     this.timer = this._delay(function() {
273     this._repeat( 40, steps, event );
274     }, i );
275    
276     this._spin( steps * this.options.step, event );
277     },
278    
279     _spin: function( step, event ) {
280     var value = this.value() || 0;
281    
282     if ( !this.counter ) {
283     this.counter = 1;
284     }
285    
286     value = this._adjustValue( value + step * this._increment( this.counter ) );
287    
288     if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {
289     this._value( value );
290     this.counter++;
291     }
292     },
293    
294     _increment: function( i ) {
295     var incremental = this.options.incremental;
296    
297     if ( incremental ) {
298     return $.isFunction( incremental ) ?
299     incremental( i ) :
300     Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 );
301     }
302    
303     return 1;
304     },
305    
306     _precision: function() {
307     var precision = this._precisionOf( this.options.step );
308     if ( this.options.min !== null ) {
309     precision = Math.max( precision, this._precisionOf( this.options.min ) );
310     }
311     return precision;
312     },
313    
314     _precisionOf: function( num ) {
315     var str = num.toString(),
316     decimal = str.indexOf( "." );
317     return decimal === -1 ? 0 : str.length - decimal - 1;
318     },
319    
320     _adjustValue: function( value ) {
321     var base, aboveMin,
322     options = this.options;
323    
324     // make sure we're at a valid step
325     // - find out where we are relative to the base (min or 0)
326     base = options.min !== null ? options.min : 0;
327     aboveMin = value - base;
328     // - round to the nearest step
329     aboveMin = Math.round(aboveMin / options.step) * options.step;
330     // - rounding is based on 0, so adjust back to our base
331     value = base + aboveMin;
332    
333     // fix precision from bad JS floating point math
334     value = parseFloat( value.toFixed( this._precision() ) );
335    
336     // clamp the value
337     if ( options.max !== null && value > options.max) {
338     return options.max;
339     }
340     if ( options.min !== null && value < options.min ) {
341     return options.min;
342     }
343    
344     return value;
345     },
346    
347     _stop: function( event ) {
348     if ( !this.spinning ) {
349     return;
350     }
351    
352     clearTimeout( this.timer );
353     clearTimeout( this.mousewheelTimer );
354     this.counter = 0;
355     this.spinning = false;
356     this._trigger( "stop", event );
357     },
358    
359     _setOption: function( key, value ) {
360     if ( key === "culture" || key === "numberFormat" ) {
361     var prevValue = this._parse( this.element.val() );
362     this.options[ key ] = value;
363     this.element.val( this._format( prevValue ) );
364     return;
365     }
366    
367     if ( key === "max" || key === "min" || key === "step" ) {
368     if ( typeof value === "string" ) {
369     value = this._parse( value );
370     }
371     }
372     if ( key === "icons" ) {
373     this.buttons.first().find( ".ui-icon" )
374     .removeClass( this.options.icons.up )
375     .addClass( value.up );
376     this.buttons.last().find( ".ui-icon" )
377     .removeClass( this.options.icons.down )
378     .addClass( value.down );
379     }
380    
381     this._super( key, value );
382    
383     if ( key === "disabled" ) {
384     if ( value ) {
385     this.element.prop( "disabled", true );
386     this.buttons.button( "disable" );
387     } else {
388     this.element.prop( "disabled", false );
389     this.buttons.button( "enable" );
390     }
391     }
392     },
393    
394     _setOptions: modifier(function( options ) {
395     this._super( options );
396     this._value( this.element.val() );
397     }),
398    
399     _parse: function( val ) {
400     if ( typeof val === "string" && val !== "" ) {
401     val = window.Globalize && this.options.numberFormat ?
402     Globalize.parseFloat( val, 10, this.options.culture ) : +val;
403     }
404     return val === "" || isNaN( val ) ? null : val;
405     },
406    
407     _format: function( value ) {
408     if ( value === "" ) {
409     return "";
410     }
411     return window.Globalize && this.options.numberFormat ?
412     Globalize.format( value, this.options.numberFormat, this.options.culture ) :
413     value;
414     },
415    
416     _refresh: function() {
417     this.element.attr({
418     "aria-valuemin": this.options.min,
419     "aria-valuemax": this.options.max,
420     // TODO: what should we do with values that can't be parsed?
421     "aria-valuenow": this._parse( this.element.val() )
422     });
423     },
424    
425     // update the value without triggering change
426     _value: function( value, allowAny ) {
427     var parsed;
428     if ( value !== "" ) {
429     parsed = this._parse( value );
430     if ( parsed !== null ) {
431     if ( !allowAny ) {
432     parsed = this._adjustValue( parsed );
433     }
434     value = this._format( parsed );
435     }
436     }
437     this.element.val( value );
438     this._refresh();
439     },
440    
441     _destroy: function() {
442     this.element
443     .removeClass( "ui-spinner-input" )
444     .prop( "disabled", false )
445     .removeAttr( "autocomplete" )
446     .removeAttr( "role" )
447     .removeAttr( "aria-valuemin" )
448     .removeAttr( "aria-valuemax" )
449     .removeAttr( "aria-valuenow" );
450     this.uiSpinner.replaceWith( this.element );
451     },
452    
453     stepUp: modifier(function( steps ) {
454     this._stepUp( steps );
455     }),
456     _stepUp: function( steps ) {
457     if ( this._start() ) {
458     this._spin( (steps || 1) * this.options.step );
459     this._stop();
460     }
461     },
462    
463     stepDown: modifier(function( steps ) {
464     this._stepDown( steps );
465     }),
466     _stepDown: function( steps ) {
467     if ( this._start() ) {
468     this._spin( (steps || 1) * -this.options.step );
469     this._stop();
470     }
471     },
472    
473     pageUp: modifier(function( pages ) {
474     this._stepUp( (pages || 1) * this.options.page );
475     }),
476    
477     pageDown: modifier(function( pages ) {
478     this._stepDown( (pages || 1) * this.options.page );
479     }),
480    
481     value: function( newVal ) {
482     if ( !arguments.length ) {
483     return this._parse( this.element.val() );
484     }
485     modifier( this._value ).call( this, newVal );
486     },
487    
488     widget: function() {
489     return this.uiSpinner;
490     }
491     });
492    
493     }( jQuery ) );

  ViewVC Help
Powered by ViewVC 1.1.20