/** * Author: meimeidev */ !function ($) { var MMGrid = function (element, options) { this._id = (((1 + Math.random()) * 0x10000) | 0).toString(16); this._loadCount = 0; this.opts = options; this._initLayout($(element)); this._initHead(); this._initOptions(); this._initEvents(); this._setColsWidth(); if (this.opts.fullWidthRows) { this._fullWidthRows(); } //初始化插件 for (var i = 0; i < this.opts.plugins.length; i++) { var plugin = this.opts.plugins[i]; plugin.init($.extend(element, this)); } if (options.autoLoad) { var that = this; this.opts = options; setTimeout(function () { if (options.url) { that.load(); } else { that.load(options.items); } }, 0); //chrome style problem } }; //see: http://tanalin.com/en/articles/ie-version-js/ var browser = function () { var isIE = !!window.ActiveXObject; var isIE10 = isIE && !!window.atob; var isIE9 = isIE && document.addEventListener && !window.atob; var isIE8 = isIE && document.querySelector && !document.addEventListener; var isIE7 = isIE && window.XMLHttpRequest && !document.querySelector; var isIE6 = isIE && !window.XMLHttpRequest; return { isIE: isIE , isIE6: isIE6 , isIE7: isIE7 , isIE8: isIE8 , isIE9: isIE9 , isIE10: isIE10 }; }(); MMGrid.prototype = { _initLayout: function ($el) { var opts = this.opts; var $elParent = $el.parent(); var elIndex = $el.index(); var mmGrid = [ '
', '', '
', '
', '
', '
', '
', '
', '', '
', '
', '', '
' + this.opts.noDataText + '
', '
', '
', '
', '
' + this.opts.loadingText + '
', '
', '
' ]; //fix in IE7,IE6 if (browser.isIE7 || browser.isIE6) { $el.prop('cellspacing', 0); } //cached object var $mmGrid = $(mmGrid.join('')); this.$mmGrid = $mmGrid; this.$style = $mmGrid.find('style'); this.$headWrapper = $mmGrid.find('.mmg-headWrapper'); this.$head = $mmGrid.find('.mmg-head'); this.$backboard = $mmGrid.find('.mmg-backboard'); this.$bodyWrapper = $mmGrid.find('.mmg-bodyWrapper'); this.$body = $el.removeAttr("style").addClass('mmg-body'); this._insertEmptyRow(); this.$body.appendTo(this.$bodyWrapper); //放回原位置 if (elIndex === 0 || $elParent.children().length == 0) { $elParent.prepend(this.$mmGrid); } else { $elParent.children().eq(elIndex - 1).after(this.$mmGrid); } // fix in ie6 if (browser.isIE6 && (!opts.width || opts.width === 'auto')) { $mmGrid.width('100%'); $mmGrid.width($mmGrid.width() - ($mmGrid.outerWidth(true) - $mmGrid.width())); } else { $mmGrid.width(opts.width); } if (browser.isIE6 && (!opts.height || opts.height === 'auto')) { $mmGrid.height('100%'); $mmGrid.height($mmGrid.height() - ($mmGrid.outerHeight(true) - $mmGrid.height())); } else { $mmGrid.height(opts.height); } if (opts.checkCol) { var chkHtml = opts.multiSelect ? '' : ''; opts.cols.unshift({ title: chkHtml, width: 20, align: 'center', lockWidth: true, checkCol: true, renderer: function () { return ''; } }); } if (opts.indexCol) { opts.cols.unshift({ title: '#', width: opts.indexColWidth, align: 'center', lockWidth: true, indexCol: true, renderer: function (val, item, rowIndex) { return ''; } }); } } , _expandCols: function (cols) { var newCols = []; if (!cols) { return newCols; } for (var colIndex = 0; colIndex < cols.length; colIndex++) { var col = cols[colIndex]; if (col.cols) { newCols.push(col); newCols.push.apply(newCols, this._expandCols(col.cols)); } else { newCols.push(col); } } return newCols; } , _leafCols: function () { var opts = this.opts; var newCols = []; var cols = this._expandCols(opts.cols); for (var colIndex = 0; colIndex < cols.length; colIndex++) { var col = cols[colIndex]; if (!col.cols) { newCols.push(col); } } return newCols; } , _expandThs: function () { return this.$head.find('th').sort(function (a, b) { return parseInt($(a).data('colindex')) - parseInt($(b).data('colindex')); }); } , _leafThs: function () { return this.$head.find('th').filter(function () { return !$.data(this, 'col').cols; }).sort(function (a, b) { return parseInt($(a).data('colindex')) - parseInt($(b).data('colindex')); }); } , _colsWithTitleDeep: function (cols, deep) { var newCols = []; if (!cols) { return newCols; } for (var colIndex = 0; colIndex < cols.length; colIndex++) { var col = cols[colIndex]; if (deep === 1) { newCols.push(col); } else { newCols.push.apply(newCols, this._colsWithTitleDeep(col.cols, deep - 1)); } } return newCols; } , _titleDeep: function (cols) { var deep = 1; for (var colIndex = 0; colIndex < cols.length; colIndex++) { var col = cols[colIndex]; if (col.cols) { var newDeep = 1 + this._titleDeep(col.cols); if (deep < newDeep) { deep = newDeep; } } } return deep; } , _titleHtml: function (col, rowspan) { var opts = this.opts; var titleHtml = []; if (!col.cols) { titleHtml.push(''); titleHtml.push('
'); titleHtml.push(''); if (col.titleHtml) { titleHtml.push(col.titleHtml); } else { titleHtml.push(col.title); } titleHtml.push('
'); if (!col.lockWidth) titleHtml.push('
'); titleHtml.push('
'); } else { var displayColsLength = col.cols.length; $.each(col.cols, function (index, item) { if (item.hidden) { displayColsLength--; } }); if (displayColsLength === 0) { col.hidden = true; } titleHtml.push(''); titleHtml.push('
'); titleHtml.push(''); if (col.titleHtml) { titleHtml.push(col.titleHtml); } else { titleHtml.push(col.title); } titleHtml.push('
'); titleHtml.push('
'); } return titleHtml.join(""); } , _initHead: function () { var that = this; var opts = this.opts; var $head = this.$head; if (opts.cols) { var theadHtmls = ['']; //获取标题深度 var titleDeep = that._titleDeep(opts.cols); for (var deep = 1; deep <= titleDeep; deep++) { var cols = that._colsWithTitleDeep(opts.cols, deep); theadHtmls.push(''); for (var colIndex = 0; colIndex < cols.length; colIndex++) { var col = cols[colIndex]; theadHtmls.push(this._titleHtml(col, titleDeep - deep + 1)); } theadHtmls.push(''); } theadHtmls.push(''); $head.html(theadHtmls.join('')); } var $ths = this._expandThs(); var expandCols = this._expandCols(opts.cols); $.each($ths, function (index) { if (!expandCols[index].width) { expandCols[index].width = 100; } $.data(this, 'col-width', expandCols[index].width); $.data(this, 'col', expandCols[index]); }); var $mmGrid = this.$mmGrid; var $headWrapper = this.$headWrapper; var $bodyWrapper = this.$bodyWrapper; if (opts.height !== 'auto') { $bodyWrapper.height($mmGrid.height() - $headWrapper.outerHeight(true)); } //初始化排序状态 if (opts.sortName) { for (var colIndex = 0; colIndex < expandCols.length; colIndex++) { var col = expandCols[colIndex]; if (col.sortName === opts.sortName || col.name === opts.sortName) { var $th = $ths.eq(colIndex); $.data($th.find('.mmg-title')[0], 'sortStatus', opts.sortStatus); $th.find('.mmg-sort').addClass('mmg-' + opts.sortStatus); } } } } , _initOptions: function () { var opts = this.opts; var $mmGrid = this.$mmGrid; var $headWrapper = this.$headWrapper; var $backboard = this.$backboard; $mmGrid.find('a.mmg-btnBackboardDn').css({ 'top': $headWrapper.outerHeight(true) }).slideUp('fast'); var cols = this._leafCols(); if (cols) { var bbHtml = ['

显示列

']; for (var colIndex = 0; colIndex < cols.length; colIndex++) { bbHtml.push(''); } $backboard.append($(bbHtml.join(''))); } } , _initEvents: function () { var that = this; var opts = this.opts; var $mmGrid = this.$mmGrid; var $headWrapper = this.$headWrapper; var $head = this.$head; var $bodyWrapper = this.$bodyWrapper; var $body = this.$body; var $backboard = this.$backboard; var $ths = this._expandThs(); var expandCols = this._expandCols(opts.cols); var leafCols = this._leafCols(); //调整浏览器 if (opts.width === 'auto' || opts.height === 'auto' || (typeof opts.width === 'string' && opts.width.indexOf('%') === opts.width.length - 1) || typeof opts.height === 'string' && opts.height.indexOf('%') === opts.height.length - 1) { $(window).on('resize', function () { that.resize(); }); } //滚动条事件 $bodyWrapper.on('scroll', function () { $head.css('left', - $(this).scrollLeft()); }); //向下按钮 var $btnBackboardDn = $mmGrid.find('a.mmg-btnBackboardDn').on('click', function () { var backboardHeight = $mmGrid.height() - $headWrapper.outerHeight(true); if (opts.height === 'auto' && opts.backboardMinHeight !== 'auto' && backboardHeight < opts.backboardMinHeight) { backboardHeight = opts.backboardMinHeight; } $backboard.height(backboardHeight); if (opts.height === 'auto') { $mmGrid.height($headWrapper.outerHeight(true) + $backboard.outerHeight(true)); } $backboard.slideDown(); $btnBackboardDn.slideUp('fast'); that._hideMessage(); }); $body.on('mouseenter', function () { $btnBackboardDn.slideUp('fast'); }); $mmGrid.on('mouseleave', function () { $btnBackboardDn.slideUp('fast'); }); $headWrapper.on('mouseenter', function () { if ($backboard.is(':hidden') && opts.showBackboard) { $btnBackboardDn.slideDown('fast'); } }); //向上按钮 $mmGrid.find('a.mmg-btnBackboardUp').on('click', function () { $backboard.slideUp().queue(function (next) { if (!that.rowsLength() || (that.rowsLength() === 1 && $body.find('tr.emptyRow').length === 1)) { that._showNoData(); } if (opts.height === 'auto') { $mmGrid.height('auto'); } next(); }); }); //隐藏列 $backboard.on('click', ':checkbox', function () { var index = $backboard.find('label').index($(this).parent()); //最后一个不隐藏 var last = 1; if (opts.checkCol) { last = last + 1; } if (opts.indexCol) { last = last + 1; } if ($backboard.find('label :checked').length < last) { this.checked = true; return; } var col = leafCols[index]; if (this.checked) { col.hidden = false; } else { col.hidden = true; } var $ths = $head.find('th'); for (var colIndex = $ths.length - 1; colIndex >= 0; colIndex--) { var $th = $ths.eq(colIndex); var iCol = $th.data('col'); if (iCol.cols) { var hidden = true; var colspan = 0; $.each(iCol.cols, function (index, item) { if (!item.hidden) { hidden = false; colspan++; } }); //IE bug if (colspan !== 0) { $th.prop('colspan', colspan); } iCol.hidden = hidden; } } that._setColsWidth(); $backboard.height($mmGrid.height() - $headWrapper.outerHeight(true)); if (opts.height !== 'auto') { $bodyWrapper.height($mmGrid.height() - $headWrapper.outerHeight(true)); } $mmGrid.find('a.mmg-btnBackboardDn').css({ 'top': $headWrapper.outerHeight(true) }) }); //排序事件 $head.on('click', '.mmg-title', function () { var $this = $(this); var $titles = $ths.find('.mmg-title'); //当前列不允许排序 var col = $this.parent().parent().data('col'); if (!col.sortable) { return; } //取得当前列下一个排序状态 var sortStatus = $.data(this, 'sortStatus') === 'asc' ? 'desc' : 'asc'; //清除排序状态 $.each($titles, function () { $.removeData(this, 'sortStatus'); }); $ths.find('.mmg-sort').removeClass('mmg-asc').removeClass('mmg-desc'); //设置当前列排序状态 $.data(this, 'sortStatus', sortStatus); $this.siblings('.mmg-sort').addClass('mmg-' + sortStatus); if (opts.url && opts.remoteSort) { that.load() } else { that._nativeSorter($.inArray(col, leafCols), sortStatus); that._setStyle(); } }).on('mousedown', '.mmg-colResize', function (e) { //调整列宽 var $resize = $(this); var start = e.pageX; var $colResizePointer = $mmGrid.find('.mmg-colResizePointer') .css('left', e.pageX - $headWrapper.offset().left).show(); var scrollLeft = $head.position().left; var $colResizePointerBefore = $mmGrid.find('.mmg-colResizePointer-before') .css('left', $resize.parent().parent().position().left + scrollLeft).show(); //取消文字选择 document.selection && document.selection.empty && (document.selection.empty(), 1) || window.getSelection && window.getSelection().removeAllRanges(); document.body.onselectstart = function () { return false; }; $headWrapper.css('-moz-user-select', 'none'); $mmGrid.on('mousemove', function (e) { $colResizePointer.css('left', e.pageX - $headWrapper.offset().left); }).on('mouseup', function (e) { //改变宽度 var $th = $resize.parent().parent(); var width = $th.width() + e.pageX - start; $.data($th[0], 'col-width', width); that._setColsWidth(); $headWrapper.mouseleave(); }).on('mouseleave', function () { $mmGrid.off('mouseup').off('mouseleave').off('mousemove'); $colResizePointer.hide(); $colResizePointerBefore.hide(); document.body.onselectstart = function () { return true;//开启文字选择 }; $headWrapper.css('-moz-user-select', 'text'); }); }); //选中事件 var $body = this.$body; $body.on('click', 'td', function (e) { var $this = $(this); if ($this.find("input,select,textarea").length > 0) { return false; } var event = jQuery.Event("cellSelected"); event.target = e.target; that.$body.triggerHandler(event, [$.data($this.parent()[0], 'item'), $this.parent().index(), $this.index()]); if (event.isPropagationStopped()) { return; } if (!$this.parent().hasClass('selected')) { that.select($this.parent().index()); } else { that.deselect($this.parent().index()); } }); //行双击 $body.on('dblclick', 'tr', function (e) { var $this = $(this); var event = jQuery.Event("rowDblclick"); event.target = e.target; that.$body.triggerHandler(event, [$.data($this[0], 'item'), $this.index()]); if (event.isPropagationStopped()) { return; } // if(!$this.parent().hasClass('selected')){ // that.select($this.parent().index()); // }else{ // that.deselect($this.parent().index()); // } }); $body.on('click', 'tr > td .mmg-check', function (e) { e.stopPropagation(); var $this = $(this); if (this.checked) { that.select($($this.parents('tr')[0]).index()); } else { that.deselect($($this.parents('tr')[0]).index()); } }); //checkbox列 if (opts.checkCol) { $head.find('th .checkAll').on('click', function () { if (this.checked) { that.select('all'); } else { that.deselect('all'); } }); } //IE6不支持hover if (browser.isIE6) { $body.on('mouseenter', 'tr', function () { $(this).toggleClass('hover'); }).on('mouseleave', 'tr', function () { $(this).toggleClass('hover'); }); }; } , _rowHtml: function (item, rowIndex) { var opts = this.opts; var expandCols = this._expandCols(opts.cols); var leafCols = this._leafCols(); if ($.isPlainObject(item)) { var trHtml = []; trHtml.push(''); for (var colIndex = 0; colIndex < leafCols.length; colIndex++) { var col = leafCols[colIndex]; trHtml.push(''); if (col.renderer) { trHtml.push(col.renderer(item[col.name], item, rowIndex)); } else { trHtml.push(item[col.name]); } trHtml.push(''); }; trHtml.push(''); return trHtml.join(''); } } , _populate: function (items) { var opts = this.opts; var $body = this.$body; this._hideMessage(); if (items && items.length !== 0 && opts.cols) { /*var tbodyHtmls = []; tbodyHtmls.push(''); for(var rowIndex=0; rowIndex < items.length; rowIndex++){ var item = items[rowIndex]; tbodyHtmls.push(this._rowHtml(item, rowIndex)); } tbodyHtmls.push(''); $body.empty().html(tbodyHtmls.join('')); var $trs = $body.find('tr'); for(var rowIndex=0; rowIndex < items.length; rowIndex++){ $.data($trs.eq(rowIndex)[0],'item',items[rowIndex]); }*/ $body.empty().html(""); for (var rowIndex = 0; rowIndex < items.length; rowIndex++) { var item = items[rowIndex]; var rowHtml = this._rowHtml(item, rowIndex); var row = $(rowHtml); $(row).data('item', item); $body.find('tbody').append(row); if (opts.EventNewRow != undefined && typeof opts.EventNewRow == "function") { opts.EventNewRow(rowIndex, item, row); } $body.triggerHandler("rowCreated", [rowIndex, item, row]); } } else { this._insertEmptyRow(); this._showNoData(); } this._setStyle(); if (opts.fullWidthRows && this._loadCount <= 1) { this._fullWidthRows(); } //当数据加载完成之后触发函数 if (opts.EventComplete != undefined && typeof opts.EventComplete == "function") { opts.EventComplete(this); } } , _insertEmptyRow: function () { var $body = this.$body; $body.empty().html(' '); } , _removeEmptyRow: function () { var $body = this.$body; $body.find('tr.emptyRow').remove(); } /* 生成列类 */ , _genColClass: function (colIndex) { return 'mmg' + this._id + '-col' + colIndex; } , _setStyle: function () { var $head = this.$head; var $ths = this._expandThs(); var $body = this.$body; var leafCol = this._leafCols(); //head $ths.eq(0).addClass('first'); $ths.eq(-1).addClass('last'); //body $body.find('tr,td').removeClass('even') .removeClass('colSelected').removeClass('colSelectedEven'); $body.find('tr:odd').addClass('even'); var sortIndex = $.inArray($head.find('.mmg-title').filter(function () { return $.data(this, 'sortStatus') === 'asc' || $(this).data('sortStatus') === 'desc'; }).parent().parent().data('col'), leafCol); $body.find('tr > td:nth-child(' + (sortIndex + 1) + ')').addClass('colSelected') .filter(':odd').addClass('colSelectedEven'); this._resizeHeight(); } , _setColsWidth: function () { var opts = this.opts; var $style = this.$style; var $head = this.$head; var $bodyWrapper = this.$bodyWrapper; var $body = this.$body; var $ths = this._expandThs(); var expandCols = this._expandCols(opts.cols); var scrollTop = $bodyWrapper.scrollTop(); var scrollLeft = $head.position().left; $bodyWrapper.width(9999); $body.width('auto'); var styleText = []; for (var colIndex = 0; colIndex < $ths.length; colIndex++) { var $th = $ths.eq(colIndex); styleText.push('.mmGrid .' + this._genColClass(colIndex) + ' {'); var width = $.data($th[0], 'col-width'); styleText.push('width: ' + width + 'px;'); styleText.push('max-width: ' + width + 'px;'); var col = expandCols[colIndex]; if (col.align) { styleText.push('text-align: ' + col.align + ';'); } if (col.hidden) { styleText.push('display: none; '); } styleText.push(' }'); } $body.detach(); try { $style.text(styleText.join('')); } catch (error) { $style[0].styleSheet.cssText = styleText.join('');//IE fix } $body.width($head.width()); $bodyWrapper.width('100%'); $bodyWrapper.append($body); //调整滚动条 $bodyWrapper.scrollLeft(-scrollLeft); if ($bodyWrapper.scrollLeft() === 0) { $head.css('left', 0); } $bodyWrapper.scrollTop(scrollTop); } , _fullWidthRows: function () { var opts = this.opts; var $bodyWrapper = this.$bodyWrapper; var $mmGrid = this.$mmGrid; var $head = this.$head; var scrollWidth = $bodyWrapper.width() - $bodyWrapper[0].clientWidth; if (scrollWidth && browser.isIE) { scrollWidth = scrollWidth + 1; } var fitWidth = $mmGrid.width() - $head.width() - scrollWidth; if (fitWidth < -20) { return; } var thsArr = []; var $ths = this._leafThs(); var leafCol = this._leafCols(); for (var i = 0; i < leafCol.length; i++) { var col = leafCol[i]; var $th = $ths.eq(i); if (!col.lockWidth && $th.is(':visible')) { thsArr.push($th); } } var increaseWidth = Math.floor(fitWidth / thsArr.length); var maxColWidthIndex = 0; for (var i = 0; i < thsArr.length; i++) { var $th = thsArr[i]; var colWidth = $.data($th[0], 'col-width') + increaseWidth; $.data($th[0], 'col-width', colWidth); var maxColWidth = $.data(thsArr[maxColWidthIndex][0], 'col-width'); if (maxColWidth < colWidth) { maxColWidthIndex = i; } } var remainWidth = fitWidth - increaseWidth * thsArr.length; var maxColWidth = $.data(thsArr[maxColWidthIndex][0], 'col-width'); $.data(thsArr[maxColWidthIndex][0], 'col-width', maxColWidth + remainWidth); this._setColsWidth(); } , _showLoading: function () { var $mmGrid = this.$mmGrid; $mmGrid.find('.mmg-mask').show(); var $loading = $mmGrid.find('.mmg-loading'); $loading.css({ 'left': ($mmGrid.width() - $loading.width()) / 2, 'top': ($mmGrid.height() - $loading.height()) / 2 }).show(); } , _hideLoading: function () { var $mmGrid = this.$mmGrid; $mmGrid.find('.mmg-mask').hide(); $mmGrid.find('.mmg-loading').hide(); } , _showNoData: function () { this._showMessage(this.opts.noDataText); } , _showLoadError: function () { this._showMessage(this.opts.loadErrorText); } , _showMessage: function (msg) { var $mmGrid = this.$mmGrid; var $headWrapper = this.$headWrapper; var $message = $mmGrid.find('.mmg-message'); $message.css({ 'left': ($mmGrid.width() - $message.width()) / 2, 'top': ($mmGrid.height() + $headWrapper.height() - $message.height()) / 2 }).text(msg).show(); } , _hideMessage: function () { var $mmGrid = this.$mmGrid; $mmGrid.find('.mmg-message').hide(); } , _nativeSorter: function (colIndex, sortStatus) { var leafCols = this._leafCols(); var col = leafCols[colIndex]; this.$body.find('tr > td:nth-child(' + (colIndex + 1) + ')') .sortElements(function (a, b) { var av = $.text($(a)); var bv = $.text($(b)); //排序前转换 if (col.type === 'number') { av = parseFloat(av); bv = parseFloat(bv); } else { //各个浏览器localeCompare的结果不一致 return sortStatus === 'desc' ? -av.localeCompare(bv) : av.localeCompare(bv); } return av > bv ? (sortStatus === 'desc' ? -1 : 1) : (sortStatus === 'desc' ? 1 : -1); }, function () { return this.parentNode; }); } , _refreshSortStatus: function () { var $ths = this.$head.find('th'); var sortColIndex = -1; var sortStatus = ''; $ths.find('.mmg-title').each(function (index, item) { var status = $.data(item, 'sortStatus'); if (status) { sortColIndex = index; sortStatus = status; } }); var sortStatus = sortStatus === 'desc' ? 'asc' : 'desc'; if (sortColIndex >= 0) { $ths.eq(sortColIndex).find('.mmg-title').data('sortStatus', sortStatus).click(); } } , _loadAjax: function (args) { var that = this; var opts = this.opts; var params = {}; //opt的params可以使函数,例如收集过滤的参数 if ($.isFunction(opts.params)) { var p = opts.params(); if (!p) { return; } params = $.extend(params, p); } else if ($.isPlainObject(opts.params)) { params = $.extend(params, opts.params); } if (opts.remoteSort) { var sortName = ''; var sortStatus = ''; var $titles = this.$head.find('.mmg-title'); for (var colIndex = 0; colIndex < $titles.length; colIndex++) { var status = $.data($titles[colIndex], 'sortStatus'); if (status) { var col = $titles.eq(colIndex).parent().parent().data('col'); sortName = col.sortName ? col.sortName : col.name; sortStatus = status; } } if (sortName) { params.sort = sortName + '.' + sortStatus; } } //插件参数合并 var pluginParams = {}; for (var i = 0; i < this.opts.plugins.length; i++) { var plugin = this.opts.plugins[i]; $.extend(pluginParams, plugin.params()); } params = $.extend(params, pluginParams); //合并load的参数 params = $.extend(params, args); that._showLoading(); $.ajax({ type: opts.method, url: opts.url, data: params, dataType: 'json', cache: opts.cache }).done(function (data) { try { //获得root对象 var items = data; if ($.isArray(data[opts.root])) { items = data[opts.root]; } that._populate(items); that._hideLoading(); if (!opts.remoteSort) { that._refreshSortStatus(); } if (data && $.isArray(data[opts.root])) { data = $.extend(args, data); } that.$body.triggerHandler('loadSuccess', data); } catch (e) { that._hideLoading(); that._showLoadError(); throw e; } }).fail(function (data) { that._hideLoading(); that._showLoadError(); that.$body.triggerHandler('loadError', data); }); } , _loadNative: function (args) { this._populate(args); this._refreshSortStatus(); //this.$body.triggerHandler('loadSuccess', args); //发现bug this.$body.triggerHandler('loadSuccess', [args]); } , load: function (args) { try { var opts = this.opts; this._hideMessage(); this._loadCount = this._loadCount + 1; if ($.isArray(args)) { //加载本地数据 this._loadNative(args); } else if (opts.url) { this._loadAjax(args); } else if (opts.items) { this._loadNative(opts.items); } else { this._loadNative([]); } } catch (e) { this._showLoadError(); throw e; } } //重设尺寸 , resize: function () { var opts = this.opts; var $mmGrid = this.$mmGrid; var $headWrapper = this.$headWrapper; var $bodyWrapper = this.$bodyWrapper; // fix in ie6 if (browser.isIE6 && (!opts.width || opts.width === 'auto')) { $mmGrid.width('100%'); $mmGrid.width($mmGrid.width() - ($mmGrid.outerWidth(true) - $mmGrid.width())); } else { $mmGrid.width(opts.width); } if (opts.height !== 'auto') { if (browser.isIE6 && (!opts.height || opts.height === 'auto')) { $mmGrid.height('100%'); $mmGrid.height($mmGrid.height() - ($mmGrid.outerHeight(true) - $mmGrid.height())); } else { $mmGrid.height(opts.height); } $bodyWrapper.height($mmGrid.height() - $headWrapper.outerHeight(true)); } //调整message var $message = $mmGrid.find('.mmg-message'); if ($message.is(':visible')) { $message.css({ 'left': ($mmGrid.width() - $message.width()) / 2, 'top': ($mmGrid.height() + $headWrapper.height() - $message.height()) / 2 }); } //调整loading var $mask = $mmGrid.find('.mmg-mask'); if ($mask.is(':visible')) { $mask.width($mmGrid.width()).height($mmGrid.height()); var $loadingWrapper = $mmGrid.find('.mmg-loading'); $loadingWrapper.css({ 'left': ($mmGrid.width() - $loadingWrapper.width()) / 2, 'top': ($mmGrid.height() - $loadingWrapper.height()) / 2 }) } $bodyWrapper.trigger('scroll'); this._resizeHeight(); } , _resizeHeight: function () { var opts = this.opts; var $bodyWrapper = this.$bodyWrapper; var $body = this.$body; if (opts.height === 'auto' && browser.isIE7) { $bodyWrapper.height('auto'); if ($bodyWrapper.width() < $body.width()) { $bodyWrapper.height($bodyWrapper.height() + $bodyWrapper.height() - $bodyWrapper[0].clientHeight + 1); } } } //选中 , select: function (args) { var opts = this.opts; var $body = this.$body; var $head = this.$head; if (typeof args === 'number') { var $tr = $body.find('tr').eq(args); if (!opts.multiSelect) { $body.find('tr.selected').removeClass('selected'); if (opts.checkCol) { $body.find('tr > td').find('.mmg-check').prop('checked', ''); } } if (!$tr.hasClass('selected')) { $tr.addClass('selected'); if (opts.checkCol) { $tr.find('td .mmg-check').prop('checked', 'checked'); } } } else if (typeof args === 'function') { $.each($body.find('tr'), function (index) { if (args($.data(this, 'item'), index)) { var $this = $(this); if (!$this.hasClass('selected')) { $this.addClass('selected'); if (opts.checkCol) { $this.find('td .mmg-check').prop('checked', 'checked'); } } } }); } else if (args === undefined || (typeof args === 'string' && args === 'all')) { $body.find('tr.selected').removeClass('selected'); $body.find('tr').addClass('selected'); $body.find('tr > td').find('.mmg-check').prop('checked', 'checked'); } else { return; } if (opts.checkCol) { var $checks = $body.find('tr > td').find('.mmg-check'); if ($checks.length === $checks.filter(':checked').length) { $head.find('th .checkAll').prop('checked', 'checked'); } } } //取消选中 , deselect: function (args) { var opts = this.opts; var $body = this.$body; var $head = this.$head; if (typeof args === 'number') { $body.find('tr').eq(args).removeClass('selected'); if (opts.checkCol) { $body.find('tr').eq(args).find('td .mmg-check').prop('checked', ''); } } else if (typeof args === 'function') { $.each($body.find('tr'), function (index) { if (args($.data(this, 'item'), index)) { $(this).removeClass('selected'); if (opts.checkCol) { $(this).find('td .mmg-check').prop('checked', ''); } } }); } else if (args === undefined || (typeof args === 'string' && args === 'all')) { $body.find('tr.selected').removeClass('selected'); if (opts.checkCol) { $body.find('tr > td').find('.mmg-check').prop('checked', ''); } } else { return; } $head.find('th .checkAll').prop('checked', ''); } , selectedRows: function () { var $body = this.$body; var selected = []; $.each($body.find('tr.selected'), function (index, item) { selected.push($.data(this, 'item')); }); return selected; } , selectedRowsIndex: function () { var $body = this.$body; var $trs = this.$body.find('tr') var selected = []; $.each($body.find('tr.selected'), function (index) { selected.push($trs.index(this)); }); return selected; } , rows: function () { var $body = this.$body; var items = []; $.each($body.find('tr'), function () { items.push($.data(this, 'item')); }); return items; } , row: function (index) { var $body = this.$body; if (index !== undefined && index >= 0) { var $tr = $body.find('tr').eq(index); if ($tr.length !== 0) { return $.data($tr[0], 'item'); } } } , rowsLength: function () { var $body = this.$body; var length = $body.find('tr').length; if (length === 1 && $body.find('tr.emptyRow').length === 1) { return 0; } return length; } //添加数据,第一个参数可以为数组 , addRow: function (item, index) { var $tbody = this.$body.find('tbody'); if ($.isArray(item)) { for (var i = item.length - 1; i >= 0; i--) { this.addRow(item[i], index); } return; } if (!$.isPlainObject(item)) { return; } this._hideMessage(); this._removeEmptyRow(); var $tr; if (index === undefined || index < 0) { $tr = $(this._rowHtml(item, this.rowsLength())); $tbody.append($tr); } else { $tr = $(this._rowHtml(item, index)); if (index === 0) { $tbody.prepend($tr); } else { var $before = $tbody.find('tr').eq(index - 1); //找不到就插到最后 if ($before.length === 0) { $tbody.append($tr); } else { $before.after($($tr)); } } } $tr.data('item', item); this._setStyle(); this.$body.triggerHandler('rowInserted', [item, index]); } //更新行内容,两个参数都必填 , updateRow: function (item, index) { var opts = this.opts; var $tbody = this.$body.find('tbody'); if (!$.isPlainObject(item)) { return; } var oldItem = this.row(index); var $tr = $tbody.find('tr').eq(index); var checked = $tr.find('td:first :checkbox').is(':checked'); $tr.html(this._rowHtml(item, index).slice(4, -5)); if (opts.checkCol) { $tr.find('td:first :checkbox').prop('checked', checked); } $tr.data('item', item); this._setStyle(); this.$body.triggerHandler('rowUpdated', [oldItem, item, index]); } //删除行,参数可以为索引数组 , removeRow: function (index) { var that = this; var $tbody = that.$body.find('tbody'); if ($.isArray(index)) { for (var i = index.length - 1; i >= 0; i--) { that.removeRow(index[i]); } return; } if (index === undefined) { var $trs = $tbody.find('tr'); for (var i = $trs.length - 1; i >= 0; i--) { that.removeRow(i); } } else { var item = that.row(index); $tbody.find('tr').eq(index).remove(); this.$body.triggerHandler('rowRemoved', [item, index]); } this._setStyle(); if (this.rowsLength() === 0) { this._showNoData(); this._insertEmptyRow(); } } }; $.fn.mmGrid = function () { if (arguments.length === 0 || typeof arguments[0] === 'object') { var option = arguments[0] , data = this.data('mmGrid') , options = $.extend(true, {}, $.fn.mmGrid.defaults, option); if (!data) { data = new MMGrid(this, options); this.data('mmGrid', data); } return $.extend(true, this, data); } if (typeof arguments[0] === 'string') { var data = this.data('mmGrid'); var fn = data[arguments[0]]; if (fn) { var args = Array.prototype.slice.call(arguments); return fn.apply(data, args.slice(1)); } } }; $.fn.mmGrid.defaults = { width: 'auto' , height: '280px' , cols: [] , url: false , params: {} , method: 'POST' , cache: false , root: 'items' , items: [] , autoLoad: true , remoteSort: false , sortName: '' , sortStatus: 'asc' , loadingText: '正在载入...' , noDataText: '没有数据' , loadErrorText: '数据加载出现异常' , multiSelect: false , checkCol: false , indexCol: false , indexColWidth: 30 , fullWidthRows: false , nowrap: false , showBackboard: true , backboardMinHeight: 125 , plugins: [] //插件 插件必须实现 init($mmGrid)和params()方法,参考mmPaginator , EventComplete: undefined //当数据加载完成触发事件 , EventNewRow: undefined //新生成行出发事件 }; $.fn.mmGrid.Constructor = MMGrid; // see: http://james.padolsey.com/javascript/sorting-elements-with-jquery/ $.fn.sortElements = (function () { var sort = [].sort; return function (comparator, getSortable) { getSortable = getSortable || function () { return this; }; var placements = this.map(function () { var sortElement = getSortable.call(this), parentNode = sortElement.parentNode, nextSibling = parentNode.insertBefore( document.createTextNode(''), sortElement.nextSibling ); return function () { if (parentNode === this) { throw new Error( "You can't sort elements if any one is a descendant of another." ); } parentNode.insertBefore(this, nextSibling); parentNode.removeChild(nextSibling); }; }); return sort.call(this, comparator).each(function (i) { placements[i].call(getSortable.call(this)); }); }; })(); }(window.jQuery);