zoukankan      html  css  js  c++  java
  • [easyui] datebox源码阅读. 批注

    jquery.datebox.js

    文件.

    (function($){
    	/**
    	 * create date box
    	 */
    	function createBox(target){
    
    		var state = $.data(target, 'datebox');
    		var opts = state.options;
    		
    		//在'onShowPanel'触发时会执行一系列的函数.
    		$(target).addClass('datebox-f').combo($.extend({}, opts, {
    			onShowPanel:function(){
    				bindEvents(this);
    				setButtons(this);
    				setCalendar(this);
    				setValue(this, $(this).datebox('getText'), true);
    				opts.onShowPanel.call(this);
    			}
    		}));
    		
    		/**
    		 * if the calendar isn't created, create it.
    		 * 创建日历
    		 */
    		if (!state.calendar){
    			
    			var panel = $(target).combo('panel').css('overflow','hidden');
    			
    			//什么时候destroy呢?
    			panel.panel('options').onBeforeDestroy = function(){
    				var c = $(this).find('.calendar-shared');
    				if (c.length){
    					// pholder -> ? -> calendar-pholder 是easyui在下文自己定义的.
    					c.insertBefore(c[0].pholder);
    				}
    			};
    			
    			//承载日历的dom对象.
    			var cc = $('<div class="datebox-calendar-inner"></div>').prependTo(panel);
    			
    			if (opts.sharedCalendar){
    				var c = $(opts.sharedCalendar);
    				if (!c[0].pholder){
    					c[0].pholder = $('<div class="calendar-pholder" style="display:none"></div>').insertAfter(c);
    				}
    				c.addClass('calendar-shared').appendTo(cc);
    				if (!c.hasClass('calendar')){
    					c.calendar();
    				}
    				state.calendar = c;
    			} else {
    				state.calendar = $('<div></div>').appendTo(cc).calendar();
    			}
    
    			//点击日历后,隐藏日历面板.
    			$.extend(state.calendar.calendar('options'), {
    				fit:true,
    				border:false,
    				onSelect:function(date){
    					var target = this.target;
    					var opts = $(target).datebox('options');
    					setValue(target, opts.formatter.call(target, date));
    					$(target).combo('hidePanel');
    					opts.onSelect.call(target, date);
    				}
    			});
    		}
    
    		$(target).combo('textbox').parent().addClass('datebox');
    		$(target).datebox('initValue', opts.value);
    		
    		//为按钮绑定点击事件.
    		function bindEvents(target){
    			var opts = $(target).datebox('options');
    			var panel = $(target).combo('panel');
    			panel.unbind('.datebox').bind('click.datebox', function(e){
    				//'datebox-button-a' -> 就是下面setButtons方法中的按钮的css样式.
    				if ($(e.target).hasClass('datebox-button-a')){
    					var index = parseInt($(e.target).attr('datebox-button-index'));
    					opts.buttons[index].handler.call(e.target, target);
    				}
    			});
    		}
    
    		//设置'Today','Close'两个按钮. -> 新版本应该是允许用户增加按钮的.
    		function setButtons(target){
    			var panel = $(target).combo('panel');
    			if (panel.children('div.datebox-button').length){return}
    			var button = $('<div class="datebox-button">'
    							+'<table cellspacing="0" cellpadding="0" style="100%">'
    							+'<tr></tr></table></div>').appendTo(panel);
    			var tr = button.find('tr');
    			for(var i=0; i<opts.buttons.length; i++){
    				var td = $('<td></td>').appendTo(tr);
    				var btn = opts.buttons[i];
    				var t = $('<a class="datebox-button-a" href="javascript:void(0)"></a>')
    						.html($.isFunction(btn.text) ? btn.text(target) : btn.text).appendTo(td);
    				t.attr('datebox-button-index', i);
    			}
    			//为按钮父元素td设置百分比.->想象"'Today','Close'"父td各占50%
    			tr.find('td').css('width', (100/opts.buttons.length)+'%');
    		}
    		
    		//
    		function setCalendar(target){
    			var panel = $(target).combo('panel');
    			var cc = panel.children('div.datebox-calendar-inner');
    			
    			//_outerWidth 在jquery.parser.js中有定义.
    			panel.children()._outerWidth(panel.width());
    			state.calendar.appendTo(cc);
    			state.calendar[0].target = target;
    			if (opts.panelHeight != 'auto'){
    				var height = panel.height();
    				panel.children().not(cc).each(function(){
    					height -= $(this).outerHeight();
    				});
    				cc._outerHeight(height);
    			}
    			state.calendar.calendar('resize');
    		}
    	}
    	
    	/**
    	 * called when user inputs some value in text box
    	 * 当给文本框赋值时->触发此动作->譬如:粘贴"2015-01-07"
    	 */
    	function doQuery(target, q){
    		setValue(target, q, true);
    	}
    	
    	/**
    	 * called when user press enter key
    	 */
    	function doEnter(target){
    		var state = $.data(target, 'datebox');
    		var opts = state.options;
    		var current = state.calendar.calendar('options').current;
    		if (current){
    			setValue(target, opts.formatter.call(target, current));
    			$(target).combo('hidePanel');
    		}
    	}
    	
    	/**
    	 * 给文本框赋值.并且切换日历的显示->calendar.calendar('moveTo',...)
    	 * remainText=undefined时 -> setText 并且 setValue
    	 */
    	function setValue(target, value, remainText){
    		var state = $.data(target, 'datebox');
    		var opts = state.options;
    		var calendar = state.calendar;
    		calendar.calendar('moveTo', opts.parser.call(target, value));
    		if (remainText){
    			$(target).combo('setValue', value);
    		} else {
    			if (value){
    				value = opts.formatter.call(target, calendar.calendar('options').current);
    			}
    			$(target).combo('setText', value).combo('setValue', value);
    		}
    	}
    	
    	/**
    	 * 构造方法.
    	 * 现象: 如果在下面的function第一行输出打印,然后到浏览器执行,会发现打印将输出多次.
    	 * 例如:
    	 * 第一次打印: options, param 都是undefined
    	 * 第二次打印: options: initValue, param: 
    	 * 第三次打印: options: options, param: undefined
    	 */
    	$.fn.datebox = function(options, param){
    		
    		if (typeof options == 'string'){
    			var method = $.fn.datebox.methods[options];
    			if (method){
    				//当 method 是"datebox"定义的方法是,直接调用.
    				return method(this, param);
    			} else {
    				//否则,调用combo对应的方法.
    				return this.combo(options, param);
    			}
    		}
    		
    		options = options || {};
    		
    		return this.each(function(){
    			
    			var state = $.data(this, 'datebox');
    			
    			if (state){
    				$.extend(state.options, options);
    			} else {
    				//在元素上存放(set)数据. 除了'cloneFrom'方法外,其他地方都是获取(get).
    				$.data(this, 'datebox', {
    					// 拷贝 $.fn.datebox.defaults 数据.
    					options: $.extend({}, $.fn.datebox.defaults, $.fn.datebox.parseOptions(this), options)
    				});
    			}
    			//
    			createBox(this);
    		});
    	};
    	
    	$.fn.datebox.methods = {
    		//测试发现,'options'方法在内部调用非常频繁.
    		options: function(jq){
    			var copts = jq.combo('options');
    			return $.extend($.data(jq[0], 'datebox').options, {
    				 copts.width,
    				height: copts.height,
    				originalValue: copts.originalValue,
    				disabled: copts.disabled,
    				readonly: copts.readonly
    			});
    		},
    		//cloneFrom 是combo中定义的方法.测试发现,内部几乎没有被使用.这个方法应该是暴露给用户使用的.
    		cloneFrom: function(jq, from){
    			return jq.each(function(){
    				$(this).combo('cloneFrom', from);
    				$.data(this, 'datebox', {
    					options: $.extend(true, {}, $(from).datebox('options')),
    					calendar: $(from).datebox('calendar')
    				});
    				$(this).addClass('datebox-f');
    			});
    		},
    		//暴露给用户使用的API.获得calendar对象.
    		calendar: function(jq){	// get the calendar object
    			return $.data(jq[0], 'datebox').calendar;
    		},
    		initValue: function(jq, value){
    			return jq.each(function(){
    				var opts = $(this).datebox('options');
    				var value = opts.value;
    				if (value){
    					//下文有定义'formatter','parser'方法.
    					value = opts.formatter.call(this, opts.parser.call(this, value));
    				}
    				//最终还是会调用'combo'的方法, 并且还调用'setText'方法
    				$(this).combo('initValue', value).combo('setText', value);
    			});
    		},
    		setValue: function(jq, value){
    			return jq.each(function(){
    				//调用本模块定义的'setValue'函数.
    				setValue(this, value);
    			});
    		},
    		reset: function(jq){
    			return jq.each(function(){
    				var opts = $(this).datebox('options');
    				// opts.originalValue -> 来自combo -> 为空字符串.
    				$(this).datebox('setValue', opts.originalValue);
    			});
    		}
    	};
    	
    	$.fn.datebox.parseOptions = function(target){
    		return $.extend({}, $.fn.combo.parseOptions(target), $.parser.parseOptions(target, ['sharedCalendar']));
    	};
    	
    	$.fn.datebox.defaults = $.extend({}, $.fn.combo.defaults, {
    		panelWidth:180,
    		panelHeight:'auto',
    		sharedCalendar:null,
    		
    		keyHandler: {
    			up:function(e){},
    			down:function(e){},
    			left: function(e){},
    			right: function(e){},
    			enter:function(e){doEnter(this)},
    			query:function(q,e){doQuery(this, q)}
    		},
    		
    		currentText:'Today',
    		closeText:'Close',
    		okText:'Ok',
    		
    		buttons:[{
    			text: function(target){return $(target).datebox('options').currentText;},
    			handler: function(target){
    				var now = new Date();
    				$(target).datebox('calendar').calendar({
    					year:now.getFullYear(),
    					month:now.getMonth()+1,
    					current:new Date(now.getFullYear(), now.getMonth(), now.getDate())
    				});
    				doEnter(target);
    			}
    		},{
    			text: function(target){return $(target).datebox('options').closeText;},
    			handler: function(target){
    				$(this).closest('div.combo-panel').panel('close');
    			}
    		}],
    		
    		formatter:function(date){
    			var y = date.getFullYear();
    			var m = date.getMonth()+1;
    			var d = date.getDate();
    			return (m<10?('0'+m):m)+'/'+(d<10?('0'+d):d)+'/'+y;
    		},
    		parser:function(s){
    			if (!s) return new Date();
    			var ss = s.split('/');
    			var m = parseInt(ss[0],10);
    			var d = parseInt(ss[1],10);
    			var y = parseInt(ss[2],10);
    			if (!isNaN(y) && !isNaN(m) && !isNaN(d)){
    				return new Date(y,m-1,d);
    			} else {
    				return new Date();
    			}
    		},
    		
    		onSelect:function(date){}
    	});
    })(jQuery);
    

      

  • 相关阅读:
    当函数中传递的参数数量不定时,获取传递给函数的参数信息
    redis分页摘抄
    redis分页
    返回数组中指定的一列,将键值作为元素键名array_column
    PHP操作Redis常用技巧总结
    php面试中的经典问题
    php 依赖注入的实现
    10分钟快速理解依赖注入
    PHP 依赖注入,依赖反转 (IOC-DI)
    PHP控制反转(IOC)和依赖注入(DI)
  • 原文地址:https://www.cnblogs.com/juedui0769/p/5114431.html
Copyright © 2011-2022 走看看