Explorar el Código

added styles for hover on mass operation checkbox, fixed incorrect blink behavior (issue #41)

larsz hace 14 años
padre
commit
5f83af2fa1

+ 18 - 10
web/css/main.css

@@ -3,7 +3,7 @@ Title  : Vesta
 Author : Eugen Lobicov, eugen.lobicov@gmail.com 
 
 created : November 27, 2009
-last updated : January 26, 2012
+last updated : January 30, 2012
 - - - - - - - - - - - - - - - - - - */
 
 html{
@@ -578,24 +578,26 @@ input::-moz-focus-inner{
 	}
 	
 .checkbox-selector,
-.context-actions{
+.context-actions,
+.checkbox-selector .ui-checkbox{
 	display:-moz-inline-stack;
 	display: inline-block;
 	zoom: 1;
 	*display: inline;
 	vertical-align:top;
 	}
-	.checkbox-selector .checkbox{
-		display:block;
-		float:left;
+	.ui-helper-hidden-accessible{
+		display:none;
+	}
+	.checkbox-selector span.ui-checkbox{
+		float:none;
 		width:11px;
 		height:11px;
-		margin:2px 5px 0 0;
-		background:url(../images/checkbox-selector.png) no-repeat;
+		margin:2px 2px 0 0;
+		background:url(../images/checkbox-selector-2012-01-29.png) no-repeat;
 		cursor:pointer;
 	}
 	.checkbox-selector .selector-title{
-		float:left;
 		font-size:11px;
 		line-height:15px;
 		text-transform:uppercase;
@@ -603,8 +605,14 @@ input::-moz-focus-inner{
 		cursor:pointer;
 		white-space:nowrap;
 	}
-	.checkbox-selector:hover .checkbox{
-		background-position:0 -90px;
+	.checkbox-selector span.ui-checkbox-hover{
+		background-position:0 -20px;
+	}
+	.checkbox-selector span.ui-checkbox-state-checked{
+		background-position:0 -40px;
+	}
+	.checkbox-selector span.ui-checkbox-state-checked-hover{
+		background-position:0 -60px;
 	}
 	.checkbox-selector .selector-title:hover{
 		color:#2ea8bd;	

BIN
web/images/checkbox-selector-2012-01-29.png


+ 10 - 2
web/index.html

@@ -209,8 +209,8 @@
                     <div class="row-filters cc">
 						<div id="batch-processor" class="b-row-selector">
 							<div class="checkbox-selector cc">
-								<input class="styled do_action_toggle_batch_selector" autocomplete="off" type="checkbox" value="" />
-								<span class="selector-title">None</span>
+								<input id="select-rows" class="cust-checkbox do_action_toggle_batch_selector" autocomplete="off" type="checkbox" value="" />
+								<label for="select-rows" class="selector-title">None</label>
 							</div>
 							<div class="context-actions c-s-box">
 								<div class="b-cust-sel complex-select c-s-opt">
@@ -251,6 +251,14 @@
         <script type="text/javascript" src="js/lib/cookie.js"></script>
         <script type="text/javascript" src="js/lib/jquery-1.6.1.js"></script>
         <script type="text/javascript" src="js/lib/jquery-ui-1.8.13.custom.min.js"></script>
+        
+        <!-- Larsz's include for custom checkboxes -->
+        <script type="text/javascript" src="js/lib/jquery.ui.widget.js"></script>
+        <script type="text/javascript" src="js/lib/jquery.usermode.js"></script>
+        <script type="text/javascript" src="js/lib/ui.checkbox.js"></script>
+        <script type="text/javascript" src="js/ui.checkbox.init.js"></script>
+        <!-- // Larsz's include for custom checkboxes -->
+
         <script type="text/javascript" src="js/lib/auth.js"></script>
         <script type="text/javascript" src="js/date_format.js"></script>
         <script type="text/javascript" src="js/lib/custom-form-elements.js"></script>

+ 236 - 0
web/js/lib/jquery.ui.widget.js

@@ -0,0 +1,236 @@
+/*!
+ * jQuery UI Widget 1.8
+ *
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Widget
+ */
+(function( $ ) {
+
+var _remove = $.fn.remove;
+
+$.fn.remove = function( selector, keepData ) {
+	return this.each(function() {
+		if ( !keepData ) {
+			if ( !selector || $.filter( selector, [ this ] ).length ) {
+				$( "*", this ).add( this ).each(function() {
+					$( this ).triggerHandler( "remove" );
+				});
+			}
+		}
+		return _remove.call( $(this), selector, keepData );
+	});
+};
+
+$.widget = function( name, base, prototype ) {
+	var namespace = name.split( "." )[ 0 ],
+		fullName;
+	name = name.split( "." )[ 1 ];
+	fullName = namespace + "-" + name;
+
+	if ( !prototype ) {
+		prototype = base;
+		base = $.Widget;
+	}
+
+	// create selector for plugin
+	$.expr[ ":" ][ fullName ] = function( elem ) {
+		return !!$.data( elem, name );
+	};
+
+	$[ namespace ] = $[ namespace ] || {};
+	$[ namespace ][ name ] = function( options, element ) {
+		// allow instantiation without initializing for simple inheritance
+		if ( arguments.length ) {
+			this._createWidget( options, element );
+		}
+	};
+
+	var basePrototype = new base();
+	// we need to make the options hash a property directly on the new instance
+	// otherwise we'll modify the options hash on the prototype that we're
+	// inheriting from
+//	$.each( basePrototype, function( key, val ) {
+//		if ( $.isPlainObject(val) ) {
+//			basePrototype[ key ] = $.extend( {}, val );
+//		}
+//	});
+	basePrototype.options = $.extend( {}, basePrototype.options );
+	$[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
+		namespace: namespace,
+		widgetName: name,
+		widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
+		widgetBaseClass: fullName
+	}, prototype );
+
+	$.widget.bridge( name, $[ namespace ][ name ] );
+};
+
+$.widget.bridge = function( name, object ) {
+	$.fn[ name ] = function( options ) {
+		var isMethodCall = typeof options === "string",
+			args = Array.prototype.slice.call( arguments, 1 ),
+			returnValue = this;
+
+		// allow multiple hashes to be passed on init
+		options = !isMethodCall && args.length ?
+			$.extend.apply( null, [ true, options ].concat(args) ) :
+			options;
+
+		// prevent calls to internal methods
+		if ( isMethodCall && options.substring( 0, 1 ) === "_" ) {
+			return returnValue;
+		}
+
+		if ( isMethodCall ) {
+			this.each(function() {
+				var instance = $.data( this, name ),
+					methodValue = instance && $.isFunction( instance[options] ) ?
+						instance[ options ].apply( instance, args ) :
+						instance;
+				if ( methodValue !== instance && methodValue !== undefined ) {
+					returnValue = methodValue;
+					return false;
+				}
+			});
+		} else {
+			this.each(function() {
+				var instance = $.data( this, name );
+				if ( instance ) {
+					if ( options ) {
+						instance.option( options );
+					}
+					instance._init();
+				} else {
+					$.data( this, name, new object( options, this ) );
+				}
+			});
+		}
+
+		return returnValue;
+	};
+};
+
+$.Widget = function( options, element ) {
+	// allow instantiation without initializing for simple inheritance
+	if ( arguments.length ) {
+		this._createWidget( options, element );
+	}
+};
+
+$.Widget.prototype = {
+	widgetName: "widget",
+	widgetEventPrefix: "",
+	options: {
+		disabled: false
+	},
+	_createWidget: function( options, element ) {
+		// $.widget.bridge stores the plugin instance, but we do it anyway
+		// so that it's stored even before the _create function runs
+		this.element = $( element ).data( this.widgetName, this );
+		this.options = $.extend( true, {},
+			this.options,
+			$.metadata && $.metadata.get( element )[ this.widgetName ],
+			options );
+
+		var self = this;
+		this.element.bind( "remove." + this.widgetName, function() {
+			self.destroy();
+		});
+
+		this._create();
+		this._init();
+	},
+	_create: function() {},
+	_init: function() {},
+
+	destroy: function() {
+		this.element
+			.unbind( "." + this.widgetName )
+			.removeData( this.widgetName );
+		this.widget()
+			.unbind( "." + this.widgetName )
+			.removeAttr( "aria-disabled" )
+			.removeClass(
+				this.widgetBaseClass + "-disabled " +
+				this.namespace + "-state-disabled" );
+	},
+
+	widget: function() {
+		return this.element;
+	},
+
+	option: function( key, value ) {
+		var options = key,
+			self = this;
+
+		if ( arguments.length === 0 ) {
+			// don't return a reference to the internal hash
+			return $.extend( {}, self.options );
+		}
+
+		if  (typeof key === "string" ) {
+			if ( value === undefined ) {
+				return this.options[ key ];
+			}
+			options = {};
+			options[ key ] = value;
+		}
+
+		$.each( options, function( key, value ) {
+			self._setOption( key, value );
+		});
+
+		return self;
+	},
+	_setOption: function( key, value ) {
+		this.options[ key ] = value;
+
+		if ( key === "disabled" ) {
+			this.widget()
+				[ value ? "addClass" : "removeClass"](
+					this.widgetBaseClass + "-disabled" + " " +
+					this.namespace + "-state-disabled" )
+				.attr( "aria-disabled", value );
+		}
+
+		return this;
+	},
+
+	enable: function() {
+		return this._setOption( "disabled", false );
+	},
+	disable: function() {
+		return this._setOption( "disabled", true );
+	},
+
+	_trigger: function( type, event, data ) {
+		var callback = this.options[ type ];
+
+		event = $.Event( event );
+		event.type = ( type === this.widgetEventPrefix ?
+			type :
+			this.widgetEventPrefix + type ).toLowerCase();
+		data = data || {};
+
+		// copy original event properties over to the new event
+		// this would happen if we could call $.event.fix instead of $.Event
+		// but we don't have a way to force an event to be fixed multiple times
+		if ( event.originalEvent ) {
+			for ( var i = $.event.props.length, prop; i; ) {
+				prop = $.event.props[ --i ];
+				event[ prop ] = event.originalEvent[ prop ];
+			}
+		}
+
+		this.element.trigger( event, data );
+
+		return !( $.isFunction(callback) &&
+			callback.call( this.element[0], event, data ) === false ||
+			event.isDefaultPrevented() );
+	}
+};
+
+})( jQuery );

+ 75 - 0
web/js/lib/jquery.usermode.js

@@ -0,0 +1,75 @@
+/**
+ * @author trixta
+ */
+(function($){
+	$.userMode = (function(){
+		var userBg, 
+			timer, 
+			testDiv,
+			boundEvents = 0;
+		
+		function testBg(){
+			testDiv = testDiv || $('<div></div>').css({position: 'absolute', left: '-999em', top: '-999px', width: '0px', height: '0px'}).appendTo('body');
+			var black = $.curCSS( testDiv.css({backgroundColor: '#000000'})[0], 'backgroundColor', true),
+				white = $.curCSS( testDiv.css({backgroundColor: '#ffffff'})[0], 'backgroundColor', true),
+				newBgStatus = (black === white || white === 'transparent');
+			if(newBgStatus != userBg){
+				userBg = newBgStatus;
+				$.event.trigger('_internalusermode');
+			}
+			return userBg;
+		}
+		
+		function init(){
+			testBg();
+			timer = setInterval(testBg, 3000);
+		}
+		
+		function stop(){
+			clearInterval(timer);
+			testDiv.remove();
+			testDiv = null;
+		}
+		
+		$.event.special.usermode = {
+			setup: function(){
+				(!boundEvents && init());
+				boundEvents++;
+				var jElem = $(this)
+					.bind('_internalusermode', $.event.special.usermode.handler);
+				//always trigger
+				setTimeout(function(){
+					jElem.triggerHandler('_internalusermode');
+				}, 1);
+                return true;
+            },
+			teardown: function(){
+                boundEvents--;
+				(!boundEvents && stop());
+				$(this).unbind('_internalusermode', $.event.special.usermode.handler);
+                return true;
+            },
+            handler: function(e){
+                e.type = 'usermode';
+				e.disabled = !userBg;
+				e.enabled = userBg;
+                return jQuery.event.handle.apply(this, arguments);
+            }
+		};
+		
+		return {
+			get: testBg
+		};
+		
+	})();
+	
+	$.fn.userMode = function(fn){
+		return this[(fn) ? 'bind' : 'trigger']('usermode', fn);
+	};
+	
+	$(function(){
+		$('html').userMode(function(e){
+			$('html')[e.enabled ? 'addClass' : 'removeClass']('hcm');
+		});
+	});
+})(jQuery);

+ 276 - 0
web/js/lib/ui.checkbox.js

@@ -0,0 +1,276 @@
+/**
+ * @author alexander.farkas
+ * @version 1.4.3
+ */
+(function($){
+	
+	var supportsValidity;
+	(function(){
+		if(!$.prop || supportsValidity){return;}
+		var supportTest = function(){
+			supportsValidity = !!$('<input />').prop('validity');
+		};
+		supportTest();
+		$(supportTest);
+	})();
+	
+    $.widget('ui.checkBox', {
+		options: {
+	        hideInput: true,
+			addVisualElement: true,
+			addLabel: true
+	    },
+        _create: function(){
+            var that = this, 
+				opts = this.options
+			;
+			
+			if(!this.element.is(':radio,:checkbox')){
+				if(this.element[0].elements && $.nodeName(this.element[0], 'form')){
+					$(this.element[0].elements).filter(':radio,:checkbox').checkBox(opts);
+				}
+				return false;
+			}
+			
+			this._proxiedReflectUI = $.proxy(this, 'reflectUI');
+			
+            this.labels = $([]);
+			
+            this.checkedStatus = false;
+			this.disabledStatus = false;
+			this.hoverStatus = false;
+            
+			this.inputType = this.element[0].type;
+            this.radio = this.inputType == 'radio';
+					
+            this.visualElement = $([]);
+            if (opts.hideInput) {
+				this.element.addClass('ui-helper-hidden-accessible');
+				if(opts.addVisualElement){
+					this.visualElement = $('<span />')
+						.addClass('ui-'+this.inputType)
+					;
+					this.element.after(this.visualElement[0]);
+				}
+            }
+			
+			if(opts.addLabel){
+				var id = this.element[0].id;
+				if(id){
+					this.labels = $('label[for="' + id + '"]', this.element[0].form || this.element[0].ownerDocument).add(this.element.parent('label'));
+				}
+				if(!this.labels[0]){
+					this.labels = this.element.closest('label', this.element[0].form);
+				}
+				this.labels.addClass(this.radio ? 'ui-radio' : 'ui-checkbox');
+			}
+			
+			this.visualGroup = this.visualElement.add(this.labels);
+			
+			this._addEvents();
+			
+			this.initialized = true;
+            this.reflectUI({type: 'initialreflect'});
+			return undefined;
+        },
+		_addEvents: function(){
+			var that 		= this, 
+			
+				opts 		= this.options,
+					
+				toggleHover = function(e){
+					if(that.disabledStatus){
+						return false;
+					}
+					that.hover = (e.type == 'focus' || e.type == 'mouseenter');
+					if(e.type == 'focus'){
+						that.visualGroup.addClass(that.inputType +'-focused');
+					} else if(e.type == 'blur'){
+						that.visualGroup.removeClass(that.inputType +'-focused');
+					}
+					that._changeStateClassChain();
+					return undefined;
+				}
+			;
+			
+			this.element
+				.bind('click.checkBox invalid.checkBox', this._proxiedReflectUI)
+				.bind('focus.checkBox blur.checkBox', toggleHover)
+			;
+			if (opts.hideInput){
+				this.element
+					.bind('usermode', function(e){
+	                    (e.enabled &&
+	                        that.destroy.call(that, true));
+	                })
+				;
+            }
+			if(opts.addVisualElement){
+				this.visualElement
+					.bind('click.checkBox', function(e){
+						that.element[0].click();
+						return false;
+					})
+				;
+			}
+			
+			this.visualGroup.bind('mouseenter.checkBox mouseleave.checkBox', toggleHover);
+			
+		},
+		_changeStateClassChain: function(){
+			var allElements = this.labels.add(this.visualElement),
+				stateClass 	= '',
+				baseClass 	= 'ui-'+ this.inputType
+			;
+				
+			if(this.checkedStatus){
+				stateClass += '-checked'; 
+				allElements.addClass(baseClass+'-checked');
+			} else {
+				allElements.removeClass(baseClass+'-checked');
+			}
+			
+			if(this.disabledStatus){
+				stateClass += '-disabled'; 
+				allElements.addClass(baseClass+'-disabled');
+			} else {
+				allElements.removeClass(baseClass+'-disabled');
+			}
+			if(this.hover){
+				stateClass += '-hover'; 
+				allElements.addClass(baseClass+'-hover');
+			} else {
+				allElements.removeClass(baseClass+'-hover');
+			}
+			
+			baseClass += '-state';
+			if(stateClass){
+				stateClass = baseClass + stateClass;
+			}
+			
+			function switchStateClass(){
+				var classes = this.className.split(' '),
+					found = false;
+				$.each(classes, function(i, classN){
+					if(classN.indexOf(baseClass) === 0){
+						found = true;
+						classes[i] = stateClass;
+						return false;
+					}
+					return undefined;
+				});
+				if(!found){
+					classes.push(stateClass);
+				}
+				this.className = classes.join(' ');
+			}
+			
+			this.visualGroup.each(switchStateClass);
+		},
+        destroy: function(onlyCss){
+            this.element.removeClass('ui-helper-hidden-accessible');
+			this.visualElement.addClass('ui-helper-hidden');
+            if (!onlyCss) {
+                var o = this.options;
+                this.element.unbind('.checkBox');
+				this.visualElement.remove();
+                this.labels
+					.unbind('.checkBox')
+					.removeClass('ui-state-hover ui-state-checked ui-state-disabled')
+				;
+            }
+        },
+		
+        disable: function(status){
+			if(status === undefined){
+				status = true;
+			}
+            this.element[0].disabled = status;
+            this.reflectUI({type: 'manuallydisabled'});
+        },
+		
+        enable: function(){
+            this.element[0].disabled = false;
+            this.reflectUI({type: 'manuallyenabled'});
+        },
+		
+        toggle: function(e){
+            this.changeCheckStatus(!(this.element.is(':checked')), e);
+        },
+		
+        changeCheckStatus: function(status, e){
+            if(e && e.type == 'click' && this.element[0].disabled){
+				return false;
+			}
+			this.element[0].checked = !!status;
+            this.reflectUI(e || {
+                type: 'changecheckstatus'
+            });
+			return undefined;
+        },
+        propagate: function(n, e, _noGroupReflect){
+			if(!e || e.type != 'initialreflect'){
+				if (this.radio && !_noGroupReflect) {
+					var elem = this.element[0];
+					//dynamic
+	                $('[name="'+ elem.name +'"]', elem.form || elem.ownerDocument).checkBox('reflectUI', e, true);
+						
+	            }
+	            return this._trigger(n, e, {
+	                options: this.options,
+	                checked: this.checkedStatus,
+	                labels: this.labels,
+					disabled: this.disabledStatus
+	            });
+			}
+			return undefined;
+        },
+		changeValidityState: function(){
+			if(supportsValidity){
+				this.visualGroup[ !this.element.prop('willValidate') || (this.element.prop('validity') || {valid: true}).valid ? 'removeClass' : 'addClass' ](this.inputType +'-invalid');
+			}
+		},
+        reflectUI: function(e){
+			
+            var oldChecked 			= this.checkedStatus, 
+				oldDisabledStatus 	= this.disabledStatus
+			;
+            					
+			this.disabledStatus = this.element.is(':disabled');
+			this.checkedStatus = this.element.is(':checked');
+			if(!e || e.type !== 'initialreflect'){
+				this.changeValidityState();
+			}
+			
+			if (this.disabledStatus != oldDisabledStatus || this.checkedStatus !== oldChecked) {
+				this._changeStateClassChain();
+				
+				(this.disabledStatus != oldDisabledStatus &&
+					this.propagate('disabledchange', e));
+				
+				(this.checkedStatus !== oldChecked &&
+					this.propagate('change', e));
+			}
+            
+        }
+    });
+		
+	if($.propHooks){
+		$.each({checked: 'changeCheckStatus', disabled: 'disable'}, function(name, fn){
+			//be hook friendly
+			if(!$.propHooks[name]){
+				$.propHooks[name] = {};
+			}
+			var oldSetHook = $.propHooks[name].set;
+			
+			$.propHooks[name].set = function(elem, value){
+				var widget = $.data(elem, 'checkBox');
+				if(widget){
+					widget[fn](!!value);
+				}
+				return oldSetHook && oldSetHook(elem, value) ;
+			};
+			
+		});
+	}
+})(jQuery);

+ 3 - 0
web/js/ui.checkbox.init.js

@@ -0,0 +1,3 @@
+$(document).ready(function(){
+	$('.cust-checkbox').checkBox();
+});