/** * jQuery UI Labs - buttons * - for experimental use only - * this is the core of all ui-button plugins * Copyleft (l) 2009 Jonathan gotti aka malko < jgotti at jgotti dot org > * Dual licensed under the MIT and GPL licenses. * http://docs.jquery.com/License * Depends: * ui.core.js * ui.classnameoptions.js */ (function($){ // base ui-button plugin $.widget("ui.button",$.extend({},$.ui.classnameoptions,{ _originalClass: '', _originalElement:null, _elmt_icon:null, _elmt_iconContainer:null, _elmt_label:null, _iconIsImage:false, _iconBeforeLabel:true, _buttonset:null, _orientationValue:'', _sizeValue:'', _cbToggle:null, _init:function(){ var self = this; //-- should think about aborting or not init when ui-button-none, ui-buttonset are used. if( this.element.attr('class').match(/(?:^|\s+)ui-button(set|-none(\s|$))/) ){ return $.widget.prototype.destroy.apply(this, arguments); } self._originalClass = self.element.attr('class'); // read inline options from class attribute (that can't be null!!!) if( $.ui.classnameoptions){ var inlineOptions=self._readClassNameOpts({buttonMode:'|toggle',active:'|active',size:'|auto|tiny|small|normal|big|huge',orientation:'|auto|[trbli]',icon:'|[a-zA-Z0-9_-]+'}) if( inlineOptions.icon && ! inlineOptions.icon.match(/\.(gif|png|jpe?g)$/i)){ inlineOptions.icon = 'ui-icon-'+inlineOptions.icon; } self._mergeOpts(inlineOptions); } self.element.addClass($.ui.button.classes.base+' ui-widget '); if(! self.element.attr('tabindex')){ self.element.attr('tabindex',0); } // preapre wrapers elements self._wrapLabel(); self._wrapIcon(); // detect some toggle markup options if( self.element.hasClass('toggle') || self.element.hasClass($.ui.button.classes.modeToggle)){ self.options.buttonMode = 'toggle'; } if( self.element.hasClass('active') || self.element.hasClass($.ui.button.classes.stateActive)){ self.options.active = true; } // apply some settings if(self._applyOpts){ self._applyOpts(['size','orientation','icon','overrideDefaultState']) ._applyOpts(['buttonMode','active','label'],true); }else{ self._setData('size',self.options.size); self._setData('orientation',self.options.orientation); self._setData('icon',self.options.icon); self._setData('overrideDefaultState',self.options.overrideDefaultState); if( self.options.buttonMode ){ self._setData('buttonMode',self.options.buttonMode); if( self.options.active ){ self._setData('active',self.options.active); } } if( self.label !== null){ self._setData('label',self.options.label); } } if( null!==self.options.disabled ){ self._setData('disabled',self.options.disabled); }else if( self.element.attr('disabled') ){ self._setData('disabled',true); } if(! $.support.style){ this.element.addClass($.ui.button.classes.blockFix); } // auto initialisation of button set on last buttonset element if( self.options.checkButtonset){ var buttonset = self.element.parent('[class*=ui-buttonset]'); //@todo replaced by $.ui.buttonset.base when will exist if( buttonset.length > 0){ self._buttonset = buttonset; if( this.element.is(':last-child')){ buttonset.buttonset(); } } } if(! self.element.attr('class').match(/ui-corner-[a-z]+/) ){ self.element.addClass('ui-corner-all'); } self._bindCommonEvents(); return this; }, //--- events ---// _bindCommonEvents: function(){ var self = this; var _mouseenter= function(){ var elmt = $(this); if(! elmt.button('option','disabled') ){ elmt.addClass($.ui.button.classes.stateHover); } }; var _mouseleave= function(){ //$(this).removeClass($.ui.button.classes.stateHover+' '+$.ui.button.classes.stateDown); // changes by cbraun: fix onMouseOut-Class-EventHandler $(this).removeClass($.ui.button.classes.stateHover); $(this).removeClass($.ui.button.classes.stateDown); $(this).removeClass($.ui.button.classes.stateFocus); }; var _pressed= function(e){ var elmt = $(this); if( elmt.button('option','disabled') ){ return false; } if( e.type==='mousedown' || (e.type==='keydown' && (e.keyCode===$.ui.keyCode.ENTER || e.keyCode===$.ui.keyCode.SPACE || e.keyCode===$.ui.keyCode.NUMPAD_ENTER)) ){ elmt.addClass($.ui.button.classes.stateDown); if( e.type==='keydown'){ if(! ($.browser.opera && e.keyCode===$.ui.keyCode.ENTER)){ // i Hate this dirty browser detection but not doing this goes to weird behaviour on opera. self.element.click(); } return false; //avoid keypress event when firing click() or we'll end up with doubling the click event on buttons under ie browsers } } }; var _released=function(event){ var elmt = $(this); // release event should not do anything if actual element wasn't pressed before (we probably have dragged the mouse from another element.) if(! elmt.hasClass($.ui.button.classes.stateDown) ) return false; $(this).removeClass($.ui.button.classes.stateDown); }; var _focus=function(event){ var elmt = $(this); if( elmt.button('option','disabled') ){ return false; } elmt.addClass($.ui.button.classes.stateFocus); }; var _blur= function(){ $(this).removeClass($.ui.button.classes.stateFocus+' '+$.ui.button.classes.stateDown); }; var events = { mouseenter:_mouseenter, mouseleave:_mouseleave, mousedown:_pressed, keydown:_pressed, mouseup:_released, keyup:_released, focus:_focus, blur:_blur }; var eventName = ''; for( eventName in events){ self.element.bind(eventName+'.uibutton',events[eventName]); } }, //--- markup ---// _setIcon:function(){ var ico = this._getData('icon'); this._iconIsImage =( ico.match(/\.(jpe?g|png|gif|ico)$/i) )?true:false; if(null !== this._elmt_icon){ this._elmt_icon.remove(); } if( '' === ico || null === ico){ this._elmt_icon = null; this._elmt_iconContainer.hide(); ico='ui-icon-none'; } if( this._iconIsImage){ this._elmt_icon=$(''); }else{ this._elmt_icon=$(''); } if(this._elmt_icon.length && ! $.support.style){ this._elmt_icon.css({margin:0}); } this._elmt_iconContainer.append(this._elmt_icon); this._elmt_iconContainer.show(); }, _wrapIcon:function(){ if( null!==this._elmt_iconContainer){ return; } this._elmt_iconContainer=$(''); this.element.append(this._elmt_iconContainer); }, _wrapLabel:function(){ if( null!==this._elmt_label ){ return; } var _elmt_label=$(''); if( this.element.html().replace(/\s/,'').length > 0){ this.element.wrapInner(_elmt_label); }else{ this.element.append(_elmt_label.append(' ').addClass($.ui.button.classes.wrapperLabelEmpty)); } this._elmt_label = this.element.find('>.'+$.ui.button.classes.wrapperLabel).disableSelection(); }, _checkElmtPos: function(){ var actual = this.element.find('span:first').is('.'+$.ui.button.classes.wrapperIcon)?true:false; if( actual==this._iconBeforeLabel) return this; if( this._iconBeforeLabel){ this.element.prepend(this._elmt_iconContainer); }else{ this.element.append(this._elmt_iconContainer); } return this; }, //--- applying options settings ---// _setData:function(key,value){ var self = this; switch(key){ case 'icon': var res = $.widget.prototype._setData.apply(self, arguments); this._setIcon(); return res; break; case 'label': // @todo should think of a way to revert to original label if changed if( null!==value){ if( ''===value){ self._elmt_label.addClass($.ui.button.classes.wrapperLabelEmpty).html(' '); }else{ self._elmt_label.removeClass($.ui.button.classes.wrapperLabelEmpty) .empty().append(value); } } break; case 'orientation': if(! value){ value = 'auto'; } var applyValue = (value==='i'?'auto':value); if( applyValue==='auto' && self._buttonset ){ applyValue = self._buttonset.buttonset('option','orientation'); } self._orientationValue = (applyValue=='auto'||applyValue=='i')?'l':applyValue; if( value==='i' || applyValue==='i'){ self._setData('label',''); } self._rmExpClass($.ui.button.classes.base+'-orientation-*',$.ui.button.classes.base+'-orientation-'+self._orientationValue); self._iconBeforeLabel=( self._orientationValue=='b' || self._orientationValue=='r')?false:true; self._checkElmtPos(); break; case 'size': self._sizeValue = value=='auto'?'normal':value; self._rmExpClass($.ui.button.classes.base+'-size-*',$.ui.button.classes.base+'-size-'+self._sizeValue); break; case 'disabled': self.element.attr('disabled',value?true:false); break; case 'buttonMode': switch(value){ case 'toggle': if(! self._cbToggle){ self._cbToggle = function(event){return self.toggle(event);}; } self.element.addClass($.ui.button.classes.modeToggle); self.element.bind('click.uibutton',self._cbToggle); break; default: if(! self._cbToggle){ self.element.unbind('click.uibutton',self._cbToggle); self.element.removeClass($.ui.button.classes.modeToggle); } } break; case 'active': if( self._getData('buttonMode') !== 'toggle' || self._getData('disabled') ) return false; value = value?true:false; self.element.toggleClass($.ui.button.classes.stateActive+' active',value); self._trigger('setactive',0,{active:value}); break; case 'overrideDefaultState': if( value===false){ value = $.ui.button.classes.stateDefault; } self.element.removeClass(this._getData('overrideDefaultState')).addClass(value); break; } return $.widget.prototype._setData.apply(this, arguments); }, importButtonSetSettings:function(buttonSet){ var self=this; self._buttonset = buttonSet.element; var buttonSetSize = buttonSet._getData('size'); var buttonSetOrientation = buttonSet._getData('orientation'); if( self._getData('size')==='auto' && buttonSetSize !== 'auto'){ self._setData('size',buttonSetSize); self.options.size='auto'; } var orientationOption = self._getData('orientation'); if( orientationOption==='auto' || orientationOption==='i' && buttonSetOrientation !== 'auto'){ self._setData('orientation',buttonSetOrientation); self.options.orientation=orientationOption; } var isOnlyChild = self.element.is(':only-child'); if( self.element.is(':first-child') && ! isOnlyChild ){ self._rmExpClass('ui-corner-*','ui-corner-left'); }else if(self.element.is(':last-child') && ! isOnlyChild ){ self._rmExpClass('ui-corner-*','ui-corner-right'); }else{ self._rmExpClass('ui-corner-*','ui-corner-'+(isOnlyChild?'all':'none')); } }, //--- public methods ---// destroy: function(){ if( this._originalElement ){ this.element.replaceWith(this._originalElement); }else{ this.element.unbind('.uibutton').attr('class',this._originalClass); this._elmt_iconContainer.remove(); this._elmt_label.contents().insertAfter(this._elmt_label) this._elmt_label.remove(); } return $.widget.prototype.destroy.apply(this, arguments); }, toggle: function(event){ this._setData('active',this._getData('active')?false:true); return this; }, /** * remove matching class names from element and eventually add new class on given element (default to widget.element) */ _rmExpClass:function(exp,add,elmt){ elmt=(!elmt)?this.element:$(elmt); exp = new RegExp('(?:^|\\s)'+exp.replace(/\*/g,'[a-zA-Z_0-9-]*')+'(?=$|\\s)','g'); elmt.attr('class',elmt.attr('class').replace(exp,'')); if( undefined!==add ){ elmt.addClass(add); } return this; } })); $.extend($.ui.button, { version: "@VERSION", defaults:{ size:'auto', orientation:'auto', icon:'', label:null, buttonMode:null, disabled:null, active:false, // set toggle button to active state checkButtonset:false, // check for .ui-buttonset parent and trigger parent buttonset rendering if found overrideDefaultState:false // any string to used in place of classes.stateDefault (empty string may be used for no state class at all) }, classes:{ base: 'ui-button', wrapperLabel: 'ui-button-label', wrapperLabelEmpty: 'ui-button-label-empty', wrapperIcon: 'ui-button-icon', wrapperIconEmpty: 'ui-icon-none', modeToggle: 'ui-button-toggle', modeSplit: 'ui-button-split', modeMenu: 'ui-button-menu', modeSplit: 'ui-button-split', stateDefault: 'ui-state-default', stateActive: 'ui-state-active', stateHover: 'ui-state-hover', stateDown: 'ui-state-down', // must be different than active! stateFocus: 'ui-state-focus', blockFix: 'ui-button-inlineBlockFix' } });//*/ })(jQuery);