From 944b9f4460ac493647ce8ce7d2c39efd4a08686c Mon Sep 17 00:00:00 2001 From: ufologist Date: Thu, 4 Jul 2013 08:15:36 -0700 Subject: [PATCH] =?UTF-8?q?=E5=9F=BA=E4=BA=8EDataTables,=20FixedColumns,?= =?UTF-8?q?=20iScroll=E5=AE=9E=E7=8E=B0=E5=9C=A8=E7=A7=BB=E5=8A=A8?= =?UTF-8?q?=E5=B9=B3=E5=8F=B0=E4=B8=8A(Android/iOS...)=E5=8F=AF=E7=94=A8?= =?UTF-8?q?=E7=9A=84=E5=9B=BA=E5=AE=9A=E5=88=97/=E8=A1=A8=E5=A4=B4?= =?UTF-8?q?=E7=9A=84=E8=A1=A8=E6=A0=BC=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 72 ++++++++++++- datatables.mobile-fixed-columns-table.js | 123 +++++++++++++++++++++++ 2 files changed, 193 insertions(+), 2 deletions(-) create mode 100644 datatables.mobile-fixed-columns-table.js diff --git a/README.md b/README.md index 98d1581..b83cf6e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,72 @@ -mobile-fixed-columns +mobile-fixed-columns-table ==================== - 在移动平台上(Android/iOS...)可用的固定列/表头的表格组件 + +测试过的手机 +==================== +* 小米1 +* Note2(N7100) +* GT-I8552 + +使用方法 +==================== + // 至少需要的参数 + $('#table').mobileFixedColumnsTable({ // 请参考DataTables的配置 + 'sScrollY': '300px', + 'sScrollX': '100%', + 'bScrollCollapse': true, + }); + + // 更多的配置项 + $('#table').mobileFixedColumnsTable({ + 'sScrollY': '300px', + 'sScrollX': '100%', + 'bScrollCollapse': true, + 'oLanguage': { + 'sInfo': '' + } + }, { + fixedColumnsOptions: { // 请参考DataTables的FixedColumns的配置 + iLeftColumns: 2 + }, + scrollerOptions: { // 请参考iScroll的配置 + onScrollMove: function() { + console.log(this, arguments); + } + } + }); + +使用效果 +==================== +TODO + +依赖 +==================== +1. jQuery +2. DataTables && FixedColumns +3. iScroll + +不是我想要造轮子 +==================== +为什么非要专门为移动平台包装这么一个组件? +主要是因为试过很多可以固定列/表头的表格组件, 在移动平台上使用都不理想 +例如: +* Fixed-Header-Table +* DataTables - FixedColumns +* Ext JS - Locking Grid + +其中最为理想的是FixedColumns, 但在*Android 2.3.x*上(极有可能2.3之前的版本也无法使用, 但未测试过)无法使用, 试过在Android 4.x上一切正常. +但还是有一点点小瑕疵. 由于FixedColumns的实现机制是利用原生的滚动条来控制固定列/表头, 在移动平台上不会出现这个原生的滚动条, 因此会给人不爽的感觉. +想着是否需要参考这些已经成熟的固定列/表头的HTML结构, 自己来实现一个类似的组件, 让其兼容*Android 2.3.x*? + +深受启发 +==================== +某日看过某人随便写的一个可以在移动平台上使用的固定列/表头的组件, 虽是个半成品, 但深受启发, 原来使用iScroll来代替原生滚动条就行了, 就这么简单. + +解析FixedColumns +==================== +TODO + +github pages demo +==================== +TODO \ No newline at end of file diff --git a/datatables.mobile-fixed-columns-table.js b/datatables.mobile-fixed-columns-table.js new file mode 100644 index 0000000..f615975 --- /dev/null +++ b/datatables.mobile-fixed-columns-table.js @@ -0,0 +1,123 @@ +/** + * 基于DataTables, FixedColumns, iScroll + * 实现在移动平台上可用的固定列/表头的表格组件 + * + * Released under MIT license + * + * @auther Sun + * @version 1.0 2013-7-4 + */ +(function($, root) { + function MobileFixedColumns(fixedColumns, scrollerOptions) { + var thiz = this; + this.fixedColumns = fixedColumns; + + this.scrollerOptions = $.extend({}, scrollerOptions, MobileFixedColumns.overrideScrollerOptions); + var originOnScrollMove = this.scrollerOptions.onScrollMove; + this.scrollerOptions.onScrollMove = function(event) { + // 如果原本监听有onScrollMove, 则需要合并进来 + // 这里的this是iScroll对象 + originOnScrollMove && originOnScrollMove.call(this, event); + // 这里的thiz是MobileFixedColumns对象 + MobileFixedColumns.defaultOnScrollMove.call(thiz, event); + }; + + this.initLeftFixedColumnScroller(); + this.initRightFixedColumnScroller(); + this.initFixedHeaderScroller(); + this.disableFixedScroller(); + this.initScrollBodyScroller(); + } + + MobileFixedColumns.prototype = { + initLeftFixedColumnScroller: function() { + // 即使iLeftColumns=0的情况下, 让表格左边没有固定列, + // 也会生成this.fixedColumns.dom.grid.left.body元素 + // 因此这里的判断需要更加严格 + if (this.fixedColumns.dom.grid.left.body && this.fixedColumns.dom.grid.left.body.children.length > 0) { + // 左边固定列的wrapper + var leftBodyWrapper = this.fixedColumns.dom.grid.left.body; + this.leftFixedColumnScroller = new iScroll(leftBodyWrapper, MobileFixedColumns.fixedScrollerOptions); + } + }, + initRightFixedColumnScroller: function() { + if (this.fixedColumns.dom.grid.right.body) { + // 右边固定列的wrapper + var rightBodyWrapper = this.fixedColumns.dom.grid.right.body; + this.rightFixedColumnScroller = new iScroll(rightBodyWrapper, MobileFixedColumns.fixedScrollerOptions); + } + }, + initFixedHeaderScroller: function() { + // 固定表头 + // XXX FixedColumns 没有直接的属性可以获得dataTables_scrollHead, 只能查找DOM了 + var scrollHeader = $(this.fixedColumns.dom.grid.dt).find('.dataTables_scrollHead')[0]; + // 固定表头多余的padding-right造成iscroll拖动到最右边时表头出现空余 + // 这个padding-right是为浏览器原生的垂直滚动条预览的空间 + $(scrollHeader).find('.dataTables_scrollHeadInner').css('padding-right', 0); + + this.fixedHeaderScroller = new iScroll(scrollHeader, MobileFixedColumns.fixedScrollerOptions); + }, + initScrollBodyScroller: function() { + // 滚动区域 + var scrollBody = this.fixedColumns.dom.scroller; + // 让iscroll的垂直滚动条处于正确的位置, 否则会超出到固定表头那里 + $(scrollBody).css('position', 'relative'); + + this.scrollBodyScroller = new iScroll(scrollBody, this.scrollerOptions); + }, + disableFixedScroller: function() { // 让用户不能主动操作固定列/表头的iScroll + this.leftFixedColumnScroller && this.leftFixedColumnScroller.disable(); + this.rightFixedColumnScroller && this.rightFixedColumnScroller.disable(); + this.fixedHeaderScroller.disable(); + } + }; + + // 拖动表格的iscroll来联动固定区域的iscroll + MobileFixedColumns.defaultOnScrollMove = function(event) { + // body滚动条的y控制固定列的y + this.leftFixedColumnScroller && this.leftFixedColumnScroller.scrollTo(0, this.scrollBodyScroller.y); + this.rightFixedColumnScroller && this.rightFixedColumnScroller.scrollTo(0, this.scrollBodyScroller.y); + + // body滚动条的x控制固定表头的x + // x和maxScrollX的值都是负值 + var absX = Math.abs(this.scrollBodyScroller.x); + var absMaxScrollX = Math.abs(this.scrollBodyScroller.maxScrollX); + // 防止频繁操作固定表头造成表头抖动 + if (absX < absMaxScrollX) { + this.fixedHeaderScroller.scrollTo(this.scrollBodyScroller.x, 0); + } else if (absX === absMaxScrollX) { // 如果大幅度拖动(将水平滚动条一拖到底)会造成固定表头跟不上节奏 + this.fixedHeaderScroller.scrollTo(this.fixedHeaderScroller.maxScrollX, 0); + } + }; + + // 必须限制为这些值 不支持这些参数, 因此覆盖了用户传进来的这些参数 + MobileFixedColumns.overrideScrollerOptions = { + bounce: false, + momentum: false, + wheelAction: 'none' + }; + MobileFixedColumns.fixedScrollerOptions = { + bounce: false, + momentum: false, + vScrollbar: false, // 将iscroll生成的模拟scrollbar隐藏 + hScrollbar: false + }; + + $.fn.mobileFixedColumnsTable = function(dataTablesOptions, options) { + var _dataTablesOptions = $.extend({}, dataTablesOptions, $.fn.mobileFixedColumnsTable.overrideDataTablesOptions); + var fixedColumnsOptions = options && options.fixedColumnsOptions; + var scrollerOptions = options && options.scrollerOptions; + + var dataTable = this.dataTable(_dataTablesOptions); + var fixedColumns = new FixedColumns(dataTable, fixedColumnsOptions); + var mobileFixedColumns = new MobileFixedColumns(fixedColumns, scrollerOptions); + + return this; + }; + // DataTables的这些参数必须限制为这些值 + $.fn.mobileFixedColumnsTable.overrideDataTablesOptions = { + bFilter: false, + bSort: false, + bPaginate: false + }; +})(jQuery, window); \ No newline at end of file