mirror of
https://github.com/Hopiu/jquery-mobile.git
synced 2026-05-04 12:54:41 +00:00
- Internally, each plugin self-initializes by binding to the pagecreate event. - Unit tests have been added and adjusted to support some internal changes involved in this commit. - In the process, the portions of the page plugin that were used to enhance the header,content,and footer sections of a native-app style page layout are now located in jquery.mobile.page.sections.js. - No public API options have changed, except that the page plugin no longer has options for keepNative, and degradeInputs, as plugins now handle these internally (keepNative was never documented, and degradeInputs only affected slider, so it lives there now. Page options related to the page sections are now located in the page.sections script, but they are still configurable via the page plugin's options api. - Make, Ant, and index files are updated with a new load order for all JS files.
333 lines
8.7 KiB
JavaScript
333 lines
8.7 KiB
JavaScript
/*
|
|
* jQuery Mobile Framework : "slider" plugin
|
|
* Copyright (c) jQuery Project
|
|
* Dual licensed under the MIT or GPL Version 2 licenses.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
( function( $, undefined ) {
|
|
|
|
//auto self-init widgets
|
|
$( document ).bind( "pagecreate", function( e ){
|
|
|
|
var nativeSel = ":jqmData(role='none'), :jqmData(role='nojs')";
|
|
|
|
//degrade range back to number type
|
|
$( "input[type='range']:not("+ nativeSel +")", e.target ).each(function(){
|
|
$(this).replaceWith(
|
|
$( "<div>" ).html( $(this).clone() ).html()
|
|
.replace( /\s+type=["']?\w+['"]?/, " type=\"number\" data-" + $.mobile.ns + "role=\"slider\" " ) );
|
|
});
|
|
|
|
//now self-init
|
|
$( ":jqmData(role='slider'):not("+ nativeSel +")", e.target ).slider();
|
|
|
|
});
|
|
|
|
$.widget( "mobile.slider", $.mobile.widget, {
|
|
options: {
|
|
theme: null,
|
|
trackTheme: null,
|
|
disabled: false
|
|
},
|
|
|
|
_create: function() {
|
|
|
|
// TODO: Each of these should have comments explain what they're for
|
|
var self = this,
|
|
|
|
control = this.element,
|
|
|
|
parentTheme = control.parents( "[class*='ui-bar-'],[class*='ui-body-']" ).eq( 0 ),
|
|
|
|
parentTheme = parentTheme.length ? parentTheme.attr( "class" ).match( /ui-(bar|body)-([a-z])/ )[ 2 ] : "c",
|
|
|
|
theme = this.options.theme ? this.options.theme : parentTheme,
|
|
|
|
trackTheme = this.options.trackTheme ? this.options.trackTheme : parentTheme,
|
|
|
|
cType = control[ 0 ].nodeName.toLowerCase(),
|
|
|
|
selectClass = ( cType == "select" ) ? "ui-slider-switch" : "",
|
|
|
|
controlID = control.attr( "id" ),
|
|
|
|
labelID = controlID + "-label",
|
|
|
|
label = $( "[for='"+ controlID +"']" ).attr( "id", labelID ),
|
|
|
|
val = function() {
|
|
return cType == "input" ? parseFloat( control.val() ) : control[0].selectedIndex;
|
|
},
|
|
|
|
min = cType == "input" ? parseFloat( control.attr( "min" ) ) : 0,
|
|
|
|
max = cType == "input" ? parseFloat( control.attr( "max" ) ) : control.find( "option" ).length-1,
|
|
|
|
step = window.parseFloat( control.attr( "step" ) || 1 ),
|
|
|
|
slider = $( "<div class='ui-slider " + selectClass + " ui-btn-down-" + trackTheme +
|
|
" ui-btn-corner-all' role='application'></div>" ),
|
|
|
|
handle = $( "<a href='#' class='ui-slider-handle'></a>" )
|
|
.appendTo( slider )
|
|
.buttonMarkup({ corners: true, theme: theme, shadow: true })
|
|
.attr({
|
|
"role": "slider",
|
|
"aria-valuemin": min,
|
|
"aria-valuemax": max,
|
|
"aria-valuenow": val(),
|
|
"aria-valuetext": val(),
|
|
"title": val(),
|
|
"aria-labelledby": labelID
|
|
}),
|
|
options;
|
|
|
|
$.extend( this, {
|
|
slider: slider,
|
|
handle: handle,
|
|
dragging: false,
|
|
beforeStart: null
|
|
});
|
|
|
|
if ( cType == "select" ) {
|
|
|
|
slider.wrapInner( "<div class='ui-slider-inneroffset'></div>" );
|
|
|
|
options = control.find( "option" );
|
|
|
|
control.find( "option" ).each(function( i ) {
|
|
|
|
var side = !i ? "b":"a",
|
|
corners = !i ? "right" :"left",
|
|
theme = !i ? " ui-btn-down-" + trackTheme :" ui-btn-active";
|
|
|
|
$( "<div class='ui-slider-labelbg ui-slider-labelbg-" + side + theme + " ui-btn-corner-" + corners + "'></div>" )
|
|
.prependTo( slider );
|
|
|
|
$( "<span class='ui-slider-label ui-slider-label-" + side + theme + " ui-btn-corner-" + corners + "' role='img'>" + $( this ).text() + "</span>" )
|
|
.prependTo( handle );
|
|
});
|
|
|
|
}
|
|
|
|
label.addClass( "ui-slider" );
|
|
|
|
// monitor the input for updated values
|
|
control.addClass( cType === "input" ? "ui-slider-input" : "ui-slider-switch" )
|
|
.change( function() {
|
|
self.refresh( val(), true );
|
|
})
|
|
.keyup( function() { // necessary?
|
|
self.refresh( val(), true, true );
|
|
})
|
|
.blur( function() {
|
|
self.refresh( val(), true );
|
|
});
|
|
|
|
// prevent screen drag when slider activated
|
|
$( document ).bind( "vmousemove", function( event ) {
|
|
if ( self.dragging ) {
|
|
self.refresh( event );
|
|
return false;
|
|
}
|
|
});
|
|
|
|
slider.bind( "vmousedown", function( event ) {
|
|
self.dragging = true;
|
|
|
|
if ( cType === "select" ) {
|
|
self.beforeStart = control[0].selectedIndex;
|
|
}
|
|
self.refresh( event );
|
|
return false;
|
|
});
|
|
|
|
slider.add( document )
|
|
.bind( "vmouseup", function() {
|
|
if ( self.dragging ) {
|
|
|
|
self.dragging = false;
|
|
|
|
if ( cType === "select" ) {
|
|
|
|
if ( self.beforeStart === control[ 0 ].selectedIndex ) {
|
|
//tap occurred, but value didn't change. flip it!
|
|
self.refresh( !self.beforeStart ? 1 : 0 );
|
|
}
|
|
var curval = val();
|
|
var snapped = Math.round( curval / ( max - min ) * 100 );
|
|
handle
|
|
.addClass( "ui-slider-handle-snapping" )
|
|
.css( "left", snapped + "%" )
|
|
.animationComplete( function() {
|
|
handle.removeClass( "ui-slider-handle-snapping" );
|
|
});
|
|
}
|
|
return false;
|
|
}
|
|
});
|
|
|
|
slider.insertAfter( control );
|
|
|
|
// NOTE force focus on handle
|
|
this.handle
|
|
.bind( "vmousedown", function() {
|
|
$( this ).focus();
|
|
})
|
|
.bind( "vclick", false );
|
|
|
|
this.handle
|
|
.bind( "keydown", function( event ) {
|
|
var index = val();
|
|
|
|
if ( self.options.disabled ) {
|
|
return;
|
|
}
|
|
|
|
// In all cases prevent the default and mark the handle as active
|
|
switch ( event.keyCode ) {
|
|
case $.mobile.keyCode.HOME:
|
|
case $.mobile.keyCode.END:
|
|
case $.mobile.keyCode.PAGE_UP:
|
|
case $.mobile.keyCode.PAGE_DOWN:
|
|
case $.mobile.keyCode.UP:
|
|
case $.mobile.keyCode.RIGHT:
|
|
case $.mobile.keyCode.DOWN:
|
|
case $.mobile.keyCode.LEFT:
|
|
event.preventDefault();
|
|
|
|
if ( !self._keySliding ) {
|
|
self._keySliding = true;
|
|
$( this ).addClass( "ui-state-active" );
|
|
}
|
|
break;
|
|
}
|
|
|
|
// move the slider according to the keypress
|
|
switch ( event.keyCode ) {
|
|
case $.mobile.keyCode.HOME:
|
|
self.refresh( min );
|
|
break;
|
|
case $.mobile.keyCode.END:
|
|
self.refresh( max );
|
|
break;
|
|
case $.mobile.keyCode.PAGE_UP:
|
|
case $.mobile.keyCode.UP:
|
|
case $.mobile.keyCode.RIGHT:
|
|
self.refresh( index + step );
|
|
break;
|
|
case $.mobile.keyCode.PAGE_DOWN:
|
|
case $.mobile.keyCode.DOWN:
|
|
case $.mobile.keyCode.LEFT:
|
|
self.refresh( index - step );
|
|
break;
|
|
}
|
|
}) // remove active mark
|
|
.keyup( function( event ) {
|
|
if ( self._keySliding ) {
|
|
self._keySliding = false;
|
|
$( this ).removeClass( "ui-state-active" );
|
|
}
|
|
});
|
|
|
|
this.refresh(undefined, undefined, true);
|
|
},
|
|
|
|
refresh: function( val, isfromControl, preventInputUpdate ) {
|
|
if ( this.options.disabled ) { return; }
|
|
|
|
var control = this.element, percent,
|
|
cType = control[0].nodeName.toLowerCase(),
|
|
min = cType === "input" ? parseFloat( control.attr( "min" ) ) : 0,
|
|
max = cType === "input" ? parseFloat( control.attr( "max" ) ) : control.find( "option" ).length - 1;
|
|
|
|
if ( typeof val === "object" ) {
|
|
var data = val,
|
|
// a slight tolerance helped get to the ends of the slider
|
|
tol = 8;
|
|
if ( !this.dragging ||
|
|
data.pageX < this.slider.offset().left - tol ||
|
|
data.pageX > this.slider.offset().left + this.slider.width() + tol ) {
|
|
return;
|
|
}
|
|
percent = Math.round( ( ( data.pageX - this.slider.offset().left ) / this.slider.width() ) * 100 );
|
|
} else {
|
|
if ( val == null ) {
|
|
val = cType === "input" ? parseFloat( control.val() ) : control[0].selectedIndex;
|
|
}
|
|
percent = ( parseFloat( val ) - min ) / ( max - min ) * 100;
|
|
}
|
|
|
|
if ( isNaN( percent ) ) {
|
|
return;
|
|
}
|
|
|
|
if ( percent < 0 ) {
|
|
percent = 0;
|
|
}
|
|
|
|
if ( percent > 100 ) {
|
|
percent = 100;
|
|
}
|
|
|
|
var newval = Math.round( ( percent / 100 ) * ( max - min ) ) + min;
|
|
|
|
if ( newval < min ) {
|
|
newval = min;
|
|
}
|
|
|
|
if ( newval > max ) {
|
|
newval = max;
|
|
}
|
|
|
|
// Flip the stack of the bg colors
|
|
if ( percent > 60 && cType === "select" ) {
|
|
// TODO: Dead path?
|
|
}
|
|
this.handle.css( "left", percent + "%" );
|
|
this.handle.attr( {
|
|
"aria-valuenow": cType === "input" ? newval : control.find( "option" ).eq( newval ).attr( "value" ),
|
|
"aria-valuetext": cType === "input" ? newval : control.find( "option" ).eq( newval ).text(),
|
|
title: newval
|
|
});
|
|
|
|
// add/remove classes for flip toggle switch
|
|
if ( cType === "select" ) {
|
|
if ( newval === 0 ) {
|
|
this.slider.addClass( "ui-slider-switch-a" )
|
|
.removeClass( "ui-slider-switch-b" );
|
|
} else {
|
|
this.slider.addClass( "ui-slider-switch-b" )
|
|
.removeClass( "ui-slider-switch-a" );
|
|
}
|
|
}
|
|
|
|
if ( !preventInputUpdate ) {
|
|
// update control"s value
|
|
if ( cType === "input" ) {
|
|
control.val( newval );
|
|
} else {
|
|
control[ 0 ].selectedIndex = newval;
|
|
}
|
|
if ( !isfromControl ) {
|
|
control.trigger( "change" );
|
|
}
|
|
}
|
|
},
|
|
|
|
enable: function() {
|
|
this.element.attr( "disabled", false );
|
|
this.slider.removeClass( "ui-disabled" ).attr( "aria-disabled", false );
|
|
return this._setOption( "disabled", false );
|
|
},
|
|
|
|
disable: function() {
|
|
this.element.attr( "disabled", true );
|
|
this.slider.addClass( "ui-disabled" ).attr( "aria-disabled", true );
|
|
return this._setOption( "disabled", true );
|
|
}
|
|
|
|
});
|
|
})( jQuery );
|
|
|