@quantlab/handsontable
Version:
Spreadsheet-like data grid editor that provides copy/paste functionality compatible with Excel/Google Docs
307 lines (242 loc) • 10.3 kB
JavaScript
'use strict';
exports.__esModule = true;
var _unicode = require('./../helpers/unicode');
var _event = require('./../helpers/dom/event');
var _element = require('./../helpers/dom/element');
var _baseEditor = require('./_baseEditor');
var _baseEditor2 = _interopRequireDefault(_baseEditor);
var _eventManager = require('./../eventManager');
var _eventManager2 = _interopRequireDefault(_eventManager);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var MobileTextEditor = _baseEditor2.default.prototype.extend();
var domDimensionsCache = {};
/**
* @private
* @editor MobileTextEditor
* @class MobileTextEditor
*/
var createControls = function createControls() {
this.controls = {};
this.controls.leftButton = document.createElement('DIV');
this.controls.leftButton.className = 'leftButton';
this.controls.rightButton = document.createElement('DIV');
this.controls.rightButton.className = 'rightButton';
this.controls.upButton = document.createElement('DIV');
this.controls.upButton.className = 'upButton';
this.controls.downButton = document.createElement('DIV');
this.controls.downButton.className = 'downButton';
for (var button in this.controls) {
if (Object.prototype.hasOwnProperty.call(this.controls, button)) {
this.positionControls.appendChild(this.controls[button]);
}
}
};
MobileTextEditor.prototype.valueChanged = function () {
return this.initValue != this.getValue();
};
MobileTextEditor.prototype.init = function () {
var that = this;
this.eventManager = new _eventManager2.default(this.instance);
this.createElements();
this.bindEvents();
this.instance.addHook('afterDestroy', function () {
that.destroy();
});
};
MobileTextEditor.prototype.getValue = function () {
return this.TEXTAREA.value;
};
MobileTextEditor.prototype.setValue = function (newValue) {
this.initValue = newValue;
this.TEXTAREA.value = newValue;
};
MobileTextEditor.prototype.createElements = function () {
this.editorContainer = document.createElement('DIV');
this.editorContainer.className = 'htMobileEditorContainer';
this.cellPointer = document.createElement('DIV');
this.cellPointer.className = 'cellPointer';
this.moveHandle = document.createElement('DIV');
this.moveHandle.className = 'moveHandle';
this.inputPane = document.createElement('DIV');
this.inputPane.className = 'inputs';
this.positionControls = document.createElement('DIV');
this.positionControls.className = 'positionControls';
this.TEXTAREA = document.createElement('TEXTAREA');
(0, _element.addClass)(this.TEXTAREA, 'handsontableInput');
this.inputPane.appendChild(this.TEXTAREA);
this.editorContainer.appendChild(this.cellPointer);
this.editorContainer.appendChild(this.moveHandle);
this.editorContainer.appendChild(this.inputPane);
this.editorContainer.appendChild(this.positionControls);
createControls.call(this);
document.body.appendChild(this.editorContainer);
};
MobileTextEditor.prototype.onBeforeKeyDown = function (event) {
var instance = this;
var that = instance.getActiveEditor();
if (event.target !== that.TEXTAREA || (0, _event.isImmediatePropagationStopped)(event)) {
return;
}
switch (event.keyCode) {
case _unicode.KEY_CODES.ENTER:
that.close();
event.preventDefault(); // don't add newline to field
break;
case _unicode.KEY_CODES.BACKSPACE:
(0, _event.stopImmediatePropagation)(event); // backspace, delete, home, end should only work locally when cell is edited (not in table context)
break;
default:
break;
}
};
MobileTextEditor.prototype.open = function () {
this.instance.addHook('beforeKeyDown', this.onBeforeKeyDown);
(0, _element.addClass)(this.editorContainer, 'active');
(0, _element.removeClass)(this.cellPointer, 'hidden');
this.updateEditorPosition();
};
MobileTextEditor.prototype.focus = function () {
this.TEXTAREA.focus();
(0, _element.setCaretPosition)(this.TEXTAREA, this.TEXTAREA.value.length);
};
MobileTextEditor.prototype.close = function () {
this.TEXTAREA.blur();
this.instance.removeHook('beforeKeyDown', this.onBeforeKeyDown);
(0, _element.removeClass)(this.editorContainer, 'active');
};
MobileTextEditor.prototype.scrollToView = function () {
var coords = this.instance.getSelectedRange().highlight;
this.instance.view.scrollViewport(coords);
};
MobileTextEditor.prototype.hideCellPointer = function () {
if (!(0, _element.hasClass)(this.cellPointer, 'hidden')) {
(0, _element.addClass)(this.cellPointer, 'hidden');
}
};
MobileTextEditor.prototype.updateEditorPosition = function (x, y) {
if (x && y) {
x = parseInt(x, 10);
y = parseInt(y, 10);
this.editorContainer.style.top = y + 'px';
this.editorContainer.style.left = x + 'px';
} else {
var selection = this.instance.getSelected(),
selectedCell = this.instance.getCell(selection[0], selection[1]);
// cache sizes
if (!domDimensionsCache.cellPointer) {
domDimensionsCache.cellPointer = {
height: (0, _element.outerHeight)(this.cellPointer),
width: (0, _element.outerWidth)(this.cellPointer)
};
}
if (!domDimensionsCache.editorContainer) {
domDimensionsCache.editorContainer = {
width: (0, _element.outerWidth)(this.editorContainer)
};
}
if (selectedCell !== undefined) {
var scrollLeft = this.instance.view.wt.wtOverlays.leftOverlay.trimmingContainer == window ? 0 : (0, _element.getScrollLeft)(this.instance.view.wt.wtOverlays.leftOverlay.holder);
var scrollTop = this.instance.view.wt.wtOverlays.topOverlay.trimmingContainer == window ? 0 : (0, _element.getScrollTop)(this.instance.view.wt.wtOverlays.topOverlay.holder);
var selectedCellOffset = (0, _element.offset)(selectedCell),
selectedCellWidth = (0, _element.outerWidth)(selectedCell),
currentScrollPosition = {
x: scrollLeft,
y: scrollTop
};
this.editorContainer.style.top = parseInt(selectedCellOffset.top + (0, _element.outerHeight)(selectedCell) - currentScrollPosition.y + domDimensionsCache.cellPointer.height, 10) + 'px';
this.editorContainer.style.left = parseInt(window.innerWidth / 2 - domDimensionsCache.editorContainer.width / 2, 10) + 'px';
if (selectedCellOffset.left + selectedCellWidth / 2 > parseInt(this.editorContainer.style.left, 10) + domDimensionsCache.editorContainer.width) {
this.editorContainer.style.left = window.innerWidth - domDimensionsCache.editorContainer.width + 'px';
} else if (selectedCellOffset.left + selectedCellWidth / 2 < parseInt(this.editorContainer.style.left, 10) + 20) {
this.editorContainer.style.left = 0 + 'px';
}
this.cellPointer.style.left = parseInt(selectedCellOffset.left - domDimensionsCache.cellPointer.width / 2 - (0, _element.offset)(this.editorContainer).left + selectedCellWidth / 2 - currentScrollPosition.x, 10) + 'px';
}
}
};
MobileTextEditor.prototype.updateEditorData = function () {
var selected = this.instance.getSelected(),
selectedValue = this.instance.getDataAtCell(selected[0], selected[1]);
this.row = selected[0];
this.col = selected[1];
this.setValue(selectedValue);
this.updateEditorPosition();
};
MobileTextEditor.prototype.prepareAndSave = function () {
var val;
if (!this.valueChanged()) {
return;
}
if (this.instance.getSettings().trimWhitespace) {
val = [[String.prototype.trim.call(this.getValue())]];
} else {
val = [[this.getValue()]];
}
this.saveValue(val);
};
MobileTextEditor.prototype.bindEvents = function () {
var that = this;
this.eventManager.addEventListener(this.controls.leftButton, 'touchend', function (event) {
that.prepareAndSave();
that.instance.selection.transformStart(0, -1, null, true);
that.updateEditorData();
event.preventDefault();
});
this.eventManager.addEventListener(this.controls.rightButton, 'touchend', function (event) {
that.prepareAndSave();
that.instance.selection.transformStart(0, 1, null, true);
that.updateEditorData();
event.preventDefault();
});
this.eventManager.addEventListener(this.controls.upButton, 'touchend', function (event) {
that.prepareAndSave();
that.instance.selection.transformStart(-1, 0, null, true);
that.updateEditorData();
event.preventDefault();
});
this.eventManager.addEventListener(this.controls.downButton, 'touchend', function (event) {
that.prepareAndSave();
that.instance.selection.transformStart(1, 0, null, true);
that.updateEditorData();
event.preventDefault();
});
this.eventManager.addEventListener(this.moveHandle, 'touchstart', function (event) {
if (event.touches.length == 1) {
var touch = event.touches[0];
var onTouchPosition = {
x: that.editorContainer.offsetLeft,
y: that.editorContainer.offsetTop
};
var onTouchOffset = {
x: touch.pageX - onTouchPosition.x,
y: touch.pageY - onTouchPosition.y
};
that.eventManager.addEventListener(this, 'touchmove', function (event) {
var touch = event.touches[0];
that.updateEditorPosition(touch.pageX - onTouchOffset.x, touch.pageY - onTouchOffset.y);
that.hideCellPointer();
event.preventDefault();
});
}
});
this.eventManager.addEventListener(document.body, 'touchend', function (event) {
if (!(0, _element.isChildOf)(event.target, that.editorContainer) && !(0, _element.isChildOf)(event.target, that.instance.rootElement)) {
that.close();
}
});
this.eventManager.addEventListener(this.instance.view.wt.wtOverlays.leftOverlay.holder, 'scroll', function (event) {
if (that.instance.view.wt.wtOverlays.leftOverlay.trimmingContainer != window) {
that.hideCellPointer();
}
});
this.eventManager.addEventListener(this.instance.view.wt.wtOverlays.topOverlay.holder, 'scroll', function (event) {
if (that.instance.view.wt.wtOverlays.topOverlay.trimmingContainer != window) {
that.hideCellPointer();
}
});
};
MobileTextEditor.prototype.destroy = function () {
this.eventManager.clear();
this.editorContainer.parentNode.removeChild(this.editorContainer);
};
exports.default = MobileTextEditor;