Browse files

Merge branch 'release/v0.10.3'

  • Loading branch information...
2 parents 59b5bad + cdedc12 commit 365c93ce9290611fbb78256751b96e2af6816e27 @psmolenski psmolenski committed Feb 10, 2014
View
11 CHANGELOG.md
@@ -1,3 +1,14 @@
+## [0.10.3](https://github.com/warpech/jquery-handsontable/tree/v0.10.3) (Feb 10, 2014)
+
+Changes since 0.10.2:
+
+- fixed undoing/redoing remove rows/columns form tables with `minSpareRows`/`minSpareCols` ([#1262](https://github.com/warpech/jquery-handsontable/issues/1262))
+- `dateEditor` now allows to type date manually ([#1266](https://github.com/warpech/jquery-handsontable/issues/1266))
+- fixed typing any value in `autocompleteEditor`, when `filter` property is set to `true` ([#1275](https://github.com/warpech/jquery-handsontable/issues/1275))
+- values typed in `autocompleteEditor` and `dropdownEditor` won't be recognized as regex anymore ([#1295](https://github.com/warpech/jquery-handsontable/issues/1295))
+- fixed copying values from cells with explicitly set `type` property ([#1300](https://github.com/warpech/jquery-handsontable/issues/1300))
+
+
## [0.10.2](https://github.com/warpech/jquery-handsontable/tree/v0.10.2) (Jan 23, 2014)
Features:
View
3 Gruntfile.js
@@ -225,7 +225,8 @@ module.exports = function (grunt) {
styles: [
'test/jasmine/css/SpecRunner.css',
'dist/jquery.handsontable.css',
- 'extensions/jquery.handsontable.removeRow.css'
+ 'extensions/jquery.handsontable.removeRow.css',
+ 'lib/jquery-ui/css/ui-bootstrap/jquery-ui.custom.css'
],
vendor: [
'lib/jquery.min.js',
View
2 bower.json
@@ -1,6 +1,6 @@
{
"name": "handsontable",
- "version": "0.10.2",
+ "version": "0.10.3",
"main": ["./dist/jquery.handsontable.full.js", "./dist/jquery.handsontable.full.css"],
"ignore": [
"**/.*",
View
4 dist/jquery.handsontable.css
@@ -1,12 +1,12 @@
/**
- * Handsontable 0.10.2
+ * Handsontable 0.10.3
* Handsontable is a simple jQuery plugin for editable tables with basic copy-paste compatibility with Excel and Google Docs
*
* Copyright 2012, Marcin Warpechowski
* Licensed under the MIT license.
* http://handsontable.com/
*
- * Date: Thu Jan 23 2014 23:06:23 GMT+0100 (CET)
+ * Date: Mon Feb 10 2014 14:15:11 GMT+0100 (CET)
*/
.handsontable {
View
4 dist/jquery.handsontable.full.css
@@ -1,12 +1,12 @@
/**
- * Handsontable 0.10.2
+ * Handsontable 0.10.3
* Handsontable is a simple jQuery plugin for editable tables with basic copy-paste compatibility with Excel and Google Docs
*
* Copyright 2012, Marcin Warpechowski
* Licensed under the MIT license.
* http://handsontable.com/
*
- * Date: Thu Jan 23 2014 23:06:23 GMT+0100 (CET)
+ * Date: Mon Feb 10 2014 14:15:11 GMT+0100 (CET)
*/
.handsontable {
View
124 dist/jquery.handsontable.full.js
@@ -1,12 +1,12 @@
/**
- * Handsontable 0.10.2
+ * Handsontable 0.10.3
* Handsontable is a simple jQuery plugin for editable tables with basic copy-paste compatibility with Excel and Google Docs
*
* Copyright 2012, Marcin Warpechowski
* Licensed under the MIT license.
* http://handsontable.com/
*
- * Date: Thu Jan 23 2014 23:06:23 GMT+0100 (CET)
+ * Date: Mon Feb 10 2014 14:15:11 GMT+0100 (CET)
*/
/*jslint white: true, browser: true, plusplus: true, indent: 4, maxerr: 50 */
@@ -329,14 +329,14 @@ Handsontable.Core = function (rootElement, userSettings) {
rlen = instance.countRows();
if (rlen < priv.settings.minRows) {
for (r = 0; r < priv.settings.minRows - rlen; r++) {
- datamap.createRow();
+ datamap.createRow(instance.countRows(), 1, true);
}
}
//should I add empty rows to meet minSpareRows?
if (emptyRows < priv.settings.minSpareRows) {
for (; emptyRows < priv.settings.minSpareRows && instance.countRows() < priv.settings.maxRows; emptyRows++) {
- datamap.createRow();
+ datamap.createRow(instance.countRows(), 1, true);
}
}
@@ -346,14 +346,14 @@ Handsontable.Core = function (rootElement, userSettings) {
//should I add empty cols to meet minCols?
if (!priv.settings.columns && instance.countCols() < priv.settings.minCols) {
for (; instance.countCols() < priv.settings.minCols; emptyCols++) {
- datamap.createCol();
+ datamap.createCol(instance.countCols(), 1, true);
}
}
//should I add empty cols to meet minSpareCols?
if (!priv.settings.columns && instance.dataType === 'array' && emptyCols < priv.settings.minSpareCols) {
for (; emptyCols < priv.settings.minSpareCols && instance.countCols() < priv.settings.maxCols; emptyCols++) {
- datamap.createCol();
+ datamap.createCol(instance.countCols(), 1, true);
}
}
@@ -2271,7 +2271,7 @@ Handsontable.Core = function (rootElement, userSettings) {
/**
* Handsontable version
*/
- this.version = '0.10.2'; //inserted by grunt from package.json
+ this.version = '0.10.3'; //inserted by grunt from package.json
};
var DefaultSettings = function () {};
@@ -3635,7 +3635,26 @@ Handsontable.helper.proxy = function (fun, context) {
};
};
-Handsontable.helper.cellMethodLookupFactory = function (methodName) {
+/**
+ * Factory that produces a function for searching methods (or any properties) which could be defined directly in
+ * table configuration or implicitly, within cell type definition.
+ *
+ * For example: renderer can be defined explicitly using "renderer" property in column configuration or it can be
+ * defined implicitly using "type" property.
+ *
+ * Methods/properties defined explicitly always takes precedence over those defined through "type".
+ *
+ * If the method/property is not found in an object, searching is continued recursively through prototype chain, until
+ * it reaches the Object.prototype.
+ *
+ *
+ * @param methodName {String} name of the method/property to search (i.e. 'renderer', 'validator', 'copyable')
+ * @param allowUndefined {Boolean} [optional] if false, the search is continued if methodName has not been found in cell "type"
+ * @returns {Function}
+ */
+Handsontable.helper.cellMethodLookupFactory = function (methodName, allowUndefined) {
+
+ allowUndefined = typeof allowUndefined == 'undefined' ? true : allowUndefined;
return function cellMethodLookup (row, col) {
@@ -3660,7 +3679,12 @@ Handsontable.helper.cellMethodLookupFactory = function (methodName) {
type = translateTypeNameToObject(properties.type);
- return type[methodName]; //method defined in type. if does not exist (eg. validator), returns undefined
+ if (type.hasOwnProperty(methodName)) {
+ return type[methodName]; //method defined in type.
+ } else if (allowUndefined) {
+ return; //method does not defined in type (eg. validator), returns undefined
+ }
+
}
return getMethodFromProperties(Handsontable.helper.getPrototypeOf(properties));
@@ -3855,7 +3879,7 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
* Creates row at the bottom of the data array
* @param {Number} [index] Optional. Index of the row before which the new row will be inserted
*/
- Handsontable.DataMap.prototype.createRow = function (index, amount) {
+ Handsontable.DataMap.prototype.createRow = function (index, amount, createdAutomatically) {
var row
, colCount = this.instance.countCols()
, numberOfCreatedRows = 0
@@ -3898,7 +3922,7 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
}
- this.instance.PluginHooks.run('afterCreateRow', index, numberOfCreatedRows);
+ this.instance.PluginHooks.run('afterCreateRow', index, numberOfCreatedRows, createdAutomatically);
this.instance.forceFullRender = true; //used when data was changed
return numberOfCreatedRows;
@@ -3909,7 +3933,7 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
* @param {Number} [index] Optional. Index of the column before which the new column will be inserted
* * @param {Number} [amount] Optional.
*/
- Handsontable.DataMap.prototype.createCol = function (index, amount) {
+ Handsontable.DataMap.prototype.createCol = function (index, amount, createdAutomatically) {
if (this.instance.dataType === 'object' || this.instance.getSettings().columns) {
throw new Error("Cannot create new column. When data source in an object, " +
"you can only have as much columns as defined in first data row, data schema or in the 'columns' setting." +
@@ -3952,7 +3976,7 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
currentIndex++;
}
- this.instance.PluginHooks.run('afterCreateCol', index, numberOfCreatedCols);
+ this.instance.PluginHooks.run('afterCreateCol', index, numberOfCreatedCols, createdAutomatically);
this.instance.forceFullRender = true; //used when data was changed
return numberOfCreatedCols;
@@ -4127,7 +4151,7 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
}
};
- var copyableLookup = Handsontable.helper.cellMethodLookupFactory('copyable');
+ var copyableLookup = Handsontable.helper.cellMethodLookupFactory('copyable', false);
/**
* Returns single value from the data array (intended for clipboard copy to an external application)
@@ -5069,8 +5093,8 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
showButtonPanel: true,
changeMonth: true,
changeYear: true,
- altField: this.$textarea,
- onSelect: function () {
+ onSelect: function (dateStr) {
+ that.setValue(dateStr);
that.finishEditing(false);
}
};
@@ -5360,10 +5384,13 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
hot.updateSettings({
'colWidths': [this.wtDom.outerWidth(this.TEXTAREA) - 2],
- afterRenderer: function (TD, row, col, prop, value, cellProperties) {
- var match = TD.innerHTML.match(new RegExp(that.query, 'i'));
- if(match){
- TD.innerHTML = value.replace(match[0], '<strong>' + match[0] + '</strong>');
+ afterRenderer: function (TD, row, col, prop, value) {
+ var caseSensitive = this.getCellMeta(row, col).filteringCaseSensitive === true;
+ var indexOfMatch = caseSensitive ? value.indexOf(that.query) : value.toLowerCase().indexOf(that.query.toLowerCase());
+
+ if(indexOfMatch != -1){
+ var match = value.substr(indexOfMatch, that.query.length);
+ TD.innerHTML = value.replace(match, '<strong>' + match + '</strong>');
}
}
});
@@ -5430,10 +5457,17 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
choices = this.cellProperties.source;
} else {
- var queryRegex = new RegExp(query, this.cellProperties.filteringCaseSensitive === true ? '' : 'i');
+ var filteringCaseSensitive = this.cellProperties.filteringCaseSensitive === true;
+ var lowerCaseQuery = query.toLowerCase();
choices = this.cellProperties.source.filter(function(choice){
- return queryRegex.test(choice);
+
+ if (filteringCaseSensitive) {
+ return choice.indexOf(query) != -1;
+ } else {
+ return choice.toLowerCase().indexOf(lowerCaseQuery) != -1;
+ }
+
});
}
@@ -5492,7 +5526,7 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
rowToHighlight = findItemIndexToHighlight(choices, value);
- if ( typeof rowToHighlight == 'undefined'){
+ if ( typeof rowToHighlight == 'undefined' && this.cellProperties.allowInvalid === false){
rowToHighlight = 0;
}
@@ -6920,26 +6954,26 @@ Handsontable.PluginHookClass = (function () {
}
PluginHookClass.prototype.add = function (key, fn) {
- // provide support for old versions of HOT
- if (key in legacy) {
- key = legacy[key];
- }
-
- if (typeof this.hooks[key] === "undefined") {
- this.hooks[key] = [];
- }
-
+ //if fn is array, run this for all the array items
if (Handsontable.helper.isArray(fn)) {
for (var i = 0, len = fn.length; i < len; i++) {
- this.hooks[key].push(fn[i]);
- }
- } else {
- if (this.hooks[key].indexOf(fn) > -1) {
- throw new Error("Seems that you are trying to set the same plugin hook twice (" + key + ", " + fn + ")"); //error here should help writing bug-free plugins
+ this.add(key, fn[i]);
}
- this.hooks[key].push(fn);
}
+ else {
+ // provide support for old versions of HOT
+ if (key in legacy) {
+ key = legacy[key];
+ }
+
+ if (typeof this.hooks[key] === "undefined") {
+ this.hooks[key] = [];
+ }
+ if (this.hooks[key].indexOf(fn) == -1) {
+ this.hooks[key].push(fn); //only add a hook if it has not already be added (adding the same hook twice is now silently ignored)
+ }
+ }
return this;
};
@@ -8908,7 +8942,12 @@ function Storage(prefix) {
}
});
- instance.addHook("afterCreateRow", function (index, amount) {
+ instance.addHook("afterCreateRow", function (index, amount, createdAutomatically) {
+
+ if (createdAutomatically) {
+ return;
+ }
+
var action = new Handsontable.UndoRedo.CreateRowAction(index, amount);
plugin.done(action);
});
@@ -8921,7 +8960,12 @@ function Storage(prefix) {
plugin.done(action);
});
- instance.addHook("afterCreateCol", function (index, amount) {
+ instance.addHook("afterCreateCol", function (index, amount, createdAutomatically) {
+
+ if (createdAutomatically) {
+ return;
+ }
+
var action = new Handsontable.UndoRedo.CreateColumnAction(index, amount);
plugin.done(action);
});
View
124 dist/jquery.handsontable.js
@@ -1,12 +1,12 @@
/**
- * Handsontable 0.10.2
+ * Handsontable 0.10.3
* Handsontable is a simple jQuery plugin for editable tables with basic copy-paste compatibility with Excel and Google Docs
*
* Copyright 2012, Marcin Warpechowski
* Licensed under the MIT license.
* http://handsontable.com/
*
- * Date: Thu Jan 23 2014 23:06:23 GMT+0100 (CET)
+ * Date: Mon Feb 10 2014 14:15:11 GMT+0100 (CET)
*/
/*jslint white: true, browser: true, plusplus: true, indent: 4, maxerr: 50 */
@@ -329,14 +329,14 @@ Handsontable.Core = function (rootElement, userSettings) {
rlen = instance.countRows();
if (rlen < priv.settings.minRows) {
for (r = 0; r < priv.settings.minRows - rlen; r++) {
- datamap.createRow();
+ datamap.createRow(instance.countRows(), 1, true);
}
}
//should I add empty rows to meet minSpareRows?
if (emptyRows < priv.settings.minSpareRows) {
for (; emptyRows < priv.settings.minSpareRows && instance.countRows() < priv.settings.maxRows; emptyRows++) {
- datamap.createRow();
+ datamap.createRow(instance.countRows(), 1, true);
}
}
@@ -346,14 +346,14 @@ Handsontable.Core = function (rootElement, userSettings) {
//should I add empty cols to meet minCols?
if (!priv.settings.columns && instance.countCols() < priv.settings.minCols) {
for (; instance.countCols() < priv.settings.minCols; emptyCols++) {
- datamap.createCol();
+ datamap.createCol(instance.countCols(), 1, true);
}
}
//should I add empty cols to meet minSpareCols?
if (!priv.settings.columns && instance.dataType === 'array' && emptyCols < priv.settings.minSpareCols) {
for (; emptyCols < priv.settings.minSpareCols && instance.countCols() < priv.settings.maxCols; emptyCols++) {
- datamap.createCol();
+ datamap.createCol(instance.countCols(), 1, true);
}
}
@@ -2271,7 +2271,7 @@ Handsontable.Core = function (rootElement, userSettings) {
/**
* Handsontable version
*/
- this.version = '0.10.2'; //inserted by grunt from package.json
+ this.version = '0.10.3'; //inserted by grunt from package.json
};
var DefaultSettings = function () {};
@@ -3635,7 +3635,26 @@ Handsontable.helper.proxy = function (fun, context) {
};
};
-Handsontable.helper.cellMethodLookupFactory = function (methodName) {
+/**
+ * Factory that produces a function for searching methods (or any properties) which could be defined directly in
+ * table configuration or implicitly, within cell type definition.
+ *
+ * For example: renderer can be defined explicitly using "renderer" property in column configuration or it can be
+ * defined implicitly using "type" property.
+ *
+ * Methods/properties defined explicitly always takes precedence over those defined through "type".
+ *
+ * If the method/property is not found in an object, searching is continued recursively through prototype chain, until
+ * it reaches the Object.prototype.
+ *
+ *
+ * @param methodName {String} name of the method/property to search (i.e. 'renderer', 'validator', 'copyable')
+ * @param allowUndefined {Boolean} [optional] if false, the search is continued if methodName has not been found in cell "type"
+ * @returns {Function}
+ */
+Handsontable.helper.cellMethodLookupFactory = function (methodName, allowUndefined) {
+
+ allowUndefined = typeof allowUndefined == 'undefined' ? true : allowUndefined;
return function cellMethodLookup (row, col) {
@@ -3660,7 +3679,12 @@ Handsontable.helper.cellMethodLookupFactory = function (methodName) {
type = translateTypeNameToObject(properties.type);
- return type[methodName]; //method defined in type. if does not exist (eg. validator), returns undefined
+ if (type.hasOwnProperty(methodName)) {
+ return type[methodName]; //method defined in type.
+ } else if (allowUndefined) {
+ return; //method does not defined in type (eg. validator), returns undefined
+ }
+
}
return getMethodFromProperties(Handsontable.helper.getPrototypeOf(properties));
@@ -3855,7 +3879,7 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
* Creates row at the bottom of the data array
* @param {Number} [index] Optional. Index of the row before which the new row will be inserted
*/
- Handsontable.DataMap.prototype.createRow = function (index, amount) {
+ Handsontable.DataMap.prototype.createRow = function (index, amount, createdAutomatically) {
var row
, colCount = this.instance.countCols()
, numberOfCreatedRows = 0
@@ -3898,7 +3922,7 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
}
- this.instance.PluginHooks.run('afterCreateRow', index, numberOfCreatedRows);
+ this.instance.PluginHooks.run('afterCreateRow', index, numberOfCreatedRows, createdAutomatically);
this.instance.forceFullRender = true; //used when data was changed
return numberOfCreatedRows;
@@ -3909,7 +3933,7 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
* @param {Number} [index] Optional. Index of the column before which the new column will be inserted
* * @param {Number} [amount] Optional.
*/
- Handsontable.DataMap.prototype.createCol = function (index, amount) {
+ Handsontable.DataMap.prototype.createCol = function (index, amount, createdAutomatically) {
if (this.instance.dataType === 'object' || this.instance.getSettings().columns) {
throw new Error("Cannot create new column. When data source in an object, " +
"you can only have as much columns as defined in first data row, data schema or in the 'columns' setting." +
@@ -3952,7 +3976,7 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
currentIndex++;
}
- this.instance.PluginHooks.run('afterCreateCol', index, numberOfCreatedCols);
+ this.instance.PluginHooks.run('afterCreateCol', index, numberOfCreatedCols, createdAutomatically);
this.instance.forceFullRender = true; //used when data was changed
return numberOfCreatedCols;
@@ -4127,7 +4151,7 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
}
};
- var copyableLookup = Handsontable.helper.cellMethodLookupFactory('copyable');
+ var copyableLookup = Handsontable.helper.cellMethodLookupFactory('copyable', false);
/**
* Returns single value from the data array (intended for clipboard copy to an external application)
@@ -5069,8 +5093,8 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
showButtonPanel: true,
changeMonth: true,
changeYear: true,
- altField: this.$textarea,
- onSelect: function () {
+ onSelect: function (dateStr) {
+ that.setValue(dateStr);
that.finishEditing(false);
}
};
@@ -5360,10 +5384,13 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
hot.updateSettings({
'colWidths': [this.wtDom.outerWidth(this.TEXTAREA) - 2],
- afterRenderer: function (TD, row, col, prop, value, cellProperties) {
- var match = TD.innerHTML.match(new RegExp(that.query, 'i'));
- if(match){
- TD.innerHTML = value.replace(match[0], '<strong>' + match[0] + '</strong>');
+ afterRenderer: function (TD, row, col, prop, value) {
+ var caseSensitive = this.getCellMeta(row, col).filteringCaseSensitive === true;
+ var indexOfMatch = caseSensitive ? value.indexOf(that.query) : value.toLowerCase().indexOf(that.query.toLowerCase());
+
+ if(indexOfMatch != -1){
+ var match = value.substr(indexOfMatch, that.query.length);
+ TD.innerHTML = value.replace(match, '<strong>' + match + '</strong>');
}
}
});
@@ -5430,10 +5457,17 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
choices = this.cellProperties.source;
} else {
- var queryRegex = new RegExp(query, this.cellProperties.filteringCaseSensitive === true ? '' : 'i');
+ var filteringCaseSensitive = this.cellProperties.filteringCaseSensitive === true;
+ var lowerCaseQuery = query.toLowerCase();
choices = this.cellProperties.source.filter(function(choice){
- return queryRegex.test(choice);
+
+ if (filteringCaseSensitive) {
+ return choice.indexOf(query) != -1;
+ } else {
+ return choice.toLowerCase().indexOf(lowerCaseQuery) != -1;
+ }
+
});
}
@@ -5492,7 +5526,7 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
rowToHighlight = findItemIndexToHighlight(choices, value);
- if ( typeof rowToHighlight == 'undefined'){
+ if ( typeof rowToHighlight == 'undefined' && this.cellProperties.allowInvalid === false){
rowToHighlight = 0;
}
@@ -6920,26 +6954,26 @@ Handsontable.PluginHookClass = (function () {
}
PluginHookClass.prototype.add = function (key, fn) {
- // provide support for old versions of HOT
- if (key in legacy) {
- key = legacy[key];
- }
-
- if (typeof this.hooks[key] === "undefined") {
- this.hooks[key] = [];
- }
-
+ //if fn is array, run this for all the array items
if (Handsontable.helper.isArray(fn)) {
for (var i = 0, len = fn.length; i < len; i++) {
- this.hooks[key].push(fn[i]);
- }
- } else {
- if (this.hooks[key].indexOf(fn) > -1) {
- throw new Error("Seems that you are trying to set the same plugin hook twice (" + key + ", " + fn + ")"); //error here should help writing bug-free plugins
+ this.add(key, fn[i]);
}
- this.hooks[key].push(fn);
}
+ else {
+ // provide support for old versions of HOT
+ if (key in legacy) {
+ key = legacy[key];
+ }
+
+ if (typeof this.hooks[key] === "undefined") {
+ this.hooks[key] = [];
+ }
+ if (this.hooks[key].indexOf(fn) == -1) {
+ this.hooks[key].push(fn); //only add a hook if it has not already be added (adding the same hook twice is now silently ignored)
+ }
+ }
return this;
};
@@ -8908,7 +8942,12 @@ function Storage(prefix) {
}
});
- instance.addHook("afterCreateRow", function (index, amount) {
+ instance.addHook("afterCreateRow", function (index, amount, createdAutomatically) {
+
+ if (createdAutomatically) {
+ return;
+ }
+
var action = new Handsontable.UndoRedo.CreateRowAction(index, amount);
plugin.done(action);
});
@@ -8921,7 +8960,12 @@ function Storage(prefix) {
plugin.done(action);
});
- instance.addHook("afterCreateCol", function (index, amount) {
+ instance.addHook("afterCreateCol", function (index, amount, createdAutomatically) {
+
+ if (createdAutomatically) {
+ return;
+ }
+
var action = new Handsontable.UndoRedo.CreateColumnAction(index, amount);
plugin.done(action);
});
View
4 dist_wc/handsontable-table/jquery.handsontable.full.css
@@ -1,12 +1,12 @@
/**
- * Handsontable 0.10.2
+ * Handsontable 0.10.3
* Handsontable is a simple jQuery plugin for editable tables with basic copy-paste compatibility with Excel and Google Docs
*
* Copyright 2012, Marcin Warpechowski
* Licensed under the MIT license.
* http://handsontable.com/
*
- * Date: Thu Jan 23 2014 23:06:23 GMT+0100 (CET)
+ * Date: Mon Feb 10 2014 14:15:11 GMT+0100 (CET)
*/
.handsontable {
View
124 dist_wc/handsontable-table/jquery.handsontable.full.js
@@ -1,12 +1,12 @@
/**
- * Handsontable 0.10.2
+ * Handsontable 0.10.3
* Handsontable is a simple jQuery plugin for editable tables with basic copy-paste compatibility with Excel and Google Docs
*
* Copyright 2012, Marcin Warpechowski
* Licensed under the MIT license.
* http://handsontable.com/
*
- * Date: Thu Jan 23 2014 23:06:23 GMT+0100 (CET)
+ * Date: Mon Feb 10 2014 14:15:11 GMT+0100 (CET)
*/
/*jslint white: true, browser: true, plusplus: true, indent: 4, maxerr: 50 */
@@ -329,14 +329,14 @@ Handsontable.Core = function (rootElement, userSettings) {
rlen = instance.countRows();
if (rlen < priv.settings.minRows) {
for (r = 0; r < priv.settings.minRows - rlen; r++) {
- datamap.createRow();
+ datamap.createRow(instance.countRows(), 1, true);
}
}
//should I add empty rows to meet minSpareRows?
if (emptyRows < priv.settings.minSpareRows) {
for (; emptyRows < priv.settings.minSpareRows && instance.countRows() < priv.settings.maxRows; emptyRows++) {
- datamap.createRow();
+ datamap.createRow(instance.countRows(), 1, true);
}
}
@@ -346,14 +346,14 @@ Handsontable.Core = function (rootElement, userSettings) {
//should I add empty cols to meet minCols?
if (!priv.settings.columns && instance.countCols() < priv.settings.minCols) {
for (; instance.countCols() < priv.settings.minCols; emptyCols++) {
- datamap.createCol();
+ datamap.createCol(instance.countCols(), 1, true);
}
}
//should I add empty cols to meet minSpareCols?
if (!priv.settings.columns && instance.dataType === 'array' && emptyCols < priv.settings.minSpareCols) {
for (; emptyCols < priv.settings.minSpareCols && instance.countCols() < priv.settings.maxCols; emptyCols++) {
- datamap.createCol();
+ datamap.createCol(instance.countCols(), 1, true);
}
}
@@ -2271,7 +2271,7 @@ Handsontable.Core = function (rootElement, userSettings) {
/**
* Handsontable version
*/
- this.version = '0.10.2'; //inserted by grunt from package.json
+ this.version = '0.10.3'; //inserted by grunt from package.json
};
var DefaultSettings = function () {};
@@ -3635,7 +3635,26 @@ Handsontable.helper.proxy = function (fun, context) {
};
};
-Handsontable.helper.cellMethodLookupFactory = function (methodName) {
+/**
+ * Factory that produces a function for searching methods (or any properties) which could be defined directly in
+ * table configuration or implicitly, within cell type definition.
+ *
+ * For example: renderer can be defined explicitly using "renderer" property in column configuration or it can be
+ * defined implicitly using "type" property.
+ *
+ * Methods/properties defined explicitly always takes precedence over those defined through "type".
+ *
+ * If the method/property is not found in an object, searching is continued recursively through prototype chain, until
+ * it reaches the Object.prototype.
+ *
+ *
+ * @param methodName {String} name of the method/property to search (i.e. 'renderer', 'validator', 'copyable')
+ * @param allowUndefined {Boolean} [optional] if false, the search is continued if methodName has not been found in cell "type"
+ * @returns {Function}
+ */
+Handsontable.helper.cellMethodLookupFactory = function (methodName, allowUndefined) {
+
+ allowUndefined = typeof allowUndefined == 'undefined' ? true : allowUndefined;
return function cellMethodLookup (row, col) {
@@ -3660,7 +3679,12 @@ Handsontable.helper.cellMethodLookupFactory = function (methodName) {
type = translateTypeNameToObject(properties.type);
- return type[methodName]; //method defined in type. if does not exist (eg. validator), returns undefined
+ if (type.hasOwnProperty(methodName)) {
+ return type[methodName]; //method defined in type.
+ } else if (allowUndefined) {
+ return; //method does not defined in type (eg. validator), returns undefined
+ }
+
}
return getMethodFromProperties(Handsontable.helper.getPrototypeOf(properties));
@@ -3855,7 +3879,7 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
* Creates row at the bottom of the data array
* @param {Number} [index] Optional. Index of the row before which the new row will be inserted
*/
- Handsontable.DataMap.prototype.createRow = function (index, amount) {
+ Handsontable.DataMap.prototype.createRow = function (index, amount, createdAutomatically) {
var row
, colCount = this.instance.countCols()
, numberOfCreatedRows = 0
@@ -3898,7 +3922,7 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
}
- this.instance.PluginHooks.run('afterCreateRow', index, numberOfCreatedRows);
+ this.instance.PluginHooks.run('afterCreateRow', index, numberOfCreatedRows, createdAutomatically);
this.instance.forceFullRender = true; //used when data was changed
return numberOfCreatedRows;
@@ -3909,7 +3933,7 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
* @param {Number} [index] Optional. Index of the column before which the new column will be inserted
* * @param {Number} [amount] Optional.
*/
- Handsontable.DataMap.prototype.createCol = function (index, amount) {
+ Handsontable.DataMap.prototype.createCol = function (index, amount, createdAutomatically) {
if (this.instance.dataType === 'object' || this.instance.getSettings().columns) {
throw new Error("Cannot create new column. When data source in an object, " +
"you can only have as much columns as defined in first data row, data schema or in the 'columns' setting." +
@@ -3952,7 +3976,7 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
currentIndex++;
}
- this.instance.PluginHooks.run('afterCreateCol', index, numberOfCreatedCols);
+ this.instance.PluginHooks.run('afterCreateCol', index, numberOfCreatedCols, createdAutomatically);
this.instance.forceFullRender = true; //used when data was changed
return numberOfCreatedCols;
@@ -4127,7 +4151,7 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
}
};
- var copyableLookup = Handsontable.helper.cellMethodLookupFactory('copyable');
+ var copyableLookup = Handsontable.helper.cellMethodLookupFactory('copyable', false);
/**
* Returns single value from the data array (intended for clipboard copy to an external application)
@@ -5069,8 +5093,8 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
showButtonPanel: true,
changeMonth: true,
changeYear: true,
- altField: this.$textarea,
- onSelect: function () {
+ onSelect: function (dateStr) {
+ that.setValue(dateStr);
that.finishEditing(false);
}
};
@@ -5360,10 +5384,13 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
hot.updateSettings({
'colWidths': [this.wtDom.outerWidth(this.TEXTAREA) - 2],
- afterRenderer: function (TD, row, col, prop, value, cellProperties) {
- var match = TD.innerHTML.match(new RegExp(that.query, 'i'));
- if(match){
- TD.innerHTML = value.replace(match[0], '<strong>' + match[0] + '</strong>');
+ afterRenderer: function (TD, row, col, prop, value) {
+ var caseSensitive = this.getCellMeta(row, col).filteringCaseSensitive === true;
+ var indexOfMatch = caseSensitive ? value.indexOf(that.query) : value.toLowerCase().indexOf(that.query.toLowerCase());
+
+ if(indexOfMatch != -1){
+ var match = value.substr(indexOfMatch, that.query.length);
+ TD.innerHTML = value.replace(match, '<strong>' + match + '</strong>');
}
}
});
@@ -5430,10 +5457,17 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
choices = this.cellProperties.source;
} else {
- var queryRegex = new RegExp(query, this.cellProperties.filteringCaseSensitive === true ? '' : 'i');
+ var filteringCaseSensitive = this.cellProperties.filteringCaseSensitive === true;
+ var lowerCaseQuery = query.toLowerCase();
choices = this.cellProperties.source.filter(function(choice){
- return queryRegex.test(choice);
+
+ if (filteringCaseSensitive) {
+ return choice.indexOf(query) != -1;
+ } else {
+ return choice.toLowerCase().indexOf(lowerCaseQuery) != -1;
+ }
+
});
}
@@ -5492,7 +5526,7 @@ Handsontable.SelectionPoint.prototype.arr = function (arr) {
rowToHighlight = findItemIndexToHighlight(choices, value);
- if ( typeof rowToHighlight == 'undefined'){
+ if ( typeof rowToHighlight == 'undefined' && this.cellProperties.allowInvalid === false){
rowToHighlight = 0;
}
@@ -6920,26 +6954,26 @@ Handsontable.PluginHookClass = (function () {
}
PluginHookClass.prototype.add = function (key, fn) {
- // provide support for old versions of HOT
- if (key in legacy) {
- key = legacy[key];
- }
-
- if (typeof this.hooks[key] === "undefined") {
- this.hooks[key] = [];
- }
-
+ //if fn is array, run this for all the array items
if (Handsontable.helper.isArray(fn)) {
for (var i = 0, len = fn.length; i < len; i++) {
- this.hooks[key].push(fn[i]);
- }
- } else {
- if (this.hooks[key].indexOf(fn) > -1) {
- throw new Error("Seems that you are trying to set the same plugin hook twice (" + key + ", " + fn + ")"); //error here should help writing bug-free plugins
+ this.add(key, fn[i]);
}
- this.hooks[key].push(fn);
}
+ else {
+ // provide support for old versions of HOT
+ if (key in legacy) {
+ key = legacy[key];
+ }
+
+ if (typeof this.hooks[key] === "undefined") {
+ this.hooks[key] = [];
+ }
+ if (this.hooks[key].indexOf(fn) == -1) {
+ this.hooks[key].push(fn); //only add a hook if it has not already be added (adding the same hook twice is now silently ignored)
+ }
+ }
return this;
};
@@ -8908,7 +8942,12 @@ function Storage(prefix) {
}
});
- instance.addHook("afterCreateRow", function (index, amount) {
+ instance.addHook("afterCreateRow", function (index, amount, createdAutomatically) {
+
+ if (createdAutomatically) {
+ return;
+ }
+
var action = new Handsontable.UndoRedo.CreateRowAction(index, amount);
plugin.done(action);
});
@@ -8921,7 +8960,12 @@ function Storage(prefix) {
plugin.done(action);
});
- instance.addHook("afterCreateCol", function (index, amount) {
+ instance.addHook("afterCreateCol", function (index, amount, createdAutomatically) {
+
+ if (createdAutomatically) {
+ return;
+ }
+
var action = new Handsontable.UndoRedo.CreateColumnAction(index, amount);
plugin.done(action);
});
View
2 handsontable.jquery.json
@@ -1,7 +1,7 @@
{
"name": "handsontable",
"title": "Handsontable",
- "version": "0.10.2",
+ "version": "0.10.3",
"author": {
"name": "Marcin Warpechowski",
"email": "marcin@nextgen.pl",
View
2 package.json
@@ -6,7 +6,7 @@
"url": "https://github.com/warpech/jquery-handsontable/issues"
},
"author": "Marcin Warpechowski <marcin@nextgen.pl>",
- "version": "0.10.2",
+ "version": "0.10.3",
"devDependencies": {
"grunt": "~0.4.1",
"grunt-replace": "~0.4.4",
View
8 src/core.js
@@ -142,14 +142,14 @@ Handsontable.Core = function (rootElement, userSettings) {
rlen = instance.countRows();
if (rlen < priv.settings.minRows) {
for (r = 0; r < priv.settings.minRows - rlen; r++) {
- datamap.createRow();
+ datamap.createRow(instance.countRows(), 1, true);
}
}
//should I add empty rows to meet minSpareRows?
if (emptyRows < priv.settings.minSpareRows) {
for (; emptyRows < priv.settings.minSpareRows && instance.countRows() < priv.settings.maxRows; emptyRows++) {
- datamap.createRow();
+ datamap.createRow(instance.countRows(), 1, true);
}
}
@@ -159,14 +159,14 @@ Handsontable.Core = function (rootElement, userSettings) {
//should I add empty cols to meet minCols?
if (!priv.settings.columns && instance.countCols() < priv.settings.minCols) {
for (; instance.countCols() < priv.settings.minCols; emptyCols++) {
- datamap.createCol();
+ datamap.createCol(instance.countCols(), 1, true);
}
}
//should I add empty cols to meet minSpareCols?
if (!priv.settings.columns && instance.dataType === 'array' && emptyCols < priv.settings.minSpareCols) {
for (; emptyCols < priv.settings.minSpareCols && instance.countCols() < priv.settings.maxCols; emptyCols++) {
- datamap.createCol();
+ datamap.createCol(instance.countCols(), 1, true);
}
}
View
10 src/dataMap.js
@@ -133,7 +133,7 @@
* Creates row at the bottom of the data array
* @param {Number} [index] Optional. Index of the row before which the new row will be inserted
*/
- Handsontable.DataMap.prototype.createRow = function (index, amount) {
+ Handsontable.DataMap.prototype.createRow = function (index, amount, createdAutomatically) {
var row
, colCount = this.instance.countCols()
, numberOfCreatedRows = 0
@@ -176,7 +176,7 @@
}
- this.instance.PluginHooks.run('afterCreateRow', index, numberOfCreatedRows);
+ this.instance.PluginHooks.run('afterCreateRow', index, numberOfCreatedRows, createdAutomatically);
this.instance.forceFullRender = true; //used when data was changed
return numberOfCreatedRows;
@@ -187,7 +187,7 @@
* @param {Number} [index] Optional. Index of the column before which the new column will be inserted
* * @param {Number} [amount] Optional.
*/
- Handsontable.DataMap.prototype.createCol = function (index, amount) {
+ Handsontable.DataMap.prototype.createCol = function (index, amount, createdAutomatically) {
if (this.instance.dataType === 'object' || this.instance.getSettings().columns) {
throw new Error("Cannot create new column. When data source in an object, " +
"you can only have as much columns as defined in first data row, data schema or in the 'columns' setting." +
@@ -230,7 +230,7 @@
currentIndex++;
}
- this.instance.PluginHooks.run('afterCreateCol', index, numberOfCreatedCols);
+ this.instance.PluginHooks.run('afterCreateCol', index, numberOfCreatedCols, createdAutomatically);
this.instance.forceFullRender = true; //used when data was changed
return numberOfCreatedCols;
@@ -405,7 +405,7 @@
}
};
- var copyableLookup = Handsontable.helper.cellMethodLookupFactory('copyable');
+ var copyableLookup = Handsontable.helper.cellMethodLookupFactory('copyable', false);
/**
* Returns single value from the data array (intended for clipboard copy to an external application)
View
24 src/editors/autocompleteEditor.js
@@ -52,10 +52,13 @@
hot.updateSettings({
'colWidths': [this.wtDom.outerWidth(this.TEXTAREA) - 2],
- afterRenderer: function (TD, row, col, prop, value, cellProperties) {
- var match = TD.innerHTML.match(new RegExp(that.query, 'i'));
- if(match){
- TD.innerHTML = value.replace(match[0], '<strong>' + match[0] + '</strong>');
+ afterRenderer: function (TD, row, col, prop, value) {
+ var caseSensitive = this.getCellMeta(row, col).filteringCaseSensitive === true;
+ var indexOfMatch = caseSensitive ? value.indexOf(that.query) : value.toLowerCase().indexOf(that.query.toLowerCase());
+
+ if(indexOfMatch != -1){
+ var match = value.substr(indexOfMatch, that.query.length);
+ TD.innerHTML = value.replace(match, '<strong>' + match + '</strong>');
}
}
});
@@ -122,10 +125,17 @@
choices = this.cellProperties.source;
} else {
- var queryRegex = new RegExp(query, this.cellProperties.filteringCaseSensitive === true ? '' : 'i');
+ var filteringCaseSensitive = this.cellProperties.filteringCaseSensitive === true;
+ var lowerCaseQuery = query.toLowerCase();
choices = this.cellProperties.source.filter(function(choice){
- return queryRegex.test(choice);
+
+ if (filteringCaseSensitive) {
+ return choice.indexOf(query) != -1;
+ } else {
+ return choice.toLowerCase().indexOf(lowerCaseQuery) != -1;
+ }
+
});
}
@@ -184,7 +194,7 @@
rowToHighlight = findItemIndexToHighlight(choices, value);
- if ( typeof rowToHighlight == 'undefined'){
+ if ( typeof rowToHighlight == 'undefined' && this.cellProperties.allowInvalid === false){
rowToHighlight = 0;
}
View
4 src/editors/dateEditor.js
@@ -36,8 +36,8 @@
showButtonPanel: true,
changeMonth: true,
changeYear: true,
- altField: this.$textarea,
- onSelect: function () {
+ onSelect: function (dateStr) {
+ that.setValue(dateStr);
that.finishEditing(false);
}
};
View
28 src/helpers.js
@@ -383,7 +383,26 @@ Handsontable.helper.proxy = function (fun, context) {
};
};
-Handsontable.helper.cellMethodLookupFactory = function (methodName) {
+/**
+ * Factory that produces a function for searching methods (or any properties) which could be defined directly in
+ * table configuration or implicitly, within cell type definition.
+ *
+ * For example: renderer can be defined explicitly using "renderer" property in column configuration or it can be
+ * defined implicitly using "type" property.
+ *
+ * Methods/properties defined explicitly always takes precedence over those defined through "type".
+ *
+ * If the method/property is not found in an object, searching is continued recursively through prototype chain, until
+ * it reaches the Object.prototype.
+ *
+ *
+ * @param methodName {String} name of the method/property to search (i.e. 'renderer', 'validator', 'copyable')
+ * @param allowUndefined {Boolean} [optional] if false, the search is continued if methodName has not been found in cell "type"
+ * @returns {Function}
+ */
+Handsontable.helper.cellMethodLookupFactory = function (methodName, allowUndefined) {
+
+ allowUndefined = typeof allowUndefined == 'undefined' ? true : allowUndefined;
return function cellMethodLookup (row, col) {
@@ -408,7 +427,12 @@ Handsontable.helper.cellMethodLookupFactory = function (methodName) {
type = translateTypeNameToObject(properties.type);
- return type[methodName]; //method defined in type. if does not exist (eg. validator), returns undefined
+ if (type.hasOwnProperty(methodName)) {
+ return type[methodName]; //method defined in type.
+ } else if (allowUndefined) {
+ return; //method does not defined in type (eg. validator), returns undefined
+ }
+
}
return getMethodFromProperties(Handsontable.helper.getPrototypeOf(properties));
View
30 src/pluginHooks.js
@@ -74,26 +74,26 @@ Handsontable.PluginHookClass = (function () {
}
PluginHookClass.prototype.add = function (key, fn) {
- // provide support for old versions of HOT
- if (key in legacy) {
- key = legacy[key];
- }
-
- if (typeof this.hooks[key] === "undefined") {
- this.hooks[key] = [];
- }
-
+ //if fn is array, run this for all the array items
if (Handsontable.helper.isArray(fn)) {
for (var i = 0, len = fn.length; i < len; i++) {
- this.hooks[key].push(fn[i]);
- }
- } else {
- if (this.hooks[key].indexOf(fn) > -1) {
- throw new Error("Seems that you are trying to set the same plugin hook twice (" + key + ", " + fn + ")"); //error here should help writing bug-free plugins
+ this.add(key, fn[i]);
}
- this.hooks[key].push(fn);
}
+ else {
+ // provide support for old versions of HOT
+ if (key in legacy) {
+ key = legacy[key];
+ }
+ if (typeof this.hooks[key] === "undefined") {
+ this.hooks[key] = [];
+ }
+
+ if (this.hooks[key].indexOf(fn) == -1) {
+ this.hooks[key].push(fn); //only add a hook if it has not already be added (adding the same hook twice is now silently ignored)
+ }
+ }
return this;
};
View
14 src/plugins/undoRedo.js
@@ -15,7 +15,12 @@
}
});
- instance.addHook("afterCreateRow", function (index, amount) {
+ instance.addHook("afterCreateRow", function (index, amount, createdAutomatically) {
+
+ if (createdAutomatically) {
+ return;
+ }
+
var action = new Handsontable.UndoRedo.CreateRowAction(index, amount);
plugin.done(action);
});
@@ -28,7 +33,12 @@
plugin.done(action);
});
- instance.addHook("afterCreateCol", function (index, amount) {
+ instance.addHook("afterCreateCol", function (index, amount, createdAutomatically) {
+
+ if (createdAutomatically) {
+ return;
+ }
+
var action = new Handsontable.UndoRedo.CreateColumnAction(index, amount);
plugin.done(action);
});
View
2 test/jasmine/SpecRunner.html
@@ -12,6 +12,8 @@
<link rel="stylesheet" type="text/css" href="../../extensions/jquery.handsontable.removeRow.css">
+ <link rel="stylesheet" type="text/css" href="../../lib/jquery-ui/css/ui-bootstrap/jquery-ui.custom.css">
+
<script src="lib/jasmine/phantom-polyfill.js"></script>
View
148 test/jasmine/spec/editors/autocompleteEditorSpec.js
@@ -1379,6 +1379,154 @@ describe('AutocompleteEditor', function () {
});
});
+ it('text in textarea should not be interpreted as regexp', function () {
+ spyOn(Handsontable.editors.AutocompleteEditor.prototype, 'queryChoices').andCallThrough();
+ var queryChoices = Handsontable.editors.AutocompleteEditor.prototype.queryChoices;
+
+ handsontable({
+ columns: [
+ {
+ editor: 'autocomplete',
+ source: choices
+ }
+ ]
+ });
+
+ selectCell(0, 0);
+ var editorInput = $('.handsontableInput');
+
+ expect(getDataAtCell(0, 0)).toBeNull();
+
+ keyDownUp('enter');
+
+ waitsFor(function () {
+ return queryChoices.calls.length > 0;
+ }, 'Source function call', 1000);
+
+ runs(function () {
+
+ queryChoices.reset();
+
+ editorInput.val("yellow|red");
+ keyDownUp("d".charCodeAt(0));
+
+
+ });
+
+ waitsFor(function () {
+ return queryChoices.calls.length > 0;
+ }, 'Source function call', 1000);
+
+ runs(function () {
+ expect(autocomplete().handsontable('getData').length).toEqual(0);
+ });
+ });
+
+ it('text in textarea should not be interpreted as regexp when highlighting the matching phrase', function () {
+ var choices = ['Male', 'Female'];
+
+ var syncSources = jasmine.createSpy('syncSources');
+
+ syncSources.plan = function (query, process) {
+ process(choices.filter(function(choice){
+ return choice.search(new RegExp(query, 'i')) != -1;
+ }));
+ };
+
+ handsontable({
+ columns: [
+ {
+ editor: 'autocomplete',
+ source: syncSources,
+ filter: false
+ }
+ ]
+ });
+
+ selectCell(0, 0);
+ var editorInput = $('.handsontableInput');
+
+ expect(getDataAtCell(0, 0)).toBeNull();
+
+ keyDownUp('enter');
+
+ waitsFor(function () {
+ return syncSources.calls.length > 0;
+ }, 'Source function call', 1000);
+
+ runs(function () {
+
+ syncSources.reset();
+
+ editorInput.val("M|F");
+ keyDownUp('F'.charCodeAt(0));
+
+
+ });
+
+ waitsFor(function () {
+ return syncSources.calls.length > 0;
+ }, 'Source function call', 1000);
+
+ runs(function () {
+ var autocompleteList = autocomplete().handsontable('getInstance').rootElement;
+ expect(autocompleteList.find('td:eq(0)').html()).toEqual('Male');
+ expect(autocompleteList.find('td:eq(1)').html()).toEqual('Female');
+
+ syncSources.reset();
+ });
+ });
+
+ it("should allow any value if filter === false and allowInvalid === true", function () {
+ spyOn(Handsontable.editors.AutocompleteEditor.prototype, 'queryChoices').andCallThrough();
+ var queryChoices = Handsontable.editors.AutocompleteEditor.prototype.queryChoices;
+
+ handsontable({
+ columns: [
+ {
+ editor: 'autocomplete',
+ source: choices,
+ filter: false,
+ strict: true,
+ allowInvalid: true
+ }
+ ]
+ });
+
+ selectCell(0, 0);
+ var editorInput = $('.handsontableInput');
+
+ expect(getDataAtCell(0, 0)).toBeNull();
+
+ keyDownUp('enter');
+
+ waitsFor(function () {
+ return queryChoices.calls.length > 0;
+ }, 'queryChoices function call', 1000);
+
+ runs(function () {
+
+ queryChoices.reset();
+
+ editorInput.val("foobar");
+ keyDownUp(82); //r
+
+
+ });
+
+ waitsFor(function () {
+ return queryChoices.calls.length > 0;
+ }, 'queryChoices function call', 1000);
+
+ runs(function () {
+
+ keyDownUp(Handsontable.helper.keyCode.ENTER);
+
+ expect(getDataAtCell(0, 0)).toEqual('foobar');
+ });
+
+ });
+
});
it('should restore the old value when hovered over a autocomplete menu item and then clicked outside of the table', function () {
View
29 test/jasmine/spec/editors/dateEditorSpec.js
@@ -131,4 +131,33 @@ describe('DateEditor', function () {
expect($('.htDatepickerHolder').is(':visible')).toBe(false);
});
+
+ it("should enable to input any value in textarea", function () {
+ var hot = handsontable({
+ data: getDates(),
+ columns: [
+ {
+ type: 'date'
+ }
+ ]
+ });
+
+ selectCell(0, 0);
+
+ var editor = hot.getActiveEditor();
+
+ editor.beginEditing();
+
+ expect(editor.isOpened()).toBe(true);
+
+ editor.TEXTAREA.value = 'foo';
+ keyDownUp('o'.charCodeAt(0));
+
+ expect(editor.getValue()).toEqual('foo');
+
+ editor.finishEditing();
+
+ expect(getDataAtCell(0, 0)).toEqual('foo');
+
+ });
});
View
29 test/jasmine/spec/plugins/PluginHooksSpec.js
@@ -50,7 +50,7 @@ describe('PluginHooks', function () {
expect(afterInitHandler.calls.length).toEqual(1);
});
- it('should add a many local hooks at init', function () {
+ it('should add a many local hooks at init (as array)', function () {
var handler1 = jasmine.createSpy('handler1');
var handler2 = jasmine.createSpy('handler2');
var handler3 = jasmine.createSpy('handler3');
@@ -265,28 +265,21 @@ describe('PluginHooks', function () {
expect(hot.runHooksAndReturn('myHook', str)).toEqual('abc');
});
- it('adding same hook twice should raise an error', function () { //error should help writing bug-free plugins
- var errors = 0;
- handsontable();
-
- var fn = function () {
+ it('adding same hook twice should register it only once (without an error)', function () {
+ var i = 0;
+ var fn = function(){
+ i++;
};
- try {
- getInstance().PluginHooks.add('myHook', fn);
- } catch (e) {
- errors++;
- }
+ var hot = handsontable({
+ afterOnCellMouseOver: fn
+ });
- expect(errors).toEqual(0);
+ hot.getInstance().updateSettings({afterOnCellMouseOver: fn});
- try {
- getInstance().PluginHooks.add('myHook', fn);
- } catch (e) {
- errors++;
- }
+ hot.runHooks('afterOnCellMouseOver');
- expect(errors).toEqual(1);
+ expect(i).toEqual(1);
});
describe("controlling handler queue execution", function () {
View
42 test/jasmine/spec/plugins/UndoRedoSpec.js
@@ -60,6 +60,25 @@ describe('UndoRedo', function () {
expect(countRows()).toEqual(2);
});
+ it('should undo creation of multiple rows with minSpareRows', function () {
+ var HOT = handsontable({
+ data: createSpreadsheetData(2, 1),
+ minSpareRows: 2
+ });
+
+ expect(getData()).toEqual([['A0'], ['A1'], [null], [null]]);
+
+ setDataAtCell(2, 0, 'A2');
+ setDataAtCell(4, 0, 'A3');
+
+ expect(getData()).toEqual([['A0'], ['A1'], ['A2'], [null], ['A3'], [null], [null]]);
+
+ HOT.undo();
+ HOT.undo();
+
+ expect(getData()).toEqual([['A0'], ['A1'], [null], [null]]);
+ });
+
it('should undo removal of single row', function () {
var HOT = handsontable({
data: createSpreadsheetData(3, 2)
@@ -242,6 +261,25 @@ describe('UndoRedo', function () {
expect(getColHeader()).toEqual(['Header1', 'Header2']);
});
+ it('should undo creation of multiple columns with minSpareCols', function () {
+ var HOT = handsontable({
+ data: createSpreadsheetData(1, 1),
+ minSpareCols: 2
+ });
+
+ expect(getData()).toEqual([['A0', null, null]]);
+
+ setDataAtCell(0, 1, 'B0');
+ setDataAtCell(0, 3, 'C0');
+
+ expect(getData()).toEqual([['A0', 'B0', null, 'C0', null, null]]);
+
+ HOT.undo();
+ HOT.undo();
+
+ expect(getData()).toEqual([['A0', null, null]]);
+ });
+
it('should undo removal of single column (colHeaders: undefined)', function () {
var HOT = handsontable({
data: createSpreadsheetData(2, 3)
@@ -1128,7 +1166,7 @@ describe('UndoRedo', function () {
});
});
- describe("Object data", function () {
+ xdescribe("Object data", function () {
function createObjectData(){
return [
@@ -1664,7 +1702,7 @@ describe('UndoRedo', function () {
});
});
- describe("plugin features", function () {
+ xdescribe("plugin features", function () {
it("should exposed new methods when plugin is enabled", function () {
var hot = handsontable({
undo: false
View
24 test/jasmine/spec/plugins/copyPasteSpec.js
@@ -210,6 +210,30 @@ describe('CopyPaste plugin', function () {
});
+ it("should set copyable text when selecting a single cell with specified type and hitting ctrl (#1300)", function () {
+ handsontable({
+ data: [['A', 1], ['B', 2]],
+ columns: [
+ {
+ type: 'text'
+ },
+ {
+ type: 'numeric'
+ }
+ ]
+ });
+
+ var copyPasteTextarea = $('textarea.copyPaste');
+
+ expect(copyPasteTextarea.val().length).toEqual(0);
+
+ selectCell(0, 0, 1, 1);
+ keyDownUp(Handsontable.helper.keyCode.CONTROL_LEFT);
+
+ expect(copyPasteTextarea.val()).toEqual('A\t1\nB\t2\n');
+
+ });
+
describe("working with multiple tables", function () {

0 comments on commit 365c93c

Please sign in to comment.