Skip to content

Commit

Permalink
Add plugin autoRowSize and refactor autoColumnSize. #493
Browse files Browse the repository at this point in the history
  • Loading branch information
budnix committed Jul 6, 2015
1 parent 402486b commit c0a139c
Show file tree
Hide file tree
Showing 51 changed files with 2,746 additions and 791 deletions.
1 change: 1 addition & 0 deletions demo/dragdown.html
Expand Up @@ -99,6 +99,7 @@ <h2>Drag-down</h2>
rowHeaders: true,
colHeaders: true,
minSpareRows: 1,
contextMenu: true,
fillHandle: true // possible values: true, false, "horizontal", "vertical"
});
hot1.loadData(data);
Expand Down
2 changes: 2 additions & 0 deletions demo/sorting.html
Expand Up @@ -158,6 +158,8 @@ <h2>Column sorting</h2>
],
manualColumnMove: true,
manualColumnResize: true,
manualRowMove: true,
manualRowResize: true,
minSpareRows: 1,
contextMenu: true,
persistentState: true
Expand Down
252 changes: 252 additions & 0 deletions lib/es6collections/es6collections.js
@@ -0,0 +1,252 @@
/*!
* Copyright (C) 2011 by Andrea Giammarchi, @WebReflection
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
(function(exports) {
'use strict';
//shared pointer
var i;
//shortcuts
var defineProperty = Object.defineProperty,
is = function(a, b) {
return isNaN(a) ? isNaN(b) : a === b;
};


//Polyfill global objects
if (typeof WeakMap == 'undefined') {
exports.WeakMap = createCollection({
// WeakMap#delete(key:void*):boolean
'delete': sharedDelete,
// WeakMap#clear():
clear: sharedClear,
// WeakMap#get(key:void*):void*
get: sharedGet,
// WeakMap#has(key:void*):boolean
has: mapHas,
// WeakMap#set(key:void*, value:void*):void
set: sharedSet
}, true);
}

if (typeof Map == 'undefined') {
exports.Map = createCollection({
// WeakMap#delete(key:void*):boolean
'delete': sharedDelete,
//:was Map#get(key:void*[, d3fault:void*]):void*
// Map#has(key:void*):boolean
has: mapHas,
// Map#get(key:void*):boolean
get: sharedGet,
// Map#set(key:void*, value:void*):void
set: sharedSet,
// Map#keys(void):Iterator
keys: sharedKeys,
// Map#values(void):Iterator
values: sharedValues,
// Map#entries(void):Iterator
entries: mapEntries,
// Map#forEach(callback:Function, context:void*):void ==> callback.call(context, key, value, mapObject) === not in specs`
forEach: sharedForEach,
// Map#clear():
clear: sharedClear
});
}

if (typeof Set == 'undefined') {
exports.Set = createCollection({
// Set#has(value:void*):boolean
has: setHas,
// Set#add(value:void*):boolean
add: sharedAdd,
// Set#delete(key:void*):boolean
'delete': sharedDelete,
// Set#clear():
clear: sharedClear,
// Set#keys(void):Iterator
keys: sharedValues, // specs actually say "the same function object as the initial value of the values property"
// Set#values(void):Iterator
values: sharedValues,
// Set#entries(void):Iterator
entries: setEntries,
// Set#forEach(callback:Function, context:void*):void ==> callback.call(context, value, index) === not in specs
forEach: sharedForEach
});
}

if (typeof WeakSet == 'undefined') {
exports.WeakSet = createCollection({
// WeakSet#delete(key:void*):boolean
'delete': sharedDelete,
// WeakSet#add(value:void*):boolean
add: sharedAdd,
// WeakSet#clear():
clear: sharedClear,
// WeakSet#has(value:void*):boolean
has: setHas
}, true);
}


/**
* ES6 collection constructor
* @return {Function} a collection class
*/
function createCollection(proto, objectOnly) {
function Collection(a) {
if (!this || this.constructor !== Collection) return new Collection(a);
this._keys = [];
this._values = [];
this._itp = []; // iteration pointers
this.objectOnly = objectOnly;

//parse initial iterable argument passed
if (a) init.call(this, a);
}

//define size for non object-only collections
if (!objectOnly) {
defineProperty(proto, 'size', {
get: sharedSize
});
}

//set prototype
proto.constructor = Collection;
Collection.prototype = proto;

return Collection;
}


