2025-04-10 23:19:13 +08:00

679 lines
25 KiB
JavaScript

/**
* jquery-resizable-columns - Resizable table columns for jQuery
* @date Sat May 16 2015 19:03:57 GMT+0100 (BST)
* @version v0.1.0
* @link http://dobtco.github.io/jquery-resizable-columns/
* @license MIT
*/
(function e(t, n, r) {
function s(o, u) {
if (!n[o]) {
if (!t[o]) {
var a = typeof require == "function" && require;
if (!u && a) return a(o, !0);
if (i) return i(o, !0);
var f = new Error("Cannot find module '" + o + "'");
throw f.code = "MODULE_NOT_FOUND", f
}
var l = n[o] = {
exports: {}
};
t[o][0].call(l.exports, function(e) {
var n = t[o][1][e];
return s(n ? n : e)
}, l, l.exports, e, t, n, r)
}
return n[o].exports
}
var i = typeof require == "function" && require;
for (var o = 0; o < r.length; o++) s(r[o]);
return s
})({
1: [function(require, module, exports) {
'use strict';
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
'default': obj
};
}
var _class = require('./class');
var _class2 = _interopRequireDefault(_class);
var _constants = require('./constants');
$.fn.resizableColumns = function(optionsOrMethod) {
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
return this.each(function() {
var $table = $(this);
var api = $table.data(_constants.DATA_API);
if (!api) {
api = new _class2['default']($table, optionsOrMethod);
$table.data(_constants.DATA_API, api);
} else if (typeof optionsOrMethod === 'string') {
return api[optionsOrMethod].apply(api, args);
}
});
};
$.resizableColumns = _class2['default'];
}, {
"./class": 2,
"./constants": 3
}],
2: [function(require, module, exports) {
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
var _createClass = (function() {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ('value' in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function(Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
})();
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError('Cannot call a class as a function');
}
}
var _constants = require('./constants');
/**
Takes a <table /> element and makes it's columns resizable across both
mobile and desktop clients.
@class ResizableColumns
@param $table {jQuery} jQuery-wrapped <table> element to make resizable
@param options {Object} Configuration object
**/
var ResizableColumns = (function() {
function ResizableColumns($table, options) {
_classCallCheck(this, ResizableColumns);
this.ns = '.rc' + this.count++;
this.options = $.extend({}, ResizableColumns.defaults, options);
this.$window = $(window);
this.$ownerDocument = $($table[0].ownerDocument);
this.$table = $table;
this.refreshHeaders();
this.restoreColumnWidths();
this.syncHandleWidths();
this.bindEvents(this.$window, 'resize', this.syncHandleWidths.bind(this));
if (this.options.start) {
this.bindEvents(this.$table, _constants.EVENT_RESIZE_START, this.options.start);
}
if (this.options.resize) {
this.bindEvents(this.$table, _constants.EVENT_RESIZE, this.options.resize);
}
if (this.options.stop) {
this.bindEvents(this.$table, _constants.EVENT_RESIZE_STOP, this.options.stop);
}
}
_createClass(ResizableColumns, [{
key: 'refreshHeaders',
/**
Refreshes the headers associated with this instances <table/> element and
generates handles for them. Also assigns percentage widths.
@method refreshHeaders
**/
value: function refreshHeaders() {
// Allow the selector to be both a regular selctor string as well as
// a dynamic callback
var selector = this.options.selector;
if (typeof selector === 'function') {
selector = selector.call(this, this.$table);
}
// Select all table headers
this.$tableHeaders = this.$table.find(selector);
// Assign percentage widths first, then create drag handles
this.assignPercentageWidths();
this.createHandles();
}
}, {
key: 'createHandles',
/**
Creates dummy handle elements for all table header columns
@method createHandles
**/
value: function createHandles() {
var _this = this;
var ref = this.$handleContainer;
if (ref != null) {
ref.remove();
}
this.$handleContainer = $('<div class=\'' + _constants.CLASS_HANDLE_CONTAINER + '\' />');
this.$table.before(this.$handleContainer);
this.$tableHeaders.each(function(i, el) {
var $current = _this.$tableHeaders.eq(i);
var $next = _this.$tableHeaders.eq(i + 1);
if ($next.length === 0 || $current.is(_constants.SELECTOR_UNRESIZABLE) || $next.is(_constants.SELECTOR_UNRESIZABLE)) {
return;
}
var $handle = $('<div class=\'' + _constants.CLASS_HANDLE + '\' />').data(_constants.DATA_TH, $(el)).appendTo(_this.$handleContainer);
});
this.bindEvents(this.$handleContainer, ['mousedown', 'touchstart'], '.' + _constants.CLASS_HANDLE, this.onPointerDown.bind(this));
}
}, {
key: 'assignPercentageWidths',
/**
Assigns a percentage width to all columns based on their current pixel width(s)
@method assignPercentageWidths
**/
value: function assignPercentageWidths() {
var _this2 = this;
this.$tableHeaders.each(function(_, el) {
var $el = $(el);
_this2.setWidth($el[0], $el.outerWidth() / _this2.$table.width() * 100);
});
}
}, {
key: 'syncHandleWidths',
/**
@method syncHandleWidths
**/
value: function syncHandleWidths() {
var _this3 = this;
var $container = this.$handleContainer;
$container.width(this.$table.width());
$container.find('.' + _constants.CLASS_HANDLE).each(function(_, el) {
var $el = $(el);
var height = _this3.options.resizeFromBody ? _this3.$table.height() : _this3.$table.find('thead').height();
var left = $el.data(_constants.DATA_TH).outerWidth() + ($el.data(_constants.DATA_TH).offset().left - _this3.$handleContainer.offset().left);
$el.css({
left: left,
height: height
});
});
}
}, {
key: 'saveColumnWidths',
/**
Persists the column widths in localStorage
@method saveColumnWidths
**/
value: function saveColumnWidths() {
var _this4 = this;
this.$tableHeaders.each(function(_, el) {
var $el = $(el);
if (_this4.options.store && !$el.is(_constants.SELECTOR_UNRESIZABLE)) {
_this4.options.store.set(_this4.generateColumnId($el), _this4.parseWidth(el));
}
});
}
}, {
key: 'restoreColumnWidths',
/**
Retrieves and sets the column widths from localStorage
@method restoreColumnWidths
**/
value: function restoreColumnWidths() {
var _this5 = this;
this.$tableHeaders.each(function(_, el) {
var $el = $(el);
if (_this5.options.store && !$el.is(_constants.SELECTOR_UNRESIZABLE)) {
var width = _this5.options.store.get(_this5.generateColumnId($el));
if (width != null) {
_this5.setWidth(el, width);
}
}
});
}
}, {
key: 'onPointerDown',
/**
Pointer/mouse down handler
@method onPointerDown
@param event {Object} Event object associated with the interaction
**/
value: function onPointerDown(event) {
// Only applies to left-click dragging
if (event.which !== 1) {
return;
}
// If a previous operation is defined, we missed the last mouseup.
// Probably gobbled up by user mousing out the window then releasing.
// We'll simulate a pointerup here prior to it
if (this.operation) {
this.onPointerUp(event);
}
// Ignore non-resizable columns
var $currentGrip = $(event.currentTarget);
if ($currentGrip.is(_constants.SELECTOR_UNRESIZABLE)) {
return;
}
console.log('鼠标单击')
var gripIndex = $currentGrip.index();
var $leftColumn = this.$tableHeaders.eq(gripIndex).not(_constants.SELECTOR_UNRESIZABLE);
var $rightColumn = this.$tableHeaders.eq(gripIndex + 1).not(_constants.SELECTOR_UNRESIZABLE);
var leftWidth = this.parseWidth($leftColumn[0]);
var rightWidth = this.parseWidth($rightColumn[0]);
this.operation = {
$leftColumn: $leftColumn,
$rightColumn: $rightColumn,
$currentGrip: $currentGrip,
startX: this.getPointerX(event),
widths: {
left: leftWidth,
right: rightWidth
},
newWidths: {
left: leftWidth,
right: rightWidth
}
};
this.bindEvents(this.$ownerDocument, ['mousemove', 'touchmove'], this.onPointerMove.bind(this));
this.bindEvents(this.$ownerDocument, ['mouseup', 'touchend'], this.onPointerUp.bind(this));
this.$handleContainer.add(this.$table).addClass(_constants.CLASS_TABLE_RESIZING);
$leftColumn.add($rightColumn).add($currentGrip).addClass(_constants.CLASS_COLUMN_RESIZING);
this.triggerEvent(_constants.EVENT_RESIZE_START, [$leftColumn, $rightColumn, leftWidth, rightWidth], event);
event.preventDefault();
}
}, {
key: 'onPointerMove',
/**
Pointer/mouse movement handler
@method onPointerMove
@param event {Object} Event object associated with the interaction
**/
value: function onPointerMove(event) {
var op = this.operation;
if (!this.operation) {
return;
}
// Determine the delta change between start and new mouse position, as a percentage of the table width
var difference = (this.getPointerX(event) - op.startX) / this.$table.width() * 100;
if (difference === 0) {
return;
}
var leftColumn = op.$leftColumn[0];
var rightColumn = op.$rightColumn[0];
var widthLeft = undefined,
widthRight = undefined;
if (difference > 0) {
widthLeft = this.constrainWidth(op.widths.left + (op.widths.right - op.newWidths.right));
widthRight = this.constrainWidth(op.widths.right - difference);
} else if (difference < 0) {
widthLeft = this.constrainWidth(op.widths.left + difference);
widthRight = this.constrainWidth(op.widths.right + (op.widths.left - op.newWidths.left));
}
if (leftColumn) {
this.setWidth(leftColumn, widthLeft);
}
if (rightColumn) {
this.setWidth(rightColumn, widthRight);
}
op.newWidths.left = widthLeft;
op.newWidths.right = widthRight;
return this.triggerEvent(_constants.EVENT_RESIZE, [op.$leftColumn, op.$rightColumn, widthLeft, widthRight], event);
}
}, {
key: 'onPointerUp',
/**
Pointer/mouse release handler
@method onPointerUp
@param event {Object} Event object associated with the interaction
**/
value: function onPointerUp(event) {
var op = this.operation;
if (!this.operation) {
return;
}
this.unbindEvents(this.$ownerDocument, ['mouseup', 'touchend', 'mousemove', 'touchmove']);
this.$handleContainer.add(this.$table).removeClass(_constants.CLASS_TABLE_RESIZING);
op.$leftColumn.add(op.$rightColumn).add(op.$currentGrip).removeClass(_constants.CLASS_COLUMN_RESIZING);
this.syncHandleWidths();
this.saveColumnWidths();
this.operation = null;
// event.which = 0;
console.log('鼠标抬起', event)
this.onPointerDown(event);
return this.triggerEvent(_constants.EVENT_RESIZE_STOP, [op.$leftColumn, op.$rightColumn, op.newWidths.left, op.newWidths.right], event);
}
}, {
key: 'destroy',
/**
Removes all event listeners, data, and added DOM elements. Takes
the <table/> element back to how it was, and returns it
@method destroy
@return {jQuery} Original jQuery-wrapped <table> element
**/
value: function destroy() {
var $table = this.$table;
var $handles = this.$handleContainer.find('.' + _constants.CLASS_HANDLE);
this.unbindEvents(this.$window.add(this.$ownerDocument).add(this.$table).add($handles));
$handles.removeData(_constants.DATA_TH);
$table.removeData(_constants.DATA_API);
this.$handleContainer.remove();
this.$handleContainer = null;
this.$tableHeaders = null;
this.$table = null;
return $table;
}
}, {
key: 'bindEvents',
/**
Binds given events for this instance to the given target DOMElement
@private
@method bindEvents
@param target {jQuery} jQuery-wrapped DOMElement to bind events to
@param events {String|Array} Event name (or array of) to bind
@param selectorOrCallback {String|Function} Selector string or callback
@param [callback] {Function} Callback method
**/
value: function bindEvents($target, events, selectorOrCallback, callback) {
if (typeof events === 'string') {
events = events + this.ns;
} else {
events = events.join(this.ns + ' ') + this.ns;
}
if (arguments.length > 3) {
$target.on(events, selectorOrCallback, callback);
} else {
$target.on(events, selectorOrCallback);
}
}
}, {
key: 'unbindEvents',
/**
Unbinds events specific to this instance from the given target DOMElement
@private
@method unbindEvents
@param target {jQuery} jQuery-wrapped DOMElement to unbind events from
@param events {String|Array} Event name (or array of) to unbind
**/
value: function unbindEvents($target, events) {
if (typeof events === 'string') {
events = events + this.ns;
} else if (events != null) {
events = events.join(this.ns + ' ') + this.ns;
} else {
events = this.ns;
}
$target.off(events);
}
}, {
key: 'triggerEvent',
/**
Triggers an event on the <table/> element for a given type with given
arguments, also setting and allowing access to the originalEvent if
given. Returns the result of the triggered event.
@private
@method triggerEvent
@param type {String} Event name
@param args {Array} Array of arguments to pass through
@param [originalEvent] If given, is set on the event object
@return {Mixed} Result of the event trigger action
**/
value: function triggerEvent(type, args, originalEvent) {
var event = $.Event(type);
if (event.originalEvent) {
event.originalEvent = $.extend({}, originalEvent);
}
return this.$table.trigger(event, [this].concat(args || []));
}
}, {
key: 'generateColumnId',
/**
Calculates a unique column ID for a given column DOMElement
@private
@method generateColumnId
@param $el {jQuery} jQuery-wrapped column element
@return {String} Column ID
**/
value: function generateColumnId($el) {
return this.$table.data(_constants.DATA_COLUMNS_ID) + '-' + $el.data(_constants.DATA_COLUMN_ID);
}
}, {
key: 'parseWidth',
/**
Parses a given DOMElement's width into a float
@private
@method parseWidth
@param element {DOMElement} Element to get width of
@return {Number} Element's width as a float
**/
value: function parseWidth(element) {
return element ? parseFloat(element.style.width.replace('%', '')) : 0;
}
}, {
key: 'setWidth',
/**
Sets the percentage width of a given DOMElement
@private
@method setWidth
@param element {DOMElement} Element to set width on
@param width {Number} Width, as a percentage, to set
**/
value: function setWidth(element, width) {
width = width.toFixed(2);
width = width > 0 ? width : 0;
element.style.width = width + '%';
}
}, {
key: 'constrainWidth',
/**
Constrains a given width to the minimum and maximum ranges defined in
the `minWidth` and `maxWidth` configuration options, respectively.
@private
@method constrainWidth
@param width {Number} Width to constrain
@return {Number} Constrained width
**/
value: function constrainWidth(width) {
if (this.options.minWidth != undefined) {
width = Math.max(this.options.minWidth, width);
}
if (this.options.maxWidth != undefined) {
width = Math.min(this.options.maxWidth, width);
}
return width;
}
}, {
key: 'getPointerX',
/**
Given a particular Event object, retrieves the current pointer offset along
the horizontal direction. Accounts for both regular mouse clicks as well as
pointer-like systems (mobiles, tablets etc.)
@private
@method getPointerX
@param event {Object} Event object associated with the interaction
@return {Number} Horizontal pointer offset
**/
value: function getPointerX(event) {
if (event.type.indexOf('touch') === 0) {
return (event.originalEvent.touches[0] || event.originalEvent.changedTouches[0]).pageX;
}
return event.pageX;
}
}]);
return ResizableColumns;
})();
exports['default'] = ResizableColumns;
ResizableColumns.defaults = {
selector: function selector($table) {
if ($table.find('thead').length) {
return _constants.SELECTOR_TH;
}
return _constants.SELECTOR_TD;
},
store: window.store,
syncHandlers: true,
resizeFromBody: true,
maxWidth: null,
minWidth: 0.01
};
ResizableColumns.count = 0;
module.exports = exports['default'];
}, {
"./constants": 3
}],
3: [function(require, module, exports) {
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
var DATA_API = 'resizableColumns';
exports.DATA_API = DATA_API;
var DATA_COLUMNS_ID = 'resizable-columns-id';
exports.DATA_COLUMNS_ID = DATA_COLUMNS_ID;
var DATA_COLUMN_ID = 'resizable-column-id';
exports.DATA_COLUMN_ID = DATA_COLUMN_ID;
var DATA_TH = 'th';
exports.DATA_TH = DATA_TH;
var CLASS_TABLE_RESIZING = 'rc-table-resizing';
exports.CLASS_TABLE_RESIZING = CLASS_TABLE_RESIZING;
var CLASS_COLUMN_RESIZING = 'rc-column-resizing';
exports.CLASS_COLUMN_RESIZING = CLASS_COLUMN_RESIZING;
var CLASS_HANDLE = 'rc-handle';
exports.CLASS_HANDLE = CLASS_HANDLE;
var CLASS_HANDLE_CONTAINER = 'rc-handle-container';
exports.CLASS_HANDLE_CONTAINER = CLASS_HANDLE_CONTAINER;
var EVENT_RESIZE_START = 'column:resize:start';
exports.EVENT_RESIZE_START = EVENT_RESIZE_START;
var EVENT_RESIZE = 'column:resize';
exports.EVENT_RESIZE = EVENT_RESIZE;
var EVENT_RESIZE_STOP = 'column:resize:stop';
exports.EVENT_RESIZE_STOP = EVENT_RESIZE_STOP;
var SELECTOR_TH = 'tr:first > th:visible';
exports.SELECTOR_TH = SELECTOR_TH;
var SELECTOR_TD = 'tr:first > td:visible';
exports.SELECTOR_TD = SELECTOR_TD;
var SELECTOR_UNRESIZABLE = '[data-noresize]';
exports.SELECTOR_UNRESIZABLE = SELECTOR_UNRESIZABLE;
}, {}],
4: [function(require, module, exports) {
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
'default': obj
};
}
var _class = require('./class');
var _class2 = _interopRequireDefault(_class);
var _adapter = require('./adapter');
var _adapter2 = _interopRequireDefault(_adapter);
exports['default'] = _class2['default'];
module.exports = exports['default'];
}, {
"./adapter": 1,
"./class": 2
}]
}, {}, [4])