/**
 * jquery 表头固定插件 v0.1.0，fixedThead.js
 * @auther wingmeng
 * @update: 2017/05/06
 */
;(function($) {
 	$.fn.fixedThead = function(options) {
 		var defaults = {
 			height: 'auto',  // 表格最大高度，默认高度占满可视区
			vspace: 0,       // 垂直预留空间，为可视区其他组件空出空间，只有当height为auto时生效
			top: 0,          // 表格距离顶部的距离
			bottom: 0,       // 表格距离底部的距离
			row: 1,          // 要固定的行数
			col: 0           // 要固定的列数
 		};
 		var opts = $.extend(defaults, $.fn.fixedThead.option, options);

		return this.each(function() {
			var _this = $(this);
			opts = verifyOpts(opts, defaults);  // 校验参数
			if (typeof options == 'string') {
				if (options === 'refresh') {  // 刷新
					refresh(_this, opts);
				} else if (options === 'destroy') {  // 销毁实例
					destroy(_this);
				}
				return;
			}
			
			if (_this.parent().parent('div.fixed-thead').length) {
				refresh(_this, opts);
				return;  // 防止重复创建DOM
			}

			// 存储、移除自身内嵌样式
			if (_this.attr('style')) {
				_this.attr('data-style', _this.attr('style'));
				_this.removeAttr('style');
			}

			// 构建HTML结构
			var configs = buildHTML(_this, opts);
			guideBuild(configs);
			configs = null;
		});
	}

	$.fn.fixedThead.option = {};

	// 校验并确保自定义参数的合法性
	function verifyOpts(opts, defaults) {
		var result = defaults;
		var ckFun = function(str) {
			if (opts[str] == 0 || opts[str]) {
				if (!isNaN(opts[str]) && opts[str] >= 0) {
					result[str] = opts[str];
				}
			}
		};
		for (var key in result) {
			ckFun(key);
		}
		return result;
	}

	// 刷新数据（动态更新表格）
	function refresh(tableObj, opts) {
		if (tableObj.parent().parent('div.fixed-thead').length) {
			var configs = {
				table: tableObj,
				bodyWrap: tableObj.parent(),
				wrapper: tableObj.parent().parent(),
				scrollBarWt: getScrollWidth(),
				opts: opts
			}
			guideBuild(configs, true);
		}
	}

	// 销毁实例
	function destroy(tableObj) {
		var parent = tableObj.parent().parent('div.fixed-thead'),
			oldStyle = tableObj.data('style');			
		if (oldStyle) {
			tableObj.attr('style', oldStyle).removeAttr('data-style');  // 还原之前的style样式
		} else {
			tableObj.removeAttr('style');
		}
		parent.before(tableObj);
		parent.empty().remove();
	}

	// 克隆table HTML
	function cloneTable(table, flag) {
		var tClone = table.clone(),  // 是否复制事件？（待完善）
			tId = table.attr('id');
		if (tId) {
			tClone.attr('id', 'clone_' + tId + '_' + flag);
		}
		tClone.removeAttr('style');  // 移除复制的内嵌样式
		return tClone;
	}

	// 构建HTML向导
	function guideBuild(configs, flag) {
		var opts = configs.opts,
			tableWrap = {};
		if (opts.row > 0 && opts.col > 0) {
			tableWrap.head = buildHTML_head(configs);
			tableWrap.side = buildHTML_side(configs);
			tableWrap.corner = buildHTML_coner(configs);
		} else {
			if (opts.row > 0) {
				tableWrap.head = buildHTML_head(configs);
			}
			if (opts.col > 0) {
				tableWrap.side = buildHTML_side(configs);
			}
		}

		calcLayout(configs, tableWrap);
		if (!flag) {
			configs.bodyWrap.scroll(function() {
				if (tableWrap.side) {
					tableWrap.side.scrollTop($(this).scrollTop());
				}
				if (tableWrap.head) {
					tableWrap.head.scrollLeft($(this).scrollLeft());
				}
			});
			$(window).resize(function() {
				calcLayout(configs, tableWrap);
			});
		}
	}

	// 构建HTML结构
	function buildHTML(tableObj, opts) {
		var wrapper = $('<div class="fixed-thead"></div>'),
			bodyWrap = $('<div class="fixed-thead-body"></div>');
		tableObj.wrap(wrapper).wrap(bodyWrap);		
		var configs = {
			table: tableObj,
			bodyWrap: tableObj.parent(),
			wrapper: tableObj.parent().parent(),
			scrollBarWt: getScrollWidth(),
			opts: opts
		};
		if (opts.top) {
			configs.wrapper.css('margin-top', opts.top);
		}
		if (opts.bottom) {
			configs.wrapper.css('margin-bottom', opts.bottom);
		}
		return configs;			
	}

	// 构建头部
	function buildHTML_head(configs) {
		var wrap = configs.wrapper.find('div.fixed-thead-head');
		var headTable = cloneTable(configs.table, 'head');
		if (wrap.length == 0) {
			wrap = $('<div class="fixed-thead-head"></div>');
			configs.bodyWrap.before(wrap.append(headTable));
		} else {
			wrap.empty().append(headTable);  // empty()一下释放内存
		}
		return wrap;
	}

	// 构建侧边
	function buildHTML_side(configs) {
		var wrap = configs.wrapper.find('div.fixed-thead-side');
		var sideTable = cloneTable(configs.table, 'side');
		if (wrap.length == 0) {
			wrap = $('<div class="fixed-thead-side"></div>');
			configs.bodyWrap.before(wrap.append(sideTable));
		} else {				
			wrap.empty().append(sideTable);				
		}
		return wrap; 
	}

	// 构建左上角
	function buildHTML_coner(configs) {
		var wrap = configs.wrapper.find('div.fixed-thead-corner');
		var cornerTable = cloneTable(configs.table, 'corner');
		if (wrap.length == 0) {
			wrap = $('<div class="fixed-thead-corner"></div>');
			configs.bodyWrap.before(wrap.append(cornerTable));
		} else {				
			wrap.empty().append(cornerTable);				
		}
		return wrap;
	}

	// 布局计算
	function calcLayout(configs, tableWrap) {
		// 计算固定的行数高度总和
		var maxHt = 0,
			headHt = 0,
			sideWt = 0;
		if (tableWrap.head) {
			for (var i = 0; i < configs.opts.row; i++) {
				headHt += configs.table.find('tr').eq(i).outerHeight();
			}
			++headHt;  // 让固定head露出1px底边框线
			configs.table.css('margin-top', -headHt + 'px');
			tableWrap.head.height(headHt);
			maxHt = calcLayout_resize_head(configs, tableWrap.head, headHt);
		}
		if (tableWrap.side) {						
			for (var i = 0; i < configs.opts.col; i++) {
				sideWt += configs.table.find('tr:eq(0)').children().eq(i).outerWidth();
			}
			++sideWt;  // 让固定side露出1px右边框线

			// 如果表格未溢出可视区（未出现水平滚动条）
			if (configs.table.width() <= configs.bodyWrap.width()) {
				sideWt = 0;
			}

			configs.table.css('margin-left', -sideWt + 'px');
			configs.bodyWrap.css('margin-left', sideWt + 'px');

			if (tableWrap.head) {
				tableWrap.head.css('margin-left', sideWt + 'px')
					.children('table').css('margin-left', -sideWt + 'px');
			}

			tableWrap.side.css({
				top: headHt - 1 + 'px',
				width: sideWt + 'px',
				maxHeight: maxHt - configs.scrollBarWt + 1 + 'px'
			}).children('table').css('margin-top', -(headHt - 1) + 'px');
		}
		if (tableWrap.corner) {
			tableWrap.corner.css({
				width: sideWt + 'px',
				height: headHt + 'px'
			});
		}
	}

	// 计算并应用头部固定区域与滚动区域的布局样式
	function calcLayout_resize_head(configs, headWrap, headHt) {
		var maxHt = 0;
		if (configs.opts.height == 'auto') {  // 占满可视区
			maxHt = $(window).height() - configs.opts.vspace - headHt - configs.opts.top - configs.opts.bottom;
		} else {
			maxHt = configs.opts.height - headHt;
		}
		configs.bodyWrap.css('max-height', maxHt + 'px');

		var headTable = headWrap.children('table'),
			rowfix = headTable.find('.fixed-thead-rowfix');
		if (configs.bodyWrap.height() < configs.table.height() - headHt) {  // 出现垂直滚动条
			if (!rowfix.length) {
				calcLayout_fix_head(configs, headWrap, headTable);
			}
		} else {
			rowfix.remove();
		}
		return maxHt;
	}

	// 溢出修补
	function calcLayout_fix_head(configs, headWrap, headTable) {
		var scrollBarWt = configs.scrollBarWt - 1 + 'px';  // 滚动条宽度
		// 添加空单元格来修复滚动条占据的宽度
		for (var i = 0; i < configs.opts.row; i++) {
			var curRow = headTable.find('tr').eq(i),
				fixRow = curRow.children().last().clone();

			fixRow.empty().addClass('fixed-thead-rowfix');	
			if (headTable.width() > headWrap.width()) {  // 出现水平滚动条的情况
				var innerDiv = $('<div style="width:' + scrollBarWt + '"></div>');
				fixRow.css({
					width: 0,
					padding: 0
				}).append(innerDiv);
			} else {
				fixRow.css({
					width: scrollBarWt,
					padding: 0
				});
			}
			curRow.append(fixRow);
		} 	
	}

	// 获取浏览器滚动条宽度
	function getScrollWidth() {
		var noScroll, scroll;
		var oDiv = document.createElement('div'),
			$oDiv = $(oDiv);
		$oDiv.css({
			position: 'absolute',
			top: '-50px',
			zIndex: '-1',
			width: '50px',
			height: '50px',
			overflow: 'hidden'
		});
		document.body.appendChild(oDiv);
		noScroll = oDiv.clientWidth;
		oDiv.style.overflowY = 'scroll';
		scroll = oDiv.clientWidth;
		$oDiv.remove();
		return noScroll - scroll;
	}
})(jQuery);