Diff: STRATO-apps/wordpress_03/app/wp-includes/js/jquery/ui/spinner.js

Keine Baseline-Datei – Diff nur gegen leer.
Zur Liste
1 -
1 + /*!
2 + * jQuery UI Spinner 1.13.3
3 + * https://jqueryui.com
4 + *
5 + * Copyright OpenJS Foundation and other contributors
6 + * Released under the MIT license.
7 + * https://jquery.org/license
8 + */
9 +
10 + //>>label: Spinner
11 + //>>group: Widgets
12 + //>>description: Displays buttons to easily input numbers via the keyboard or mouse.
13 + //>>docs: https://api.jqueryui.com/spinner/
14 + //>>demos: https://jqueryui.com/spinner/
15 + //>>css.structure: ../../themes/base/core.css
16 + //>>css.structure: ../../themes/base/spinner.css
17 + //>>css.theme: ../../themes/base/theme.css
18 +
19 + ( function( factory ) {
20 + "use strict";
21 +
22 + if ( typeof define === "function" && define.amd ) {
23 +
24 + // AMD. Register as an anonymous module.
25 + define( [
26 + "jquery",
27 + "./button",
28 + "../version",
29 + "../keycode",
30 + "../safe-active-element",
31 + "../widget"
32 + ], factory );
33 + } else {
34 +
35 + // Browser globals
36 + factory( jQuery );
37 + }
38 + } )( function( $ ) {
39 + "use strict";
40 +
41 + function spinnerModifier( fn ) {
42 + return function() {
43 + var previous = this.element.val();
44 + fn.apply( this, arguments );
45 + this._refresh();
46 + if ( previous !== this.element.val() ) {
47 + this._trigger( "change" );
48 + }
49 + };
50 + }
51 +
52 + $.widget( "ui.spinner", {
53 + version: "1.13.3",
54 + defaultElement: "<input>",
55 + widgetEventPrefix: "spin",
56 + options: {
57 + classes: {
58 + "ui-spinner": "ui-corner-all",
59 + "ui-spinner-down": "ui-corner-br",
60 + "ui-spinner-up": "ui-corner-tr"
61 + },
62 + culture: null,
63 + icons: {
64 + down: "ui-icon-triangle-1-s",
65 + up: "ui-icon-triangle-1-n"
66 + },
67 + incremental: true,
68 + max: null,
69 + min: null,
70 + numberFormat: null,
71 + page: 10,
72 + step: 1,
73 +
74 + change: null,
75 + spin: null,
76 + start: null,
77 + stop: null
78 + },
79 +
80 + _create: function() {
81 +
82 + // handle string values that need to be parsed
83 + this._setOption( "max", this.options.max );
84 + this._setOption( "min", this.options.min );
85 + this._setOption( "step", this.options.step );
86 +
87 + // Only format if there is a value, prevents the field from being marked
88 + // as invalid in Firefox, see #9573.
89 + if ( this.value() !== "" ) {
90 +
91 + // Format the value, but don't constrain.
92 + this._value( this.element.val(), true );
93 + }
94 +
95 + this._draw();
96 + this._on( this._events );
97 + this._refresh();
98 +
99 + // Turning off autocomplete prevents the browser from remembering the
100 + // value when navigating through history, so we re-enable autocomplete
101 + // if the page is unloaded before the widget is destroyed. #7790
102 + this._on( this.window, {
103 + beforeunload: function() {
104 + this.element.removeAttr( "autocomplete" );
105 + }
106 + } );
107 + },
108 +
109 + _getCreateOptions: function() {
110 + var options = this._super();
111 + var element = this.element;
112 +
113 + $.each( [ "min", "max", "step" ], function( i, option ) {
114 + var value = element.attr( option );
115 + if ( value != null && value.length ) {
116 + options[ option ] = value;
117 + }
118 + } );
119 +
120 + return options;
121 + },
122 +
123 + _events: {
124 + keydown: function( event ) {
125 + if ( this._start( event ) && this._keydown( event ) ) {
126 + event.preventDefault();
127 + }
128 + },
129 + keyup: "_stop",
130 + focus: function() {
131 + this.previous = this.element.val();
132 + },
133 + blur: function( event ) {
134 + if ( this.cancelBlur ) {
135 + delete this.cancelBlur;
136 + return;
137 + }
138 +
139 + this._stop();
140 + this._refresh();
141 + if ( this.previous !== this.element.val() ) {
142 + this._trigger( "change", event );
143 + }
144 + },
145 + mousewheel: function( event, delta ) {
146 + var activeElement = $.ui.safeActiveElement( this.document[ 0 ] );
147 + var isActive = this.element[ 0 ] === activeElement;
148 +
149 + if ( !isActive || !delta ) {
150 + return;
151 + }
152 +
153 + if ( !this.spinning && !this._start( event ) ) {
154 + return false;
155 + }
156 +
157 + this._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event );
158 + clearTimeout( this.mousewheelTimer );
159 + this.mousewheelTimer = this._delay( function() {
160 + if ( this.spinning ) {
161 + this._stop( event );
162 + }
163 + }, 100 );
164 + event.preventDefault();
165 + },
166 + "mousedown .ui-spinner-button": function( event ) {
167 + var previous;
168 +
169 + // We never want the buttons to have focus; whenever the user is
170 + // interacting with the spinner, the focus should be on the input.
171 + // If the input is focused then this.previous is properly set from
172 + // when the input first received focus. If the input is not focused
173 + // then we need to set this.previous based on the value before spinning.
174 + previous = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] ) ?
175 + this.previous : this.element.val();
176 + function checkFocus() {
177 + var isActive = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] );
178 + if ( !isActive ) {
179 + this.element.trigger( "focus" );
180 + this.previous = previous;
181 +
182 + // support: IE
183 + // IE sets focus asynchronously, so we need to check if focus
184 + // moved off of the input because the user clicked on the button.
185 + this._delay( function() {
186 + this.previous = previous;
187 + } );
188 + }
189 + }
190 +
191 + // Ensure focus is on (or stays on) the text field
192 + event.preventDefault();
193 + checkFocus.call( this );
194 +
195 + // Support: IE
196 + // IE doesn't prevent moving focus even with event.preventDefault()
197 + // so we set a flag to know when we should ignore the blur event
198 + // and check (again) if focus moved off of the input.
199 + this.cancelBlur = true;
200 + this._delay( function() {
201 + delete this.cancelBlur;
202 + checkFocus.call( this );
203 + } );
204 +
205 + if ( this._start( event ) === false ) {
206 + return;
207 + }
208 +
209 + this._repeat( null, $( event.currentTarget )
210 + .hasClass( "ui-spinner-up" ) ? 1 : -1, event );
211 + },
212 + "mouseup .ui-spinner-button": "_stop",
213 + "mouseenter .ui-spinner-button": function( event ) {
214 +
215 + // button will add ui-state-active if mouse was down while mouseleave and kept down
216 + if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
217 + return;
218 + }
219 +
220 + if ( this._start( event ) === false ) {
221 + return false;
222 + }
223 + this._repeat( null, $( event.currentTarget )
224 + .hasClass( "ui-spinner-up" ) ? 1 : -1, event );
225 + },
226 +
227 + // TODO: do we really want to consider this a stop?
228 + // shouldn't we just stop the repeater and wait until mouseup before
229 + // we trigger the stop event?
230 + "mouseleave .ui-spinner-button": "_stop"
231 + },
232 +
233 + // Support mobile enhanced option and make backcompat more sane
234 + _enhance: function() {
235 + this.uiSpinner = this.element
236 + .attr( "autocomplete", "off" )
237 + .wrap( "<span>" )
238 + .parent()
239 +
240 + // Add buttons
241 + .append(
242 + "<a></a><a></a>"
243 + );
244 + },
245 +
246 + _draw: function() {
247 + this._enhance();
248 +
249 + this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" );
250 + this._addClass( "ui-spinner-input" );
251 +
252 + this.element.attr( "role", "spinbutton" );
253 +
254 + // Button bindings
255 + this.buttons = this.uiSpinner.children( "a" )
256 + .attr( "tabIndex", -1 )
257 + .attr( "aria-hidden", true )
258 + .button( {
259 + classes: {
260 + "ui-button": ""
261 + }
262 + } );
263 +
264 + // TODO: Right now button does not support classes this is already updated in button PR
265 + this._removeClass( this.buttons, "ui-corner-all" );
266 +
267 + this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" );
268 + this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" );
269 + this.buttons.first().button( {
270 + "icon": this.options.icons.up,
271 + "showLabel": false
272 + } );
273 + this.buttons.last().button( {
274 + "icon": this.options.icons.down,
275 + "showLabel": false
276 + } );
277 +
278 + // IE 6 doesn't understand height: 50% for the buttons
279 + // unless the wrapper has an explicit height
280 + if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) &&
281 + this.uiSpinner.height() > 0 ) {
282 + this.uiSpinner.height( this.uiSpinner.height() );
283 + }
284 + },
285 +
286 + _keydown: function( event ) {
287 + var options = this.options,
288 + keyCode = $.ui.keyCode;
289 +
290 + switch ( event.keyCode ) {
291 + case keyCode.UP:
292 + this._repeat( null, 1, event );
293 + return true;
294 + case keyCode.DOWN:
295 + this._repeat( null, -1, event );
296 + return true;
297 + case keyCode.PAGE_UP:
298 + this._repeat( null, options.page, event );
299 + return true;
300 + case keyCode.PAGE_DOWN:
301 + this._repeat( null, -options.page, event );
302 + return true;
303 + }
304 +
305 + return false;
306 + },
307 +
308 + _start: function( event ) {
309 + if ( !this.spinning && this._trigger( "start", event ) === false ) {
310 + return false;
311 + }
312 +
313 + if ( !this.counter ) {
314 + this.counter = 1;
315 + }
316 + this.spinning = true;
317 + return true;
318 + },
319 +
320 + _repeat: function( i, steps, event ) {
321 + i = i || 500;
322 +
323 + clearTimeout( this.timer );
324 + this.timer = this._delay( function() {
325 + this._repeat( 40, steps, event );
326 + }, i );
327 +
328 + this._spin( steps * this.options.step, event );
329 + },
330 +
331 + _spin: function( step, event ) {
332 + var value = this.value() || 0;
333 +
334 + if ( !this.counter ) {
335 + this.counter = 1;
336 + }
337 +
338 + value = this._adjustValue( value + step * this._increment( this.counter ) );
339 +
340 + if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false ) {
341 + this._value( value );
342 + this.counter++;
343 + }
344 + },
345 +
346 + _increment: function( i ) {
347 + var incremental = this.options.incremental;
348 +
349 + if ( incremental ) {
350 + return typeof incremental === "function" ?
351 + incremental( i ) :
352 + Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
353 + }
354 +
355 + return 1;
356 + },
357 +
358 + _precision: function() {
359 + var precision = this._precisionOf( this.options.step );
360 + if ( this.options.min !== null ) {
361 + precision = Math.max( precision, this._precisionOf( this.options.min ) );
362 + }
363 + return precision;
364 + },
365 +
366 + _precisionOf: function( num ) {
367 + var str = num.toString(),
368 + decimal = str.indexOf( "." );
369 + return decimal === -1 ? 0 : str.length - decimal - 1;
370 + },
371 +
372 + _adjustValue: function( value ) {
373 + var base, aboveMin,
374 + options = this.options;
375 +
376 + // Make sure we're at a valid step
377 + // - find out where we are relative to the base (min or 0)
378 + base = options.min !== null ? options.min : 0;
379 + aboveMin = value - base;
380 +
381 + // - round to the nearest step
382 + aboveMin = Math.round( aboveMin / options.step ) * options.step;
383 +
384 + // - rounding is based on 0, so adjust back to our base
385 + value = base + aboveMin;
386 +
387 + // Fix precision from bad JS floating point math
388 + value = parseFloat( value.toFixed( this._precision() ) );
389 +
390 + // Clamp the value
391 + if ( options.max !== null && value > options.max ) {
392 + return options.max;
393 + }
394 + if ( options.min !== null && value < options.min ) {
395 + return options.min;
396 + }
397 +
398 + return value;
399 + },
400 +
401 + _stop: function( event ) {
402 + if ( !this.spinning ) {
403 + return;
404 + }
405 +
406 + clearTimeout( this.timer );
407 + clearTimeout( this.mousewheelTimer );
408 + this.counter = 0;
409 + this.spinning = false;
410 + this._trigger( "stop", event );
411 + },
412 +
413 + _setOption: function( key, value ) {
414 + var prevValue, first, last;
415 +
416 + if ( key === "culture" || key === "numberFormat" ) {
417 + prevValue = this._parse( this.element.val() );
418 + this.options[ key ] = value;
419 + this.element.val( this._format( prevValue ) );
420 + return;
421 + }
422 +
423 + if ( key === "max" || key === "min" || key === "step" ) {
424 + if ( typeof value === "string" ) {
425 + value = this._parse( value );
426 + }
427 + }
428 + if ( key === "icons" ) {
429 + first = this.buttons.first().find( ".ui-icon" );
430 + this._removeClass( first, null, this.options.icons.up );
431 + this._addClass( first, null, value.up );
432 + last = this.buttons.last().find( ".ui-icon" );
433 + this._removeClass( last, null, this.options.icons.down );
434 + this._addClass( last, null, value.down );
435 + }
436 +
437 + this._super( key, value );
438 + },
439 +
440 + _setOptionDisabled: function( value ) {
441 + this._super( value );
442 +
443 + this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value );
444 + this.element.prop( "disabled", !!value );
445 + this.buttons.button( value ? "disable" : "enable" );
446 + },
447 +
448 + _setOptions: spinnerModifier( function( options ) {
449 + this._super( options );
450 + } ),
451 +
452 + _parse: function( val ) {
453 + if ( typeof val === "string" && val !== "" ) {
454 + val = window.Globalize && this.options.numberFormat ?
455 + Globalize.parseFloat( val, 10, this.options.culture ) : +val;
456 + }
457 + return val === "" || isNaN( val ) ? null : val;
458 + },
459 +
460 + _format: function( value ) {
461 + if ( value === "" ) {
462 + return "";
463 + }
464 + return window.Globalize && this.options.numberFormat ?
465 + Globalize.format( value, this.options.numberFormat, this.options.culture ) :
466 + value;
467 + },
468 +
469 + _refresh: function() {
470 + this.element.attr( {
471 + "aria-valuemin": this.options.min,
472 + "aria-valuemax": this.options.max,
473 +
474 + // TODO: what should we do with values that can't be parsed?
475 + "aria-valuenow": this._parse( this.element.val() )
476 + } );
477 + },
478 +
479 + isValid: function() {
480 + var value = this.value();
481 +
482 + // Null is invalid
483 + if ( value === null ) {
484 + return false;
485 + }
486 +
487 + // If value gets adjusted, it's invalid
488 + return value === this._adjustValue( value );
489 + },
490 +
491 + // Update the value without triggering change
492 + _value: function( value, allowAny ) {
493 + var parsed;
494 + if ( value !== "" ) {
495 + parsed = this._parse( value );
496 + if ( parsed !== null ) {
497 + if ( !allowAny ) {
498 + parsed = this._adjustValue( parsed );
499 + }
500 + value = this._format( parsed );
501 + }
502 + }
503 + this.element.val( value );
504 + this._refresh();
505 + },
506 +
507 + _destroy: function() {
508 + this.element
509 + .prop( "disabled", false )
510 + .removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" );
511 +
512 + this.uiSpinner.replaceWith( this.element );
513 + },
514 +
515 + stepUp: spinnerModifier( function( steps ) {
516 + this._stepUp( steps );
517 + } ),
518 + _stepUp: function( steps ) {
519 + if ( this._start() ) {
520 + this._spin( ( steps || 1 ) * this.options.step );
521 + this._stop();
522 + }
523 + },
524 +
525 + stepDown: spinnerModifier( function( steps ) {
526 + this._stepDown( steps );
527 + } ),
528 + _stepDown: function( steps ) {
529 + if ( this._start() ) {
530 + this._spin( ( steps || 1 ) * -this.options.step );
531 + this._stop();
532 + }
533 + },
534 +
535 + pageUp: spinnerModifier( function( pages ) {
536 + this._stepUp( ( pages || 1 ) * this.options.page );
537 + } ),
538 +
539 + pageDown: spinnerModifier( function( pages ) {
540 + this._stepDown( ( pages || 1 ) * this.options.page );
541 + } ),
542 +
543 + value: function( newVal ) {
544 + if ( !arguments.length ) {
545 + return this._parse( this.element.val() );
546 + }
547 + spinnerModifier( this._value ).call( this, newVal );
548 + },
549 +
550 + widget: function() {
551 + return this.uiSpinner;
552 + }
553 + } );
554 +
555 + // DEPRECATED
556 + // TODO: switch return back to widget declaration at top of file when this is removed
557 + if ( $.uiBackCompat !== false ) {
558 +
559 + // Backcompat for spinner html extension points
560 + $.widget( "ui.spinner", $.ui.spinner, {
561 + _enhance: function() {
562 + this.uiSpinner = this.element
563 + .attr( "autocomplete", "off" )
564 + .wrap( this._uiSpinnerHtml() )
565 + .parent()
566 +
567 + // Add buttons
568 + .append( this._buttonHtml() );
569 + },
570 + _uiSpinnerHtml: function() {
571 + return "<span>";
572 + },
573 +
574 + _buttonHtml: function() {
575 + return "<a></a><a></a>";
576 + }
577 + } );
578 + }
579 +
580 + return $.ui.spinner;
581 +
582 + } );
583 +