/** parse initial iterable argument passed */
function init(a) {
var i;
//init Set argument, like `[1,2,3,{}]`
if (this.add) a.forEach(this.add, this);
//init Map argument like `[[1,2], [{}, 4]]`
else a.forEach(function(a) {
this.set(a[0], a[1])
}, this);
}


/** delete */
function sharedDelete(key) {
if (this.has(key)) {
this._keys.splice(i, 1);
this._values.splice(i, 1);
// update iteration pointers
this._itp.forEach(function(p) {
if (i < p[0]) p[0]--;
});
}
// Aurora here does it while Canary doesn't
return -1 < i;
};

function sharedGet(key) {
return this.has(key) ? this._values[i] : undefined;
}

function has(list, key) {
if (this.objectOnly && key !== Object(key)) throw new TypeError("Invalid value used as weak collection key");
//NaN or 0 passed
if (key != key || key === 0) for (i = list.length; i-- && !is(list[i], key);) {} else i = list.indexOf(key);
return -1 < i;
}

function setHas(value) {
return has.call(this, this._values, value);
}

function mapHas(value) {
return has.call(this, this._keys, value);
}

/** @chainable */
function sharedSet(key, value) {
this.has(key) ? this._values[i] = value : this._values[this._keys.push(key) - 1] = value;
return this;
}

/** @chainable */
function sharedAdd(value) {
if (!this.has(value)) this._values.push(value);
return this;
}

function sharedClear() {
this._values.length = 0;
}

/** keys, values, and iterate related methods */
function sharedKeys() {
return sharedIterator(this._itp, this._keys);
}

function sharedValues() {
return sharedIterator(this._itp, this._values);
}

function mapEntries() {
return sharedIterator(this._itp, this._keys, this._values);
}

function setEntries() {
return sharedIterator(this._itp, this._values, this._values);
}

function sharedIterator(itp, array, array2) {
var p = [0],
done = false;
itp.push(p);
return {
next: function() {
var v, k = p[0];
if (!done && k < array.length) {
v = array2 ? [array[k], array2[k]] : array[k];
p[0]++;
} else {
done = true;
itp.splice(itp.indexOf(p), 1);
}
return {
done: done,
value: v
};
}
};
}

function sharedSize() {
return this._values.length;
}

