mirror of
https://github.com/Hopiu/jquery-mobile.git
synced 2026-03-30 12:40:30 +00:00
- Modified findClosestEnabledButton() so that instead of checking for existence of ele.className, before using it, that it check for typeof ele.className === 'string'. This prevents us from looking at the className property of SVG elements which actually use type SVGAnimatedString which does not have the split() function in its API.
189 lines
5.2 KiB
JavaScript
189 lines
5.2 KiB
JavaScript
/*
|
|
* "buttons" plugin - for making button-like links
|
|
*/
|
|
|
|
( function( $, undefined ) {
|
|
|
|
$.fn.buttonMarkup = function( options ) {
|
|
options = options || {};
|
|
|
|
for ( var i = 0; i < this.length; i++ ) {
|
|
var el = this.eq( i ),
|
|
e = el[ 0 ],
|
|
o = $.extend( {}, $.fn.buttonMarkup.defaults, {
|
|
icon: options.icon !== undefined ? options.icon : el.jqmData( "icon" ),
|
|
iconpos: options.iconpos !== undefined ? options.iconpos : el.jqmData( "iconpos" ),
|
|
theme: options.theme !== undefined ? options.theme : el.jqmData( "theme" ),
|
|
inline: options.inline !== undefined ? options.inline : el.jqmData( "inline" ),
|
|
shadow: options.shadow !== undefined ? options.shadow : el.jqmData( "shadow" ),
|
|
corners: options.corners !== undefined ? options.corners : el.jqmData( "corners" ),
|
|
iconshadow: options.iconshadow !== undefined ? options.iconshadow : el.jqmData( "iconshadow" )
|
|
}, options ),
|
|
|
|
// Classes Defined
|
|
innerClass = "ui-btn-inner",
|
|
textClass = "ui-btn-text",
|
|
buttonClass, iconClass,
|
|
|
|
// Button inner markup
|
|
buttonInner = document.createElement( o.wrapperEls ),
|
|
buttonText = document.createElement( o.wrapperEls ),
|
|
buttonIcon = o.icon ? document.createElement( "span" ) : null;
|
|
|
|
if ( attachEvents ) {
|
|
attachEvents();
|
|
}
|
|
|
|
// if not, try to find closest theme container
|
|
if ( !o.theme ) {
|
|
o.theme = $.mobile.getInheritedTheme( el, "c" );
|
|
}
|
|
|
|
buttonClass = "ui-btn ui-btn-up-" + o.theme;
|
|
|
|
if ( o.inline ) {
|
|
buttonClass += " ui-btn-inline";
|
|
}
|
|
|
|
if ( o.icon ) {
|
|
o.icon = "ui-icon-" + o.icon;
|
|
o.iconpos = o.iconpos || "left";
|
|
|
|
iconClass = "ui-icon " + o.icon;
|
|
|
|
if ( o.iconshadow ) {
|
|
iconClass += " ui-icon-shadow";
|
|
}
|
|
}
|
|
|
|
if ( o.iconpos ) {
|
|
buttonClass += " ui-btn-icon-" + o.iconpos;
|
|
|
|
if ( o.iconpos == "notext" && !el.attr( "title" ) ) {
|
|
el.attr( "title", el.getEncodedText() );
|
|
}
|
|
}
|
|
|
|
if ( o.corners ) {
|
|
buttonClass += " ui-btn-corner-all";
|
|
innerClass += " ui-btn-corner-all";
|
|
}
|
|
|
|
if ( o.shadow ) {
|
|
buttonClass += " ui-shadow";
|
|
}
|
|
|
|
e.setAttribute( "data-" + $.mobile.ns + "theme", o.theme );
|
|
el.addClass( buttonClass );
|
|
|
|
buttonInner.className = innerClass;
|
|
buttonInner.setAttribute("aria-hidden", "true");
|
|
|
|
buttonText.className = textClass;
|
|
buttonInner.appendChild( buttonText );
|
|
|
|
if ( buttonIcon ) {
|
|
buttonIcon.className = iconClass;
|
|
buttonInner.appendChild( buttonIcon );
|
|
}
|
|
|
|
while ( e.firstChild ) {
|
|
buttonText.appendChild( e.firstChild );
|
|
}
|
|
|
|
e.appendChild( buttonInner );
|
|
|
|
// TODO obviously it would be nice to pull this element out instead of
|
|
// retrieving it from the DOM again, but this change is much less obtrusive
|
|
// and 1.0 draws nigh
|
|
$.data( e, 'textWrapper', $( buttonText ) );
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
$.fn.buttonMarkup.defaults = {
|
|
corners: true,
|
|
shadow: true,
|
|
iconshadow: true,
|
|
inline: false,
|
|
wrapperEls: "span"
|
|
};
|
|
|
|
function closestEnabledButton( element ) {
|
|
var cname;
|
|
|
|
while ( element ) {
|
|
// Note that we check for typeof className below because the element we
|
|
// handed could be in an SVG DOM where className on SVG elements is defined to
|
|
// be of a different type (SVGAnimatedString). We only operate on HTML DOM
|
|
// elements, so we look for plain "string".
|
|
|
|
cname = ( typeof element.className === 'string' ) && element.className.split(' ');
|
|
|
|
if ( cname && $.inArray( "ui-btn", cname ) > -1 && $.inArray( "ui-disabled", cname ) < 0 ) {
|
|
break;
|
|
}
|
|
element = element.parentNode;
|
|
}
|
|
|
|
return element;
|
|
}
|
|
|
|
var attachEvents = function() {
|
|
$( document ).bind( {
|
|
"vmousedown": function( event ) {
|
|
var btn = closestEnabledButton( event.target ),
|
|
$btn, theme;
|
|
|
|
if ( btn ) {
|
|
$btn = $( btn );
|
|
theme = $btn.attr( "data-" + $.mobile.ns + "theme" );
|
|
$btn.removeClass( "ui-btn-up-" + theme ).addClass( "ui-btn-down-" + theme );
|
|
}
|
|
},
|
|
"vmousecancel vmouseup": function( event ) {
|
|
var btn = closestEnabledButton( event.target ),
|
|
$btn, theme;
|
|
|
|
if ( btn ) {
|
|
$btn = $( btn );
|
|
theme = $btn.attr( "data-" + $.mobile.ns + "theme" );
|
|
$btn.removeClass( "ui-btn-down-" + theme ).addClass( "ui-btn-up-" + theme );
|
|
}
|
|
},
|
|
"vmouseover focus": function( event ) {
|
|
var btn = closestEnabledButton( event.target ),
|
|
$btn, theme;
|
|
|
|
if ( btn ) {
|
|
$btn = $( btn );
|
|
theme = $btn.attr( "data-" + $.mobile.ns + "theme" );
|
|
$btn.removeClass( "ui-btn-up-" + theme ).addClass( "ui-btn-hover-" + theme );
|
|
}
|
|
},
|
|
"vmouseout blur": function( event ) {
|
|
var btn = closestEnabledButton( event.target ),
|
|
$btn, theme;
|
|
|
|
if ( btn ) {
|
|
$btn = $( btn );
|
|
theme = $btn.attr( "data-" + $.mobile.ns + "theme" );
|
|
$btn.removeClass( "ui-btn-hover-" + theme + " ui-btn-down-" + theme ).addClass( "ui-btn-up-" + theme );
|
|
}
|
|
}
|
|
});
|
|
|
|
attachEvents = null;
|
|
};
|
|
|
|
//links in bars, or those with data-role become buttons
|
|
//auto self-init widgets
|
|
$( document ).bind( "pagecreate create", function( e ){
|
|
|
|
$( ":jqmData(role='button'), .ui-bar > a, .ui-header > a, .ui-footer > a, .ui-bar > :jqmData(role='controlgroup') > a", e.target )
|
|
.not( ".ui-btn, :jqmData(role='none'), :jqmData(role='nojs')" )
|
|
.buttonMarkup();
|
|
});
|
|
|
|
})( jQuery );
|