function sharedForEach(callback, context) {
var it = this.entries();
for (;;) {
var r = it.next();
if (r.done) break;
callback.call(context, r.value[1], r.value[0], this);
}
}

})(typeof exports != 'undefined' && typeof global != 'undefined' ? global : window);
1 change: 1 addition & 0 deletions src/3rdparty/walkontable/src/settings.js
Expand Up @@ -21,6 +21,7 @@ class WalkontableSettings {
debug: false, // shows WalkontableDebugOverlay

// presentation mode
externalRowCalculator: false,
stretchH: 'none', // values: all, last, none
currentRowClassName: null,
currentColumnClassName: null,
Expand Down
5 changes: 0 additions & 5 deletions src/3rdparty/walkontable/src/table.js
Expand Up @@ -496,11 +496,6 @@ class WalkontableTable {
} else if (typeof width === 'object') {
width = width[sourceColumn];
}
let oversizedWidth = this.wot.wtViewport.oversizedCols[sourceColumn];

if (oversizedWidth !== void 0) {
width = width ? Math.max(width, oversizedWidth) : oversizedWidth;
}

return width;
}
Expand Down
12 changes: 10 additions & 2 deletions src/3rdparty/walkontable/src/tableRenderer.js
Expand Up @@ -153,6 +153,8 @@ class WalkontableTableRenderer {
let height = this.wot.wtTable.getRowHeight(sourceRowIndex);

if (height) {
// Decrease height. 1 pixel will be "replaced" by 1px border top
height--;
TR.firstChild.style.height = height + 'px';
} else {
TR.firstChild.style.height = '';
Expand All @@ -169,6 +171,9 @@ class WalkontableTableRenderer {
* @param {Number} sourceRow Row index
*/
resetOversizedRow(sourceRow) {
if (this.wot.getSetting('externalRowCalculator')) {
return;
}
if (this.wot.wtViewport.oversizedRows && this.wot.wtViewport.oversizedRows[sourceRow]) {
this.wot.wtViewport.oversizedRows[sourceRow] = void 0;
}
Expand All @@ -178,6 +183,9 @@ class WalkontableTableRenderer {
* Check if any of the rendered rows is higher than expected, and if so, cache them
*/
markOversizedRows() {
if (this.wot.getSetting('externalRowCalculator')) {
return;
}
let rowCount = this.instance.wtTable.TBODY.childNodes.length;
let expectedTableHeight = rowCount * this.instance.wtSettings.settings.defaultRowHeight;
let actualTableHeight = dom.innerHeight(this.instance.wtTable.TBODY) - 1;
Expand All @@ -202,12 +210,12 @@ class WalkontableTableRenderer {
if (rowHeader) {
rowInnerHeight = dom.innerHeight(rowHeader);
} else {
rowInnerHeight = dom.innerHeight(currentTr) - 1;
rowInnerHeight = dom.innerHeight(currentTr);
}

if ((!previousRowHeight && this.instance.wtSettings.settings.defaultRowHeight < rowInnerHeight ||
previousRowHeight < rowInnerHeight)) {
this.instance.wtViewport.oversizedRows[sourceRowIndex] = rowInnerHeight;
this.instance.wtViewport.oversizedRows[sourceRowIndex] = ++rowInnerHeight;
}
}
}
Expand Down
8 changes: 3 additions & 5 deletions src/3rdparty/walkontable/src/viewport.js
@@ -1,6 +1,6 @@

import * as dom from './../../../dom.js';
import {eventManager as eventManagerObject} from './../../../eventManager.js';
import {EventManager} from './../../../eventManager.js';
import {WalkontableViewportColumnsCalculator} from './calculator/viewportColumns.js';
import {WalkontableViewportRowsCalculator} from './calculator/viewportRows.js';

Expand All @@ -19,17 +19,15 @@ class WalkontableViewport {
this.instance = this.wot;

this.oversizedRows = [];
this.oversizedCols = [];
this.oversizedColumnHeaders = [];
this.clientHeight = 0;
this.containerWidth = NaN;
this.rowHeaderWidth = NaN;
this.rowsVisibleCalculator = null;
this.columnsVisibleCalculator = null;

const eventManager = eventManagerObject(wotInstance);

eventManager.addEventListener(window, 'resize', () => {
this.eventManager = new EventManager(this.wot);
this.eventManager.addEventListener(window, 'resize', () => {
this.clientHeight = this.getWorkspaceHeight();
});
}
Expand Down
7 changes: 1 addition & 6 deletions src/browser.js
Expand Up @@ -13,13 +13,8 @@ window.Handsontable = function Handsontable(rootElement, userSettings) {
Handsontable.version = version;
Handsontable.buildDate = buildDate;

import './shims/array.filter.js';
import './shims/array.indexOf.js';
import './shims/array.isArray.js';
import './shims/classes.js';
import './shims/object.keys.js';
import './shims/string.trim.js';
import './shims/weakmap.js';
import 'es6collections';

Handsontable.plugins = {};

Expand Down

0 comments on commit c0a139c

Please sign in to comment.