Files
sdkjs/cell/view/CellEditorView.js
Alexander.Trofimov 67d2469518 [se] Paste
Use function _addChars to paste text in cell editor
2019-01-31 16:45:14 +03:00

2806 lines
80 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* (c) Copyright Ascensio System SIA 2010-2019
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
"use strict";
(/**
* @param {Window} window
* @param {undefined} undefined
*/
function (window, undefined) {
/*
* Import
* -----------------------------------------------------------------------------
*/
var asc = window["Asc"];
var AscBrowser = AscCommon.AscBrowser;
var cElementType = AscCommonExcel.cElementType;
var c_oAscCellEditorSelectState = AscCommonExcel.c_oAscCellEditorSelectState;
var c_oAscCellEditorState = asc.c_oAscCellEditorState;
var Fragment = AscCommonExcel.Fragment;
var asc_getcvt = asc.getCvtRatio;
var asc_round = asc.round;
var asc_search = asc.search;
var asc_lastidx = asc.lastIndexOf;
var asc_HL = AscCommonExcel.HandlersList;
var asc_incDecFonSize = asc.incDecFonSize;
/** @const */
var kBeginOfLine = -1;
/** @const */
var kBeginOfText = -2;
/** @const */
var kEndOfLine = -3;
/** @const */
var kEndOfText = -4;
/** @const */
var kNextChar = -5;
/** @const */
var kNextWord = -6;
/** @const */
var kNextLine = -7;
/** @const */
var kPrevChar = -8;
/** @const */
var kPrevWord = -9;
/** @const */
var kPrevLine = -10;
/** @const */
var kPosition = -11;
/** @const */
var kPositionLength = -12;
/** @const */
var kNewLine = "\n";
/**
* CellEditor widget
* -----------------------------------------------------------------------------
* @constructor
* @param {Element} elem
* @param {Element} input
* @param {Array} fmgrGraphics
* @param {AscCommonExcel.Font} oFont
* @param {HandlersList} handlers
* @param {Number} padding
*/
function CellEditor( elem, input, fmgrGraphics, oFont, handlers, padding ) {
this.element = elem;
this.input = input;
this.handlers = new asc_HL( handlers );
this.options = {};
this.sides = undefined;
//---declaration---
this.canvasOuter = undefined;
this.canvasOuterStyle = undefined;
this.canvas = undefined;
this.canvasOverlay = undefined;
this.cursor = undefined;
this.cursorStyle = undefined;
this.cursorTID = undefined;
this.cursorPos = 0;
this.beginCompositePos = -1;
this.compositeLength = 0;
this.topLineIndex = 0;
this.m_oFont = oFont;
this.fmgrGraphics = fmgrGraphics;
this.drawingCtx = undefined;
this.overlayCtx = undefined;
this.textRender = undefined;
this.textFlags = undefined;
this.kx = 1;
this.ky = 1;
this.skipKeyPress = undefined;
this.undoList = [];
this.redoList = [];
this.undoMode = false;
this.noUpdateMode = false;
this.selectionBegin = -1;
this.selectionEnd = -1;
this.isSelectMode = c_oAscCellEditorSelectState.no;
this.hasCursor = false;
this.hasFocus = false;
this.newTextFormat = null;
this.selectionTimer = undefined;
this.enableKeyEvents = true;
this.isTopLineActive = false;
this.skipTLUpdate = true;
this.loadFonts = false;
this.isOpened = false;
this.callTopLineMouseup = false;
this.lastKeyCode = undefined;
this.m_nEditorState = c_oAscCellEditorState.editEnd; // Состояние редактора
// Функции, которые будем отключать
this.fKeyMouseUp = null;
this.fKeyMouseMove = null;
//-----------------
this.objAutoComplete = {};
this.sAutoComplete = null;
/** @type RegExp */
this.reReplaceNL = /\r?\n|\r/g;
this.rangeChars = ["=", "-", "+", "*", "/", "(", "{", ",", "<", ">", "^", "!", "&", ":", ";", " "];
this.reNotFormula = new XRegExp( "[^\\p{L}\\\\_\\]\\[\\p{N}\\.]", "i" );
this.reFormula = new XRegExp( "^([\\p{L}\\\\_\\]\\[][\\p{L}\\\\_\\]\\[\\p{N}\\.]*)", "i" );
this.defaults = {
padding: padding,
selectColor: new AscCommon.CColor(190, 190, 255, 0.5),
canvasZIndex: 500,
blinkInterval: 500,
cursorShape: "text"
};
this._formula = null;
this._parseResult = null;
// Обработчик кликов
this.clickCounter = new AscFormat.ClickCounter();
this._init();
return this;
}
CellEditor.prototype._init = function () {
var t = this;
var z = t.defaults.canvasZIndex;
this.sAutoComplete = null;
if (null != this.element) {
t.canvasOuter = document.createElement('div');
t.canvasOuter.id = "ce-canvas-outer";
t.canvasOuter.style.position = "absolute";
t.canvasOuter.style.display = "none";
t.canvasOuter.style.zIndex = z;
var innerHTML = '<canvas id="ce-canvas" style="z-index: ' + (z + 1) + '"></canvas>';
innerHTML += '<canvas id="ce-canvas-overlay" style="z-index: ' + (z + 2) + '; cursor: ' + t.defaults.cursorShape +
'"></canvas>';
innerHTML += '<div id="ce-cursor" style="display: none; z-index: ' + (z + 3) + '"></div>';
t.canvasOuter.innerHTML = innerHTML;
this.element.appendChild(t.canvasOuter);
t.canvasOuterStyle = t.canvasOuter.style;
t.canvas = document.getElementById("ce-canvas");
t.canvasOverlay = document.getElementById("ce-canvas-overlay");
t.cursor = document.getElementById("ce-cursor");
t.cursorStyle = t.cursor.style;
}
// create text render
t.drawingCtx = new asc.DrawingContext({
canvas: t.canvas, units: 0/*px*/, fmgrGraphics: this.fmgrGraphics, font: this.m_oFont
});
t.overlayCtx = new asc.DrawingContext({
canvas: t.canvasOverlay, units: 0/*px*/, fmgrGraphics: this.fmgrGraphics, font: this.m_oFont
});
t.textRender = new AscCommonExcel.CellTextRender(t.drawingCtx);
// bind event handlers
if (t.canvasOuter && t.canvasOuter.addEventListener) {
t.canvasOuter.addEventListener("mousedown", function () {
return t._onMouseDown.apply(t, arguments);
}, false);
t.canvasOuter.addEventListener("mouseup", function () {
return t._onMouseUp.apply(t, arguments);
}, false);
t.canvasOuter.addEventListener("mousemove", function () {
return t._onMouseMove.apply(t, arguments);
}, false);
t.canvasOuter.addEventListener("mouseleave", function () {
return t._onMouseLeave.apply(t, arguments);
}, false);
}
// check input, it may have zero len, for mobile version
if (t.input && t.input.addEventListener) {
t.input.addEventListener("focus", function () {
return t.isOpened ? t._topLineGotFocus.apply(t, arguments) : true;
}, false);
t.input.addEventListener("mousedown", function () {
return t.isOpened ? (t.callTopLineMouseup = true) : true;
}, false);
t.input.addEventListener("mouseup", function () {
return t.isOpened ? t._topLineMouseUp.apply(t, arguments) : true;
}, false);
t.input.addEventListener("input", function () {
return t._onInputTextArea.apply(t, arguments);
}, false);
// Не поддерживаем drop на верхнюю строку
t.input.addEventListener("drop", function (e) {
e.preventDefault();
return false;
}, false);
}
this.fKeyMouseUp = function () {
return t._onWindowMouseUp.apply(t, arguments);
};
this.fKeyMouseMove = function () {
return t._onWindowMouseMove.apply(t, arguments);
};
};
CellEditor.prototype.destroy = function () {
};
/**
* @param {Object} options
* fragments - text fragments
* flags - text flags (wrapText, textAlign)
* font
* background
* saveValueCallback
*/
CellEditor.prototype.open = function ( options ) {
var b = this.input.selectionStart;
this.isOpened = true;
if ( window.addEventListener ) {
window.addEventListener( "mouseup", this.fKeyMouseUp, false );
window.addEventListener( "mousemove", this.fKeyMouseMove, false );
}
this._setOptions( options );
this._updateTopLineActive(true === this.input.isFocused);
this._updateFormulaEditMod( /*bIsOpen*/true );
this._draw();
if ( !(options.cursorPos >= 0) ) {
if ( this.isTopLineActive ) {
if ( typeof b !== "undefined" ) {
if ( this.cursorPos !== b ) {
this._moveCursor( kPosition, b );
}
}
else {
this._moveCursor( kEndOfText );
}
}
else if ( options.isClearCell ) {
this._selectChars( kEndOfText );
}
else {
this._moveCursor( kEndOfText );
}
}
/*
* Выставляем фокус при открытии
* При нажатии символа, фокус не ставим
* При F2 выставляем фокус в редакторе
* При dbl клике фокус выставляем в зависимости от наличия текста в ячейке
*/
this.setFocus( this.isTopLineActive ? true : (undefined !== options.focus) ? options.focus : this._haveTextInEdit() ? true : false );
this._updateUndoRedoChanged();
};
CellEditor.prototype.close = function (saveValue, bApplyByArray, callback) {
var opt = this.options;
var t = this;
var localSaveValueCallback = function(isSuccess) {
t.textFlags.bApplyByArray = null;
if(!isSuccess) {
t.handlers.trigger('setStrictClose', true);
if(callback) {
callback(false);
}
return false;
}
t.isOpened = false;
t._formula = null;
t._parseResult = null;
if (!window['IS_NATIVE_EDITOR']) {
if (window.removeEventListener) {
window.removeEventListener("mouseup", t.fKeyMouseUp, false);
window.removeEventListener("mousemove", t.fKeyMouseMove, false);
}
t.input.blur();
t.isTopLineActive = false;
t.input.isFocused = false;
t._hideCursor();
// hide
t._hideCanvas();
}
// delete autoComplete
t.objAutoComplete = {};
// Сброс состояния редактора
t.m_nEditorState = c_oAscCellEditorState.editEnd;
t.handlers.trigger("closed");
if(callback) {
callback(true);
} else {
return true;
}
};
if (saveValue) {
// Пересчет делаем всегда для не пустой ячейки или если были изменения. http://bugzilla.onlyoffice.com/show_bug.cgi?id=34864
if (0 < this.undoList.length || 0 < this._getFragmentsLength(this.options.fragments)) {
var isFormula = this.isFormula();
// Делаем замену текста на автодополнение, если есть select и текст полностью совпал.
if (this.sAutoComplete && !isFormula) {
this.selectionBegin = this.textRender.getBeginOfText();
this.cursorPos = this.selectionEnd = this.textRender.getEndOfText();
this.noUpdateMode = true;
this._addChars(this.sAutoComplete);
this.noUpdateMode = false;
}
this.textFlags.bApplyByArray = bApplyByArray;
return opt.saveValueCallback(opt.fragments, this.textFlags, localSaveValueCallback);
}
}
this.isOpened = false;
this._formula = null;
this._parseResult = null;
if (!window['IS_NATIVE_EDITOR']) {
if (window.removeEventListener) {
window.removeEventListener("mouseup", this.fKeyMouseUp, false);
window.removeEventListener("mousemove", this.fKeyMouseMove, false);
}
this.input.blur();
this._updateTopLineActive(false);
this.input.isFocused = false;
this._hideCursor();
// hide
this._hideCanvas();
}
// delete autoComplete
this.objAutoComplete = {};
// Сброс состояния редактора
this.m_nEditorState = c_oAscCellEditorState.editEnd;
this.handlers.trigger("closed");
return true;
};
CellEditor.prototype.setTextStyle = function (prop, val) {
var t = this, opt = t.options, begin, end, i, first, last;
if (t.selectionBegin !== t.selectionEnd) {
begin = Math.min(t.selectionBegin, t.selectionEnd);
end = Math.max(t.selectionBegin, t.selectionEnd);
// save info to undo/redo
if (end - begin < 2) {
t.undoList.push({fn: t._addChars, args: [t.textRender.getChars(begin, 1), begin]});
} else {
t.undoList.push({fn: t._addFragments, args: [t._getFragments(begin, end - begin), begin]});
}
t._extractFragments(begin, end - begin);
first = t._findFragment(begin);
last = t._findFragment(end - 1);
if (first && last) {
for (i = first.index; i <= last.index; ++i) {
var valTmp = t._setFormatProperty(opt.fragments[i].format, prop, val);
// Только для горячих клавиш
if (null === val) {
val = valTmp;
}
}
// merge fragments with equal formats
t._mergeFragments();
t._update();
// Обновляем выделение
t._cleanSelection();
t._drawSelection();
// save info to undo/redo
t.undoList.push({fn: t._removeChars, args: [begin, end - begin]});
t.redoList = [];
}
} else {
first = t._findFragmentToInsertInto(t.cursorPos);
if (first) {
if (!t.newTextFormat) {
t.newTextFormat = opt.fragments[first.index].format.clone();
}
t._setFormatProperty(t.newTextFormat, prop, val);
t._update();
}
}
};
CellEditor.prototype.empty = function ( options ) {
// Чистка для редактирования только All
if ( Asc.c_oAscCleanOptions.All !== options ) {
return;
}
// Удаляем только selection
this._removeChars();
};
CellEditor.prototype.undo = function () {
this._performAction( this.undoList, this.redoList );
};
CellEditor.prototype.redo = function () {
this._performAction( this.redoList, this.undoList );
};
CellEditor.prototype.getZoom = function () {
return this.drawingCtx.getZoom();
};
CellEditor.prototype.changeZoom = function ( factor ) {
this.drawingCtx.changeZoom( factor );
this.overlayCtx.changeZoom( factor );
};
CellEditor.prototype.canEnterCellRange = function () {
var fR = this._findRangeUnderCursor();
var isRange = (fR.range !== null && !fR.range.isName);
var prevChar = this.textRender.getChars(this.cursorPos - 1, 1);
return isRange || this.rangeChars.indexOf(prevChar) >= 0;
};
CellEditor.prototype.activateCellRange = function () {
var res = this._findRangeUnderCursor();
res.range ? this.handlers.trigger("existedRange", res.range, res.wsName) : this.handlers.trigger("newRange");
};
CellEditor.prototype.enterCellRange = function (rangeStr) {
var res = this._findRangeUnderCursor();
if (res.range) {
this._moveCursor(kPosition, res.index);
this._selectChars(kPosition, res.index + res.length);
}
var lastAction = this.undoList.length > 0 ? this.undoList[this.undoList.length - 1] : null;
while (lastAction && lastAction.isRange) {
this.undoList.pop();
lastAction = this.undoList.length > 0 ? this.undoList[this.undoList.length - 1] : null;
}
var tmp = this.skipTLUpdate;
this.skipTLUpdate = false;
this._addChars(rangeStr, undefined, /*isRange*/true);
this.skipTLUpdate = tmp;
};
CellEditor.prototype.changeCellRange = function (range) {
var t = this;
t._moveCursor(kPosition, range.cursorePos/* -length */);
t._selectChars(kPositionLength, range.formulaRangeLength);
t._addChars(range.getName(), undefined, /*isRange*/true);
t._moveCursor(kEndOfText);
};
CellEditor.prototype.move = function (l, t, r, b) {
this.textFlags.wrapOnlyCE = false;
this.sides = this.options.getSides();
this.left = this.sides.cellX;
this.top = this.sides.cellY;
this.right = this.sides.r[this.sides.ri];
this.bottom = this.sides.b[this.sides.bi];
// ToDo вынести в отдельную функцию
var canExpW = true, canExpH = true, tm, expW, expH, fragments = this._getRenderFragments();
if (0 < fragments.length) {
tm = this.textRender.measureString(fragments, this.textFlags, this._getContentWidth());
expW = tm.width > this._getContentWidth();
expH = tm.height > this._getContentHeight();
while (expW && canExpW || expH && canExpH) {
if (expW) {
canExpW = this._expandWidth();
}
if (expH) {
canExpH = this._expandHeight();
}
if (!canExpW) {
this.textFlags.wrapOnlyCE = true;
tm = this.textRender.measureString(fragments, this.textFlags, this._getContentWidth());
} else {
tm = this.textRender.measure(this._getContentWidth());
}
expW = tm.width > this._getContentWidth();
expH = tm.height > this._getContentHeight();
}
}
if (this.left < l || this.top < t || this.left > r || this.top > b) {
// hide
this._hideCanvas();
} else {
this._adjustCanvas();
this._showCanvas();
this._renderText();
this._drawSelection();
}
};
CellEditor.prototype.setFocus = function (hasFocus) {
this.hasFocus = !!hasFocus;
this.handlers.trigger("gotFocus", this.hasFocus);
};
CellEditor.prototype.restoreFocus = function () {
if (this.isTopLineActive) {
this.input.focus();
}
};
CellEditor.prototype.copySelection = function () {
var t = this;
var res = null;
if ( t.selectionBegin !== t.selectionEnd ) {
var start = t.selectionBegin;
var end = t.selectionEnd;
if ( start > end ) {
var temp = start;
start = end;
end = temp;
}
res = t._getFragments( start, end - start );
}
return res;
};
CellEditor.prototype.cutSelection = function () {
var t = this;
var f = null;
if ( t.selectionBegin !== t.selectionEnd ) {
var start = t.selectionBegin;
var end = t.selectionEnd;
if ( start > end ) {
var temp = start;
start = end;
end = temp;
}
f = t._getFragments( start, end - start );
t._removeChars();
}
return f;
};
CellEditor.prototype.pasteText = function (text) {
text = text.replace(/\t/g, " ");
text = text.replace(/\r/g, "");
text = text.replace(/^\n+|\n+$/g, "");
if (0 === text.length) {
return;
}
this._addChars(text);
};
CellEditor.prototype.paste = function (fragments, cursorPos) {
if (!(fragments.length > 0)) {
return;
}
var length = this._getFragmentsLength(fragments);
if (!this._checkMaxCellLength(length)) {
return;
}
var wrap = fragments.some(function (val) {
return -1 !== val.text.indexOf(kNewLine);
});
this._cleanFragments(fragments);
if (this.selectionBegin !== this.selectionEnd) {
this._removeChars();
}
// save info to undo/redo
this.undoList.push({fn: this._removeChars, args: [this.cursorPos, length]});
this.redoList = [];
this._addFragments(fragments, this.cursorPos);
if (wrap) {
this._wrapText();
this._update();
}
// Сделано только для вставки формулы в ячейку (когда не открыт редактор)
if (undefined !== cursorPos) {
this._moveCursor(kPosition, cursorPos);
}
};
/** @param flag {Boolean} */
CellEditor.prototype.enableKeyEventsHandler = function ( flag ) {
var oldValue = this.enableKeyEvents;
this.enableKeyEvents = !!flag;
if ( this.isOpened && oldValue !== this.enableKeyEvents ) {
this.enableKeyEvents ? this.showCursor() : this._hideCursor();
}
};
CellEditor.prototype.isFormula = function () {
var fragments = this.options.fragments;
return fragments && fragments.length > 0 && fragments[0].text.length > 0 && fragments[0].text.charAt( 0 ) === "=";
};
CellEditor.prototype.formulaIsOperator = function () {
var elem;
return this.isFormula() &&
(null !== (elem = this._parseResult.getElementByPos(this.cursorPos - 1)) && elem.type === cElementType.operator ||
null === elem || this._parseResult.operand_expected);
};
CellEditor.prototype.insertFormula = function ( functionName, isDefName ) {
// Проверим форула ли это
if ( false === this.isFormula() ) {
// Может это просто текста нет
var fragments = this.options.fragments;
if ( 1 === fragments.length && 0 === fragments[0].text.length ) {
// Это просто нет текста, добавим форумулу
functionName = "=" + functionName + "()";
}
else {
// Не смогли добавить...
return false;
}
}
else {
if ( !isDefName )
// Это уже форула, добавляем без '='
{
functionName = functionName + "()";
}
}
var tmp = this.skipTLUpdate;
this.skipTLUpdate = false;
// Вставим форумулу в текущую позицию
this._addChars( functionName );
// Меняем позицию курсора внутрь скобок
if ( !isDefName ) {
this._moveCursor( kPosition, this.cursorPos - 1 );
}
this.skipTLUpdate = tmp;
};
CellEditor.prototype.replaceText = function (pos, len, newText) {
this._moveCursor(kPosition, pos);
this._selectChars(kPosition, pos + len);
this._addChars(newText);
};
CellEditor.prototype.setFontRenderingMode = function () {
if ( this.isOpened ) {
this._draw();
}
};
// Private
CellEditor.prototype._setOptions = function ( options ) {
var opt = this.options = options;
var ctx = this.drawingCtx;
var u = ctx.getUnits();
this.textFlags = opt.flags.clone();
if ( this.textFlags.textAlign === AscCommon.align_Justify || this.isFormula() ) {
this.textFlags.textAlign = AscCommon.align_Left;
}
this.textFlags.shrinkToFit = false;
this._cleanFragments( opt.fragments );
this.textRender.setString( opt.fragments, this.textFlags );
this.newTextFormat = null;
if ( opt.zoom > 0 ) {
this.overlayCtx.setFont( this.drawingCtx.getFont() );
this.changeZoom( opt.zoom );
}
this.kx = asc_getcvt( u, 0/*px*/, ctx.getPPIX() );
this.ky = asc_getcvt( u, 0/*px*/, ctx.getPPIY() );
this.sides = opt.getSides();
this.left = this.sides.cellX;
this.top = this.sides.cellY;
this.right = this.sides.r[this.sides.ri];
this.bottom = this.sides.b[this.sides.bi];
this.cursorPos = opt.cursorPos !== undefined ? opt.cursorPos : 0;
this.topLineIndex = 0;
this.selectionBegin = -1;
this.selectionEnd = -1;
this.isSelectMode = c_oAscCellEditorSelectState.no;
this.hasCursor = false;
this.undoList = [];
this.redoList = [];
this.undoMode = false;
this.skipKeyPress = false;
};
CellEditor.prototype._parseRangeStr = function (s) {
var range = AscCommonExcel.g_oRangeCache.getAscRange(s);
return range ? range.clone() : null;
};
CellEditor.prototype._parseFormulaRanges = function () {
var s = AscCommonExcel.getFragmentsText(
this.options.fragments), t = this, ret = false, range, wsOPEN = this.handlers.trigger(
"getCellFormulaEnterWSOpen"), ws = wsOPEN ? wsOPEN.model : this.handlers.trigger("getActiveWS");
if (Asc.c_oAscNumFormatType.Text === this.options.cellNumFormat || s.length < 1 || s.charAt(0) !== "=") {
return ret;
}
/*function cb(ref){
for(var id in ref){
console.log(ref[id])
if(!ref[id].isRef) continue;
range = t._parseRangeStr(ref[id].ref)
if(range){
ret = true;
range.cursorePos = ref[id].offset;
range.formulaRangeLength = ref[id].length;
t.handlers.trigger("newRange", range);
}
}
}*/
// var __s__ = new Date().getTime();
// var parres = parserTest.parse(s,cb);
// var __e__ = new Date().getTime();
// console.log("e-s "+ (__e__ - __s__));
var bbox = this.options.bbox;
this._parseResult = new AscCommonExcel.ParseResult([], []);
var cellWithFormula = new window['AscCommonExcel'].CCellWithFormula(ws, bbox.r1, bbox.c1);
this._formula = new AscCommonExcel.parserFormula(s.substr(1), cellWithFormula, ws);
this._formula.parse(true, true, this._parseResult);
var r, offset, _e, _s, wsName = null, refStr, isName = false, _sColorPos, localStrObj;
if (this._parseResult.refPos && this._parseResult.refPos.length > 0) {
for (var index = 0; index < this._parseResult.refPos.length; index++) {
wsName = null;
isName = false;
r = this._parseResult.refPos[index];
offset = r.end;
_e = r.end;
_sColorPos = _s = r.start;
switch (r.oper.type) {
case cElementType.cell : {
if (wsOPEN) {
wsName = wsOPEN.model.getName();
}
ret = true;
refStr = r.oper.toLocaleString();
break;
}
case cElementType.cell3D : {
localStrObj = r.oper.toLocaleStringObj();
refStr = localStrObj[1];
ret = true;
wsName = r.oper.getWS().getName();
_s = _e - localStrObj[1].length;
_sColorPos = _e - localStrObj[0].length;
break;
}
case cElementType.cellsRange : {
if (wsOPEN) {
wsName = wsOPEN.model.getName();
}
ret = true;
refStr = r.oper.toLocaleString();
break;
}
case cElementType.cellsRange3D : {
if (!r.oper.isSingleSheet()) {
continue;
}
ret = true;
localStrObj = r.oper.toLocaleStringObj();
refStr = localStrObj[1];
wsName = r.oper.getWS().getName();
_s = _e - localStrObj[1].length;
_sColorPos = _e - localStrObj[0].length;
break;
}
case cElementType.table :
case cElementType.name :
case cElementType.name3D : {
var nameRef = r.oper.toRef(bbox);
if (nameRef instanceof AscCommonExcel.cError) {
continue;
}
switch (nameRef.type) {
case cElementType.cellsRange3D : {
if (!nameRef.isSingleSheet()) {
continue;
}
}
case cElementType.cellsRange :
case cElementType.cell3D : {
ret = true;
localStrObj = r.oper.toLocaleStringObj();
refStr = localStrObj[1];
wsName = nameRef.getWS().getName();
_s = _e - localStrObj[1].length;
break;
}
}
isName = true;
break;
}
default :
continue;
}
if (ret) {
range = t._parseRangeStr(refStr);
if (!range) {
return false;
}
range.cursorePos = offset - (_e - _s) + 1;
range.formulaRangeLength = _e - _s;
range.colorRangePos = offset - (_e - _sColorPos) + 1;
range.colorRangeLength = _e - _sColorPos;
if (isName) {
range.isName = isName;
}
t.handlers.trigger("newRange", range, wsName);
}
}
}
return ret;
};
CellEditor.prototype._findRangeUnderCursor = function () {
var ranges, t = this, s = t.textRender.getChars(0, t.textRender.getCharsCount()), range, arrFR = this.handlers.trigger(
"getFormulaRanges"), a;
for (var id = 0; id < arrFR.length; id++) {
/*так как у нас уже есть некий массив с рейнджами, которые в формуле, то пробегаемся по ним и смотрим,
* находится ли курсор в позиции над этим диапазоном, дабы не парсить всю формулу заново
* необходимо чтобы парсить случаи когда используется что-то такое sumnas2:K2 - sumnas2 невалидная ссылка.
* */
ranges = arrFR[id].ranges;
for (var i = 0, l = ranges.length; i < l; ++i) {
a = ranges[i];
if (t.cursorPos >= a.cursorePos && t.cursorPos <= a.cursorePos + a.formulaRangeLength) {
range = a.clone(true);
range.isName = a.isName;
return {index: a.cursorePos, length: a.formulaRangeLength, range: range};
}
}
}
/*не нашли диапазонов под курсором, парсим формулу*/
var r, offset, _e, _s, wsName = null, ret = false, refStr, isName = false, _sColorPos, wsOPEN = this.handlers.trigger(
"getCellFormulaEnterWSOpen"), ws = wsOPEN ? wsOPEN.model : this.handlers.trigger("getActiveWS"), localStrObj;
var bbox = this.options.bbox;
this._parseResult = new AscCommonExcel.ParseResult([], []);
var cellWithFormula = new window['AscCommonExcel'].CCellWithFormula(ws, bbox.r1, bbox.c1);
this._formula = new AscCommonExcel.parserFormula(s.substr(1), cellWithFormula, ws);
this._formula.parse(true, true, this._parseResult, bbox);
if (this._parseResult.refPos && this._parseResult.refPos.length > 0) {
for (var index = 0; index < this._parseResult.refPos.length; index++) {
wsName = null;
r = this._parseResult.refPos[index];
offset = r.end;
_e = r.end;
_sColorPos = _s = r.start;
switch (r.oper.type) {
case cElementType.cell : {
if (wsOPEN) {
wsName = wsOPEN.model.getName();
}
refStr = r.oper.toLocaleString();
ret = true;
break;
}
case cElementType.cell3D : {
localStrObj = r.oper.toLocaleStringObj();
refStr = localStrObj[1];
ret = true;
wsName = r.oper.getWS().getName();
_s = _e - localStrObj[1].length + 1;
_sColorPos = _e - localStrObj[0].length;
break;
}
case cElementType.cellsRange : {
if (wsOPEN) {
wsName = wsOPEN.model.getName();
}
refStr = r.oper.toLocaleString();
ret = true;
break;
}
case cElementType.cellsRange3D : {
if (!r.oper.isSingleSheet()) {
continue;
}
ret = true;
localStrObj = r.oper.toLocaleStringObj();
refStr = localStrObj[1];
wsName = r.oper.getWS().getName();
_s = _e - localStrObj[1].length + 1;
break;
}
case cElementType.table :
case cElementType.name :
case cElementType.name3D : {
var nameRef = r.oper.toRef(bbox);
if (nameRef instanceof AscCommonExcel.cError) {
continue;
}
switch (nameRef.type) {
case cElementType.cellsRange3D : {
if (!nameRef.isSingleSheet()) {
continue;
}
}
case cElementType.cellsRange :
case cElementType.cell3D : {
ret = true;
localStrObj = nameRef.toLocaleStringObj();
refStr = localStrObj[1];
wsName = nameRef.getWS().getName();
_s = _e - localStrObj[1].length;
break;
}
}
isName = true;
break;
}
default :
continue;
}
if (ret && t.cursorPos > _s && t.cursorPos <= _s + r.oper.value.length) {
range = t._parseRangeStr(refStr);
if (range) {
if (this.handlers.trigger("getActiveWS") && this.handlers.trigger("getActiveWS").getName() != wsName) {
return {index: -1, length: 0, range: null};
}
range.isName = isName;
return {index: _s, length: r.oper.value.length, range: range, wsName: wsName};
}
}
}
}
range ? range.isName = isName : null;
return !range ? {index: -1, length: 0, range: null} :
{index: _s, length: r.oper.value.length, range: range, wsName: wsName};
};
CellEditor.prototype._updateTopLineActive = function (state) {
if (state !== this.isTopLineActive) {
this.isTopLineActive = state;
this.handlers.trigger("updateEditorState", this.isTopLineActive ? c_oAscCellEditorState.editInFormulaBar : c_oAscCellEditorState.editInCell);
}
};
CellEditor.prototype._updateFormulaEditMod = function ( bIsOpen ) {
var isFormula = this.isFormula();
if ( !bIsOpen ) {
this._updateEditorState( isFormula );
}
this.handlers.trigger( "updateFormulaEditMod", isFormula );
this._parseFormulaRanges();
this.handlers.trigger( "updateFormulaEditModEnd" );
};
// Обновляем состояние Undo/Redo
CellEditor.prototype._updateUndoRedoChanged = function () {
this.handlers.trigger( "updateUndoRedoChanged", 0 < this.undoList.length, 0 < this.redoList.length );
};
CellEditor.prototype._haveTextInEdit = function () {
var fragments = this.options.fragments;
return fragments.length > 0 && fragments[0].text.length > 0;
};
CellEditor.prototype._updateEditorState = function ( isFormula ) {
if ( undefined === isFormula ) {
isFormula = this.isFormula();
}
var editorState = isFormula ? c_oAscCellEditorState.editFormula : "" === AscCommonExcel.getFragmentsText( this.options.fragments ) ? c_oAscCellEditorState.editEmptyCell : c_oAscCellEditorState.editText;
if ( this.m_nEditorState !== editorState ) {
this.m_nEditorState = editorState;
this.handlers.trigger( "updateEditorState", this.m_nEditorState );
}
};
CellEditor.prototype._getRenderFragments = function () {
var opt = this.options, fragments = opt.fragments, ranges, i, j, k, l, first, last, val, lengthColors, tmpColors, colorIndex, uniqueColorIndex;
if (this.isFormula()) {
var arrRanges = this.handlers.trigger("getFormulaRanges");
if (0 < arrRanges.length) {
fragments = [];
for (i = 0; i < opt.fragments.length; ++i) {
fragments.push(opt.fragments[i].clone());
}
lengthColors = AscCommonExcel.c_oAscFormulaRangeBorderColor.length;
tmpColors = [];
uniqueColorIndex = 0;
for (i = 0; i < arrRanges.length; ++i) {
ranges = arrRanges[i].ranges;
for (j = 0, l = ranges.length; j < l; ++j) {
val = ranges[j];
colorIndex = asc.getUniqueRangeColor(ranges, j, tmpColors);
if (null == colorIndex) {
colorIndex = uniqueColorIndex++;
}
tmpColors.push(colorIndex);
this._extractFragments(val.colorRangePos, val.colorRangeLength, fragments);
first = this._findFragment(val.cursorePos, fragments);
last = this._findFragment(val.cursorePos + val.formulaRangeLength - 1, fragments);
if (first && last) {
for (k = first.index; k <= last.index; ++k) {
fragments[k].format.setColor(AscCommonExcel.c_oAscFormulaRangeBorderColor[colorIndex % lengthColors]);
}
}
}
}
}
}
return fragments;
};
// Rendering
CellEditor.prototype._draw = function () {
var canExpW = true, canExpH = true, tm, expW, expH, fragments = this._getRenderFragments();
if (0 < fragments.length) {
tm = this.textRender.measureString(fragments, this.textFlags, this._getContentWidth());
expW = tm.width > this._getContentWidth();
expH = tm.height > this._getContentHeight();
while (expW && canExpW || expH && canExpH) {
if (expW) {
canExpW = this._expandWidth();
}
if (expH) {
canExpH = this._expandHeight();
}
if (!canExpW) {
this.textFlags.wrapOnlyCE = true;
tm = this.textRender.measureString(fragments, this.textFlags, this._getContentWidth());
} else {
tm = this.textRender.measure(this._getContentWidth());
}
expW = tm.width > this._getContentWidth();
expH = tm.height > this._getContentHeight();
}
}
this._cleanText();
this._cleanSelection();
this._adjustCanvas();
this._showCanvas();
this._renderText();
this.input.value = AscCommonExcel.getFragmentsText(fragments);
this._updateCursorPosition();
this._showCursor();
};
CellEditor.prototype._update = function () {
this._updateFormulaEditMod(/*bIsOpen*/false);
var tm, canExpW, canExpH, oldLC, doAjust = false, fragments = this._getRenderFragments();
if (0 < fragments.length) {
oldLC = this.textRender.getLinesCount();
tm = this.textRender.measureString(fragments, this.textFlags, this._getContentWidth());
if (this.textRender.getLinesCount() < oldLC) {
this.topLineIndex -= oldLC - this.textRender.getLinesCount();
}
canExpW = !(this.textFlags.wrapText || this.textFlags.wrapOnlyCE);
while (tm.width > this._getContentWidth() && canExpW) {
canExpW = this._expandWidth();
if (!canExpW) {
this.textFlags.wrapOnlyCE = true;
tm = this.textRender.measureString(fragments, this.textFlags, this._getContentWidth());
}
doAjust = true;
}
canExpH = true;
while (tm.height > this._getContentHeight() && canExpH) {
canExpH = this._expandHeight();
doAjust = true;
}
}
if (doAjust) {
this._adjustCanvas();
}
this._renderText(); // вызов нужен для пересчета поля line.startX, которое используется в _updateCursorPosition
this._fireUpdated(); // вызов нужен для обновление текста верхней строки, перед обновлением позиции курсора
this._updateCursorPosition(true);
this._showCursor();
this._updateUndoRedoChanged();
if (window['IS_NATIVE_EDITOR']) {
window['native']['onCellEditorChangeText'](AscCommonExcel.getFragmentsText(this.options.fragments));
}
};
CellEditor.prototype._fireUpdated = function () {
var s = AscCommonExcel.getFragmentsText(this.options.fragments);
var isFormula = -1 === this.beginCompositePos && s.charAt(0) === "=";
var funcPos, funcName, match;
if (!this.isTopLineActive || !this.skipTLUpdate || this.undoMode) {
this.input.value = s;
}
if (isFormula) {
funcPos = asc_lastidx(s, this.reNotFormula, this.cursorPos) + 1;
if (funcPos > 0) {
match = s.slice(funcPos, this.cursorPos).match(this.reFormula);
}
if (match) {
funcName = match[1];
} else {
funcPos = undefined;
funcName = undefined;
}
}
this.handlers.trigger("updated", s, this.cursorPos, isFormula, funcPos, funcName);
};
CellEditor.prototype._expandWidth = function () {
var t = this, l = false, r = false, leftSide = this.sides.l, rightSide = this.sides.r;
function expandLeftSide() {
var i = asc_search( leftSide, function ( v ) {
return v < t.left;
} );
if ( i >= 0 ) {
t.left = leftSide[i];
return true;
}
var val = leftSide[leftSide.length - 1];
if ( Math.abs( t.left - val ) > 0.000001 ) { // left !== leftSide[len-1]
t.left = val;
}
return false;
}
function expandRightSide() {
var i = asc_search( rightSide, function ( v ) {
return v > t.right;
} );
if ( i >= 0 ) {
t.right = rightSide[i];
return true;
}
var val = rightSide[rightSide.length - 1];
if ( Math.abs( t.right - val ) > 0.000001 ) { // right !== rightSide[len-1]
t.right = val;
}
return false;
}
switch ( t.textFlags.textAlign ) {
case AscCommon.align_Right:
r = expandLeftSide();
break;
case AscCommon.align_Center:
l = expandLeftSide();
r = expandRightSide();
break;
case AscCommon.align_Left:
default:
r = expandRightSide();
}
return l || r;
};
CellEditor.prototype._expandHeight = function () {
var t = this, bottomSide = this.sides.b, i = asc_search( bottomSide, function ( v ) {
return v > t.bottom;
} );
if ( i >= 0 ) {
t.bottom = bottomSide[i];
return true;
}
var val = bottomSide[bottomSide.length - 1];
if ( Math.abs( t.bottom - val ) > 0.000001 ) { // bottom !== bottomSide[len-1]
t.bottom = val;
}
return false;
};
CellEditor.prototype._cleanText = function () {
this.drawingCtx.clear();
};
CellEditor.prototype._showCanvas = function () {
this.canvasOuterStyle.display = 'block';
};
CellEditor.prototype._hideCanvas = function () {
this.canvasOuterStyle.display = 'none';
};
CellEditor.prototype._adjustCanvas = function () {
var z = this.defaults.canvasZIndex;
var left = this.left * this.kx;
var top = this.top * this.ky;
var widthStyle = (this.right - this.left) * this.kx - 1; // ToDo разобраться с '-1'
var heightStyle = (this.bottom - this.top) * this.ky - 1;
var isRetina = AscBrowser.isRetina;
var width = widthStyle, height = heightStyle;
if ( isRetina ) {
left = AscCommon.AscBrowser.convertToRetinaValue(left);
top = AscCommon.AscBrowser.convertToRetinaValue(top);
widthStyle = AscCommon.AscBrowser.convertToRetinaValue(widthStyle);
heightStyle = AscCommon.AscBrowser.convertToRetinaValue(heightStyle);
width = AscCommon.AscBrowser.convertToRetinaValue(widthStyle, true);
height = AscCommon.AscBrowser.convertToRetinaValue(heightStyle, true);
}
this.canvasOuterStyle.left = left + 'px';
this.canvasOuterStyle.top = top + 'px';
this.canvasOuterStyle.width = widthStyle + 'px';
this.canvasOuterStyle.height = heightStyle + 'px';
this.canvasOuterStyle.zIndex = this.top < 0 ? -1 : z;
this.canvas.width = this.canvasOverlay.width = width;
this.canvas.height = this.canvasOverlay.height = height;
if ( isRetina ) {
this.canvas.style.width = this.canvasOverlay.style.width = widthStyle + 'px';
this.canvas.style.height = this.canvasOverlay.style.height = heightStyle + 'px';
}
};
CellEditor.prototype._renderText = function (dy) {
var t = this, opt = t.options, ctx = t.drawingCtx;
if (!window['IS_NATIVE_EDITOR']) {
ctx.setFillStyle(opt.background)
.fillRect(0, 0, ctx.getWidth(), ctx.getHeight());
}
if (opt.fragments.length > 0) {
t.textRender.render(undefined, t._getContentLeft(), dy || 0, t._getContentWidth(), opt.font.getColor());
}
};
CellEditor.prototype._cleanSelection = function () {
this.overlayCtx.clear();
};
CellEditor.prototype._drawSelection = function () {
var ctx = this.overlayCtx;
var zoom = this.getZoom();
var begPos, endPos, top, topLine, begInfo, endInfo, line, i, y, h, selection = [];
function drawRect(x, y, w, h) {
if (window['IS_NATIVE_EDITOR']) {
selection.push([x, y, w, h]);
} else {
ctx.fillRect(x, y, w, h);
}
}
begPos = this.selectionBegin;
endPos = this.selectionEnd;
if (!window['IS_NATIVE_EDITOR']) {
ctx.setFillStyle(this.defaults.selectColor).clear();
}
if (begPos !== endPos && !this.isTopLineActive) {
top = this.textRender.calcLineOffset(this.topLineIndex);
begInfo = this.textRender.calcCharOffset(Math.min(begPos, endPos));
line = this.textRender.getLineInfo(begInfo.lineIndex);
topLine = this.textRender.calcLineOffset(begInfo.lineIndex);
endInfo = this.textRender.calcCharOffset(Math.max(begPos, endPos));
h = asc_round(line.th * zoom);
y = topLine - top;
if (begInfo.lineIndex === endInfo.lineIndex) {
drawRect(begInfo.left, y, endInfo.left - begInfo.left, h);
} else {
drawRect(begInfo.left, y, line.tw - begInfo.left + line.startX, h);
for (i = begInfo.lineIndex + 1, y += h; i < endInfo.lineIndex; ++i, y += h) {
line = this.textRender.getLineInfo(i);
h = asc_round(line.th * zoom);
drawRect(line.startX, y, line.tw, h);
}
line = this.textRender.getLineInfo(endInfo.lineIndex);
topLine = this.textRender.calcLineOffset(endInfo.lineIndex);
if (line) {
drawRect(line.startX, topLine - top, endInfo.left - line.startX, asc_round(line.th * zoom));
}
}
}
return selection;
};
// Cursor
CellEditor.prototype.showCursor = function () {
if ( window['IS_NATIVE_EDITOR'] ) {
return;
}
if ( !this.options ) {
this.options = {};
}
this.options.isHideCursor = false;
this._showCursor();
};
CellEditor.prototype._showCursor = function () {
if ( window['IS_NATIVE_EDITOR'] ) {
return;
}
var t = this;
if ( true === t.options.isHideCursor || t.isTopLineActive === true ) {
return;
}
window.clearInterval( t.cursorTID );
t.cursorStyle.display = "block";
t.cursorTID = window.setInterval( function () {
t.cursorStyle.display = ("none" === t.cursorStyle.display) ? "block" : "none";
}, t.defaults.blinkInterval );
};
CellEditor.prototype._hideCursor = function () {
if (window['IS_NATIVE_EDITOR']) {
return;
}
window.clearInterval(this.cursorTID);
this.cursorStyle.display = "none";
};
CellEditor.prototype._updateCursorPosition = function (redrawText) {
// ToDo стоит переправить данную функцию
var h = this.canvas.height;
var y = -this.textRender.calcLineOffset(this.topLineIndex);
var cur = this.textRender.calcCharOffset(this.cursorPos);
var charsCount = this.textRender.getCharsCount();
var curLeft = asc_round(
((AscCommon.align_Right !== this.textFlags.textAlign || this.cursorPos !== charsCount) && cur !== null &&
cur.left !== null ? cur.left : this._getContentPosition()) * this.kx);
var curTop = asc_round(((cur !== null ? cur.top : 0) + y) * this.ky);
var curHeight = asc_round((cur !== null ? cur.height : this._getContentHeight()) * this.ky);
var i, dy, nCount = this.textRender.getLinesCount();
var zoom = this.getZoom();
while (1 < nCount) {
if (curTop + curHeight - 1 > h) {
i = i === undefined ? 0 : i + 1;
if (i === nCount) {
break;
}
dy = asc_round(this.textRender.getLineInfo(i).th * zoom);
y -= dy;
curTop -= asc_round(dy * this.ky);
++this.topLineIndex;
continue;
}
if (curTop < 0) {
--this.topLineIndex;
dy = asc_round(this.textRender.getLineInfo(this.topLineIndex).th * zoom);
y += dy;
curTop += asc_round(dy * this.ky);
continue;
}
break;
}
if (dy !== undefined || redrawText) {
this._renderText(y);
}
if (AscBrowser.isRetina) {
curLeft = AscCommon.AscBrowser.convertToRetinaValue(curLeft);
curTop = AscCommon.AscBrowser.convertToRetinaValue(curTop);
curHeight = AscCommon.AscBrowser.convertToRetinaValue(curHeight);
}
if (window['IS_NATIVE_EDITOR']) {
this.curLeft = curLeft;
this.curTop = curTop;
this.curHeight = curHeight;
} else {
this.cursorStyle.left = curLeft + "px";
this.cursorStyle.top = curTop + "px";
this.cursorStyle.height = curHeight + "px";
}
if (AscCommon.g_inputContext) {
AscCommon.g_inputContext.move(this.left * this.kx + curLeft, this.top * this.ky + curTop);
}
if (cur) {
this.input.scrollTop = this.input.clientHeight * cur.lineIndex;
}
if (this.isTopLineActive && !this.skipTLUpdate) {
this._updateTopLineCurPos();
}
this._updateSelectionInfo();
};
CellEditor.prototype._moveCursor = function (kind, pos) {
this.newTextFormat = null;
var t = this;
this.sAutoComplete = null;
switch (kind) {
case kPrevChar:
t.cursorPos = t.textRender.getPrevChar(t.cursorPos);
break;
case kNextChar:
t.cursorPos = t.textRender.getNextChar(t.cursorPos);
break;
case kPrevWord:
t.cursorPos = t.textRender.getPrevWord(t.cursorPos);
break;
case kNextWord:
t.cursorPos = t.textRender.getNextWord(t.cursorPos);
break;
case kBeginOfLine:
t.cursorPos = t.textRender.getBeginOfLine(t.cursorPos);
break;
case kEndOfLine:
t.cursorPos = t.textRender.getEndOfLine(t.cursorPos);
break;
case kBeginOfText:
t.cursorPos = t.textRender.getBeginOfText(t.cursorPos);
break;
case kEndOfText:
t.cursorPos = t.textRender.getEndOfText(t.cursorPos);
break;
case kPrevLine:
t.cursorPos = t.textRender.getPrevLine(t.cursorPos);
break;
case kNextLine:
t.cursorPos = t.textRender.getNextLine(t.cursorPos);
break;
case kPosition:
t.cursorPos = pos;
break;
case kPositionLength:
t.cursorPos += pos;
break;
default:
return;
}
if (t.selectionBegin !== t.selectionEnd) {
t.selectionBegin = t.selectionEnd = -1;
t._cleanSelection();
}
t._updateCursorPosition();
t._showCursor();
};
CellEditor.prototype._findCursorPosition = function ( coord ) {
var t = this;
var lc = t.textRender.getLinesCount();
var i, h, w, li, chw;
var zoom = this.getZoom();
for ( h = 0, i = Math.max( t.topLineIndex, 0 ); i < lc; ++i ) {
li = t.textRender.getLineInfo( i );
h += asc_round(li.th * zoom);
if ( coord.y <= h ) {
for ( w = li.startX, i = li.beg; i <= li.end; ++i ) {
chw = t.textRender.getCharWidth( i );
if ( coord.x <= w + chw ) {
return coord.x <= w + chw / 2 ? i : i + 1 > li.end ? kEndOfLine : i + 1;
}
w += chw;
}
return i < t.textRender.getCharsCount() ? i - 1 : kEndOfText;
}
}
return kNextLine;
};
CellEditor.prototype._updateTopLineCurPos = function () {
if (this.loadFonts) {
return;
}
var isSelected = this.selectionBegin !== this.selectionEnd;
var b = isSelected ? this.selectionBegin : this.cursorPos;
var e = isSelected ? this.selectionEnd : this.cursorPos;
if (this.input.setSelectionRange) {
this.input.setSelectionRange(Math.min(b, e), Math.max(b, e));
}
};
CellEditor.prototype._topLineGotFocus = function () {
this._updateTopLineActive(true);
this.input.isFocused = true;
this.setFocus(true);
this._hideCursor();
this._updateTopLineCurPos();
this._cleanSelection();
};
CellEditor.prototype._topLineMouseUp = function () {
var t = this;
this.callTopLineMouseup = false;
// при такой комбинации ctrl+a, click, ctrl+a, click не обновляется selectionStart
// поэтому выполняем обработку после обработчика системы
setTimeout(function () {
t._updateCursorByTopLine();
});
};
CellEditor.prototype._updateCursorByTopLine = function () {
var b = this.input.selectionStart;
var e = this.input.selectionEnd;
if (typeof b !== "undefined") {
if (this.cursorPos !== b || this.selectionBegin !== this.selectionEnd) {
this._moveCursor(kPosition, b);
}
if (b !== e) {
this._selectChars(kPosition, e);
}
}
};
CellEditor.prototype._syncEditors = function () {
var t = this;
var s1 = AscCommonExcel.getFragmentsText(t.options.fragments);
var s2 = t.input.value;
var l = Math.min(s1.length, s2.length);
var i1 = 0, i2;
while (i1 < l && s1.charAt(i1) === s2.charAt(i1)) {
++i1;
}
i2 = i1 + 1;
if (i2 >= l) {
i2 = Math.max(s1.length, s2.length);
} else {
while (i2 < l && s1.charAt(i1) !== s2.charAt(i2)) {
++i2;
}
}
t._addChars(s2.slice(i1, i2), i1);
};
// Content
CellEditor.prototype._getContentLeft = function () {
return this.defaults.padding;
};
CellEditor.prototype._getContentWidth = function () {
return this.right - this.left - 2 * this.defaults.padding + 1/*px*/;
};
CellEditor.prototype._getContentHeight = function () {
var t = this;
return t.bottom - t.top;
};
CellEditor.prototype._getContentPosition = function () {
switch (this.textFlags.textAlign) {
case AscCommon.align_Right:
return this.right - this.left - this.defaults.padding - 1;
case AscCommon.align_Center:
return 0.5 * (this.right - this.left);
}
return this.defaults.padding;
};
CellEditor.prototype._wrapText = function () {
this.textFlags.wrapOnlyNL = true;
};
CellEditor.prototype._addChars = function (str, pos, isRange) {
var length = str.length;
if (!this._checkMaxCellLength(length)) {
return false;
}
var opt = this.options, f, l, s;
var noUpdateMode = this.noUpdateMode;
this.noUpdateMode = true;
this.sAutoComplete = null;
if (this.selectionBegin !== this.selectionEnd) {
var copyFragment = this._findFragmentToInsertInto(Math.min(this.selectionBegin, this.selectionEnd) + 1);
if (copyFragment && !this.newTextFormat) {
this.newTextFormat = opt.fragments[copyFragment.index].format.clone();
}
this._removeChars(undefined, undefined, isRange);
}
if (0 !== length) {
if (pos === undefined) {
pos = this.cursorPos;
}
if (!this.undoMode) {
// save info to undo/redo
this.undoList.push({fn: this._removeChars, args: [pos, length], isRange: isRange});
this.redoList = [];
}
if (this.newTextFormat) {
var oNewObj = new Fragment({format: this.newTextFormat, text: str});
this._addFragments([oNewObj], pos);
this.newTextFormat = null;
} else {
f = this._findFragmentToInsertInto(pos);
if (f) {
l = pos - f.begin;
s = opt.fragments[f.index].text;
opt.fragments[f.index].text = s.slice(0, l) + str + s.slice(l);
}
}
this.cursorPos = pos + str.length;
}
this.noUpdateMode = noUpdateMode;
if (!this.noUpdateMode) {
this._update();
}
};
CellEditor.prototype._addNewLine = function () {
this._wrapText();
this._addChars( kNewLine );
};
CellEditor.prototype._removeChars = function (pos, length, isRange) {
var t = this, opt = t.options, b, e, l, first, last;
this.sAutoComplete = null;
if (t.selectionBegin !== t.selectionEnd) {
b = Math.min(t.selectionBegin, t.selectionEnd);
e = Math.max(t.selectionBegin, t.selectionEnd);
t.selectionBegin = t.selectionEnd = -1;
t._cleanSelection();
} else if (length === undefined) {
switch (pos) {
case kPrevChar:
b = t.textRender.getPrevChar(t.cursorPos);
e = t.cursorPos;
break;
case kNextChar:
b = t.cursorPos;
e = t.textRender.getNextChar(t.cursorPos);
break;
case kPrevWord:
b = t.textRender.getPrevWord(t.cursorPos);
e = t.cursorPos;
break;
case kNextWord:
b = t.cursorPos;
e = t.textRender.getNextWord(t.cursorPos);
break;
default:
return;
}
} else {
b = pos;
e = pos + length;
}
if (b === e) {
return;
}
// search for begin and end positions
first = t._findFragment(b);
last = t._findFragment(e - 1);
if (!t.undoMode) {
// save info to undo/redo
if (e - b < 2 && opt.fragments[first.index].text.length > 1) {
t.undoList.push({fn: t._addChars, args: [t.textRender.getChars(b, 1), b], isRange: isRange});
} else {
t.undoList.push({fn: t._addFragments, args: [t._getFragments(b, e - b), b], isRange: isRange});
}
t.redoList = [];
}
if (first && last) {
// remove chars
if (first.index === last.index) {
l = opt.fragments[first.index].text;
opt.fragments[first.index].text = l.slice(0, b - first.begin) + l.slice(e - first.begin);
} else {
opt.fragments[first.index].text = opt.fragments[first.index].text.slice(0, b - first.begin);
opt.fragments[last.index].text = opt.fragments[last.index].text.slice(e - last.begin);
l = last.index - first.index;
if (l > 1) {
opt.fragments.splice(first.index + 1, l - 1);
}
}
// merge fragments with equal formats
t._mergeFragments();
}
t.cursorPos = b;
if (!t.noUpdateMode) {
t._update();
}
};
CellEditor.prototype._selectChars = function (kind, pos) {
var t = this;
var begPos, endPos;
this.sAutoComplete = null;
begPos = t.selectionBegin === t.selectionEnd ? t.cursorPos : t.selectionBegin;
t._moveCursor(kind, pos);
endPos = t.cursorPos;
t.selectionBegin = begPos;
t.selectionEnd = endPos;
t._drawSelection();
if (t.isTopLineActive && !t.skipTLUpdate) {
t._updateTopLineCurPos();
}
};
CellEditor.prototype._changeSelection = function (coord) {
var t = this;
function doChangeSelection(coordTmp) {
// ToDo реализовать для слова.
if (c_oAscCellEditorSelectState.word === t.isSelectMode) {
return;
}
var pos = t._findCursorPosition(coordTmp);
if (pos !== undefined) {
pos >= 0 ? t._selectChars(kPosition, pos) : t._selectChars(pos);
}
}
if (window['IS_NATIVE_EDITOR']) {
doChangeSelection(coord);
} else {
window.clearTimeout(t.selectionTimer);
t.selectionTimer = window.setTimeout(function () {
doChangeSelection(coord);
}, 0);
}
};
CellEditor.prototype._findFragment = function (pos, fragments) {
var i, begin, end;
if (!fragments) {
fragments = this.options.fragments;
}
for (i = 0, begin = 0; i < fragments.length; ++i) {
end = begin + fragments[i].text.length;
if (pos >= begin && pos < end) {
return {index: i, begin: begin, end: end};
}
if (i < fragments.length - 1) {
begin = end;
}
}
return pos === end ? {index: i - 1, begin: begin, end: end} : undefined;
};
CellEditor.prototype._findFragmentToInsertInto = function ( pos ) {
var opt = this.options, i, begin, end;
for ( i = 0, begin = 0; i < opt.fragments.length; ++i ) {
end = begin + opt.fragments[i].text.length;
if ( pos >= begin && pos <= end ) {
return {index: i, begin: begin, end: end};
}
if ( i < opt.fragments.length - 1 ) {
begin = end;
}
}
return undefined;
};
CellEditor.prototype._isWholeFragment = function ( pos, len ) {
var fr = this._findFragment( pos );
return fr && pos === fr.begin && len === fr.end - fr.begin;
};
CellEditor.prototype._splitFragment = function ( f, pos, fragments ) {
var fr;
if ( !fragments ) {
fragments = this.options.fragments;
}
if ( pos > f.begin && pos < f.end ) {
fr = fragments[f.index];
Array.prototype.splice.apply( fragments, [f.index, 1].concat( [new Fragment( {
format: fr.format.clone(), text: fr.text.slice( 0, pos - f.begin )
} ), new Fragment( {format: fr.format.clone(), text: fr.text.slice( pos - f.begin )} )] ) );
}
};
CellEditor.prototype._getFragments = function ( startPos, length ) {
var t = this, opt = t.options, endPos = startPos + length - 1, res = [], fr, i;
var first = t._findFragment( startPos );
var last = t._findFragment( endPos );
if ( !first || !last ) {
throw "Can not extract fragment of text";
}
if ( first.index === last.index ) {
fr = opt.fragments[first.index].clone();
fr.text = fr.text.slice( startPos - first.begin, endPos - first.begin + 1 );
res.push( fr );
}
else {
fr = opt.fragments[first.index].clone();
fr.text = fr.text.slice( startPos - first.begin );
res.push( fr );
for ( i = first.index + 1; i < last.index; ++i ) {
fr = opt.fragments[i].clone();
res.push( fr );
}
fr = opt.fragments[last.index].clone();
fr.text = fr.text.slice( 0, endPos - last.begin + 1 );
res.push( fr );
}
return res;
};
CellEditor.prototype._extractFragments = function (startPos, length, fragments) {
var fr;
fr = this._findFragment(startPos, fragments);
if (!fr) {
throw "Can not extract fragment of text";
}
this._splitFragment(fr, startPos, fragments);
fr = this._findFragment(startPos + length, fragments);
if (!fr) {
throw "Can not extract fragment of text";
}
this._splitFragment(fr, startPos + length, fragments);
};
CellEditor.prototype._addFragments = function ( f, pos ) {
var t = this, opt = t.options, fr;
fr = t._findFragment( pos );
if ( fr && pos < fr.end ) {
t._splitFragment( fr, pos );
fr = t._findFragment( pos );
Array.prototype.splice.apply( opt.fragments, [fr.index, 0].concat( f ) );
}
else {
opt.fragments = opt.fragments.concat( f );
}
// merge fragments with equal formats
t._mergeFragments();
t.cursorPos = pos + t._getFragmentsLength( f );
if ( !t.noUpdateMode ) {
t._update();
}
};
CellEditor.prototype._mergeFragments = function () {
var t = this, opt = t.options, i;
for (i = 0; i < opt.fragments.length;) {
if (opt.fragments[i].text.length < 1 && opt.fragments.length > 1) {
opt.fragments.splice(i, 1);
continue;
}
if (i < opt.fragments.length - 1) {
var fr = opt.fragments[i];
var nextFr = opt.fragments[i + 1];
if (fr.format.isEqual(nextFr.format)) {
opt.fragments.splice(i, 2, new Fragment({format: fr.format, text: fr.text + nextFr.text}));
continue;
}
}
++i;
}
};
CellEditor.prototype._cleanFragments = function (fr) {
var t = this, i, s, f, wrap = t.textFlags.wrapText || t.textFlags.wrapOnlyNL;
for (i = 0; i < fr.length; ++i) {
s = fr[i].text;
if (!wrap && -1 !== s.indexOf(kNewLine)) {
this._wrapText();
}
fr[i].text = s;
f = fr[i].format;
if (f.getName() === "") {
f.setName(t.options.font.getName());
}
if (f.getSize() === 0) {
f.setSize(t.options.font.getSize());
}
}
};
CellEditor.prototype._getFragmentsLength = function ( f ) {
return f.length > 0 ? f.reduce( function ( pv, cv ) {
return pv + cv.text.length;
}, 0 ) : 0;
};
CellEditor.prototype._setFormatProperty = function (format, prop, val) {
switch (prop) {
case "fn":
format.setName(val);
format.setScheme(null);
break;
case "fs":
format.setSize(val);
break;
case "b":
var bold = format.getBold();
val = (null === val) ? ((bold) ? !bold : true) : val;
format.setBold(val);
break;
case "i":
var italic = format.getItalic();
val = (null === val) ? ((italic) ? !italic : true) : val;
format.setItalic(val);
break;
case "u":
var underline = format.getUnderline();
val = (null === val) ? ((Asc.EUnderline.underlineNone === underline) ? Asc.EUnderline.underlineSingle :
Asc.EUnderline.underlineNone) : val;
format.setUnderline(val);
break;
case "s":
var strikeout = format.getStrikeout();
val = (null === val) ? ((strikeout) ? !strikeout : true) : val;
format.setStrikeout(val);
break;
case "fa":
format.setVerticalAlign(val);
break;
case "c":
format.setColor(val);
break;
case "changeFontSize":
var newFontSize = asc_incDecFonSize(val, format.getSize());
if (null !== newFontSize) {
format.setSize(newFontSize);
}
break;
}
return val;
};
CellEditor.prototype._performAction = function ( list1, list2 ) {
var t = this, action, str, pos, len;
if ( list1.length < 1 ) {
return;
}
action = list1.pop();
if ( action.fn === t._removeChars ) {
pos = action.args[0];
len = action.args[1];
if ( len < 2 && !t._isWholeFragment( pos, len ) ) {
list2.push( {fn: t._addChars, args: [t.textRender.getChars( pos, len ), pos], isRange: action.isRange} );
}
else {
list2.push( {fn: t._addFragments, args: [t._getFragments( pos, len ), pos], isRange: action.isRange} );
}
}
else if ( action.fn === t._addChars ) {
str = action.args[0];
pos = action.args[1];
list2.push( {fn: t._removeChars, args: [pos, str.length], isRange: action.isRange} );
}
else if ( action.fn === t._addFragments ) {
pos = action.args[1];
len = t._getFragmentsLength( action.args[0] );
list2.push( {fn: t._removeChars, args: [pos, len], isRange: action.isRange} );
}
else {
return;
}
t.undoMode = true;
if ( t.selectionBegin !== t.selectionEnd ) {
t.selectionBegin = t.selectionEnd = -1;
t._cleanSelection();
}
action.fn.apply( t, action.args );
t.undoMode = false;
};
CellEditor.prototype._tryCloseEditor = function (event, bApplyByArray) {
var t = this;
var callback = function(success) {
//для случая, когда пользователь нажимает ctrl+shift+enter переход на новую строку не осуществляется
if(!bApplyByArray && success) {
t.handlers.trigger("applyCloseEvent", event);
}
};
if(!window['AscCommonExcel'].bIsSupportArrayFormula) {
bApplyByArray = false;
}
this.close(true, bApplyByArray, callback);
};
CellEditor.prototype._getAutoComplete = function (str) {
// ToDo можно ускорить делая поиск каждый раз не в большом массиве, а в уменьшенном (по предыдущим символам)
var oLastResult = this.objAutoComplete[str];
if (oLastResult) {
return oLastResult;
}
var arrAutoComplete = this.options.autoComplete;
var arrAutoCompleteLC = this.options.autoCompleteLC;
var i, length, arrResult = [];
for (i = 0, length = arrAutoCompleteLC.length; i < length; ++i) {
if (arrAutoCompleteLC[i].length !== str.length && 0 === arrAutoCompleteLC[i].indexOf(str)) {
arrResult.push(arrAutoComplete[i]);
}
}
return this.objAutoComplete[str] = arrResult;
};
CellEditor.prototype._updateSelectionInfo = function () {
var tmp = this.cursorPos;
tmp = this._findFragmentToInsertInto( tmp );
if ( !tmp ) {
return;
}
tmp = this.newTextFormat || this.options.fragments[tmp.index].format;
var va = tmp.getVerticalAlign();
var fc = tmp.getColor();
var result = new AscCommonExcel.asc_CFont();
result.name = tmp.getName();
result.size = tmp.getSize();
result.bold = tmp.getBold();
result.italic = tmp.getItalic();
// ToDo убрать, когда будет реализовано двойное подчеркивание
result.underline = (Asc.EUnderline.underlineNone !== tmp.getUnderline());
result.strikeout = tmp.getStrikeout();
result.subscript = va === AscCommon.vertalign_SubScript;
result.superscript = va === AscCommon.vertalign_SuperScript;
result.color = (fc ? asc.colorObjToAscColor( fc ) : new Asc.asc_CColor(this.options.font.getColor()));
this.handlers.trigger( "updateEditorSelectionInfo", result );
};
CellEditor.prototype._checkMaxCellLength = function ( length ) {
var newLength = this._getFragmentsLength( this.options.fragments ) + length;
// Ограничение на ввод
if ( newLength > Asc.c_oAscMaxCellOrCommentLength ) {
if ( this.selectionBegin === this.selectionEnd ) {
return false;
}
var b = Math.min( this.selectionBegin, this.selectionEnd );
var e = Math.max( this.selectionBegin, this.selectionEnd );
if ( newLength - this._getFragmentsLength( this._getFragments( b, e - b ) ) > Asc.c_oAscMaxCellOrCommentLength ) {
return false;
}
}
return true;
};
// Event handlers
/**
*
* @param event {KeyboardEvent}
* @param isInput {boolean}
* @returns {boolean}
*/
CellEditor.prototype._onWindowKeyDown = function (event, isInput) {
var t = this, kind = undefined, hieroglyph = false;
var ctrlKey = !AscCommon.getAltGr(event) && (event.metaKey || event.ctrlKey);
if (!t.isOpened || (!isInput && !t.enableKeyEvents)) {
return true;
}
// для исправления Bug 15902 - Alt забирает фокус из приложения
if (event.which === 18) {
t.lastKeyCode = event.which;
}
t.skipKeyPress = true;
t.skipTLUpdate = false;
// определение ввода иероглифов
if (t.isTopLineActive && t._getFragmentsLength(t.options.fragments) !== t.input.value.length) {
hieroglyph = true;
}
switch (event.which) {
case 27: // "esc"
if (t.handlers.trigger("isGlobalLockEditCell")) {
return false;
}
t.close();
event.stopPropagation();
event.preventDefault();
return false;
case 13: // "enter"
if (window['IS_NATIVE_EDITOR']) {
t._addNewLine();
} else {
if (!t.hasFocus) {
t.setFocus(true);
}
if (!(event.altKey && event.shiftKey)) {
if (event.altKey) {
t._addNewLine();
} else {
if (false === t.handlers.trigger("isGlobalLockEditCell")) {
t._tryCloseEditor(event, event.shiftKey&&event.ctrlKey);
}
}
}
}
event.stopPropagation();
event.preventDefault();
return false;
case 9: // tab
if (!t.hasFocus) {
t.setFocus(true);
}
if (hieroglyph) {
t._syncEditors();
}
if (false === t.handlers.trigger("isGlobalLockEditCell")) {
t._tryCloseEditor(event);
}
return false;
case 8: // "backspace"
if (!this.enableKeyEvents) {
break;
}
if (!window['IS_NATIVE_EDITOR']) {
// Отключим стандартную обработку браузера нажатия backspace
event.stopPropagation();
event.preventDefault();
if (hieroglyph) {
t._syncEditors();
}
}
t._removeChars(ctrlKey ? kPrevWord : kPrevChar);
return false;
case 46: // "del"
if (!this.enableKeyEvents || event.shiftKey) {
break;
}
if (!t.hasFocus) {
t.setFocus(true);
}
if (hieroglyph) {
t._syncEditors();
}
event.stopPropagation();
event.preventDefault();
t._removeChars(ctrlKey ? kNextWord : kNextChar);
return true;
case 37: // "left"
if (!this.enableKeyEvents) {
break;
}
event.stopPropagation();
event.preventDefault();
if (!t.hasFocus) {
break;
}
if (hieroglyph) {
t._syncEditors();
}
kind = ctrlKey ? kPrevWord : kPrevChar;
event.shiftKey ? t._selectChars(kind) : t._moveCursor(kind);
return false;
case 39: // "right"
if (!this.enableKeyEvents) {
break;
}
event.stopPropagation();
event.preventDefault();
if (!t.hasFocus) {
break;
}
if (hieroglyph) {
t._syncEditors();
}
kind = ctrlKey ? kNextWord : kNextChar;
event.shiftKey ? t._selectChars(kind) : t._moveCursor(kind);
return false;
case 38: // "up"
if (!this.enableKeyEvents) {
break;
}
event.stopPropagation();
event.preventDefault();
if (!t.hasFocus) {
break;
}
if (hieroglyph) {
t._syncEditors();
}
event.shiftKey ? t._selectChars(kPrevLine) : t._moveCursor(kPrevLine);
return false;
case 40: // "down"
if (!this.enableKeyEvents) {
break;
}
event.stopPropagation();
event.preventDefault();
if (!t.hasFocus) {
break;
}
if (hieroglyph) {
t._syncEditors();
}
event.shiftKey ? t._selectChars(kNextLine) : t._moveCursor(kNextLine);
return false;
case 35: // "end"
if (!this.enableKeyEvents) {
break;
}
// Отключим стандартную обработку браузера нажатия end
event.stopPropagation();
event.preventDefault();
if (!t.hasFocus) {
break;
}
if (hieroglyph) {
t._syncEditors();
}
kind = ctrlKey ? kEndOfText : kEndOfLine;
event.shiftKey ? t._selectChars(kind) : t._moveCursor(kind);
return false;
case 36: // "home"
if (!this.enableKeyEvents) {
break;
}
// Отключим стандартную обработку браузера нажатия home
event.stopPropagation();
event.preventDefault();
if (!t.hasFocus) {
break;
}
if (hieroglyph) {
t._syncEditors();
}
kind = ctrlKey ? kBeginOfText : kBeginOfLine;
event.shiftKey ? t._selectChars(kind) : t._moveCursor(kind);
return false;
case 53: // 5
if (ctrlKey) {
if (!t.hasFocus) {
t.setFocus(true);
}
// Отключим стандартную обработку браузера нажатия ctrl + 5
event.stopPropagation();
event.preventDefault();
if (hieroglyph) {
t._syncEditors();
}
t.setTextStyle("s", null);
return true;
}
break;
case 65: // A
if (ctrlKey) {
if (!t.hasFocus) {
t.setFocus(true);
}
// Отключим стандартную обработку браузера нажатия ctrl + a
if (!t.isTopLineActive) {
event.stopPropagation();
event.preventDefault();
}
t._moveCursor(kBeginOfText);
t._selectChars(kEndOfText);
return true;
}
break;
case 66: // B
if (ctrlKey) {
if (!t.hasFocus) {
t.setFocus(true);
}
// Отключим стандартную обработку браузера нажатия ctrl + b
event.stopPropagation();
event.preventDefault();
if (hieroglyph) {
t._syncEditors();
}
t.setTextStyle("b", null);
return true;
}
break;
case 73: // I
if (ctrlKey) {
if (!t.hasFocus) {
t.setFocus(true);
}
// Отключим стандартную обработку браузера нажатия ctrl + i
event.stopPropagation();
event.preventDefault();
if (hieroglyph) {
t._syncEditors();
}
t.setTextStyle("i", null);
return true;
}
break;
/*case 83: // S
if (ctrlKey) {
if (!t.hasFocus) {t.setFocus(true);}
if (hieroglyph) {t._syncEditors();}
if (false === t.handlers.trigger("isGlobalLockEditCell"))
t._tryCloseEditor(event);
return false;
}
break;*/
case 85: // U
if (ctrlKey) {
if (!t.hasFocus) {
t.setFocus(true);
}
// Отключим стандартную обработку браузера нажатия ctrl + u
event.stopPropagation();
event.preventDefault();
if (hieroglyph) {
t._syncEditors();
}
t.setTextStyle("u", null);
return true;
}
break;
case 144://Num Lock
case 145://Scroll Lock
if (AscBrowser.isOpera) {
event.stopPropagation();
event.preventDefault();
}
return false;
case 80: // print Ctrl + p
if (ctrlKey) {
event.stopPropagation();
event.preventDefault();
return false;
}
break;
case 89: // ctrl + y
case 90: // ctrl + z
if (ctrlKey) {
event.stopPropagation();
event.preventDefault();
if (!t.hasFocus) {
t.setFocus(true);
}
event.which === 90 ? t.undo() : t.redo();
return false;
}
break;
case 113: // F2
if (AscBrowser.isOpera) {
event.stopPropagation();
event.preventDefault();
}
return false;
case 115: // F4
var res = this._findRangeUnderCursor();
if (res.range) {
res.range.switchReference();
this.enterCellRange(res.range.getName());
}
event.stopPropagation();
event.preventDefault();
return false;
}
t.skipKeyPress = false;
t.skipTLUpdate = true;
return true;
};
/** @param event {KeyboardEvent} */
CellEditor.prototype._onWindowKeyPress = function (event) {
var t = this;
if (!window['IS_NATIVE_EDITOR']) {
if (!t.isOpened || !t.enableKeyEvents) {
return true;
}
if (t.skipKeyPress || event.which < 32) {
t.skipKeyPress = true;
return true;
}
// Проверим, есть ли глобальный lock
//if (t.handlers.trigger("isGlobalLockEditCell"))
// return true;
if (!t.hasFocus) {
t.setFocus(true);
}
// определение ввода иероглифов
if (t.isTopLineActive && t._getFragmentsLength(t.options.fragments) !== t.input.value.length) {
t._syncEditors();
}
//t.setFocus(true);
}
var tmpCursorPos;
var newChar = String.fromCharCode(event.which);
t._addChars(newChar);
// При первом быстром вводе стоит добавить в конце проценты (для процентного формата и только для числа)
if (t.options.isAddPersentFormat && AscCommon.isNumber(newChar)) {
t.options.isAddPersentFormat = false;
tmpCursorPos = t.cursorPos;
t.undoMode = true;
t._addChars("%");
t.cursorPos = tmpCursorPos;
t.undoMode = false;
t._updateCursorPosition();
}
if (t.textRender.getEndOfText() === t.cursorPos && !t.isFormula()) {
var s = AscCommonExcel.getFragmentsText(t.options.fragments);
if (!AscCommon.isNumber(s)) {
var arrAutoComplete = t._getAutoComplete(s.toLowerCase());
var lengthInput = s.length;
if (1 === arrAutoComplete.length) {
var newValue = arrAutoComplete[0];
tmpCursorPos = t.cursorPos;
t._addChars(newValue.substring(lengthInput));
t.selectionBegin = tmpCursorPos;
t._selectChars(kEndOfText);
this.sAutoComplete = newValue;
}
}
}
return t.isTopLineActive; // prevent event bubbling
};
/** @param event {KeyboardEvent} */
CellEditor.prototype._onWindowKeyUp = function ( event ) {
var t = this;
// для исправления Bug 15902 - Alt забирает фокус из приложения
if ( t.lastKeyCode === 18 && event.which === 18 ) {
return false;
}
};
/** @param event {MouseEvent} */
CellEditor.prototype._onWindowMouseUp = function ( event ) {
AscCommon.global_mouseEvent.UnLockMouse();
this.isSelectMode = c_oAscCellEditorSelectState.no;
if ( this.callTopLineMouseup ) {
this._topLineMouseUp();
}
return true;
};
/** @param event {MouseEvent} */
CellEditor.prototype._onWindowMouseMove = function (event) {
if (c_oAscCellEditorSelectState.no !== this.isSelectMode && !this.hasCursor) {
this._changeSelection(this._getCoordinates(event));
}
return true;
};
/** @param event {MouseEvent} */
CellEditor.prototype._onMouseDown = function (event) {
if (AscCommon.g_inputContext && AscCommon.g_inputContext.externalChangeFocus())
return;
AscCommon.global_mouseEvent.LockMouse();
var pos;
var coord = this._getCoordinates(event);
if (!window['IS_NATIVE_EDITOR']) {
this.clickCounter.mouseDownEvent(coord.x, coord.y, event.button);
}
this.setFocus(true);
this.handlers.trigger('setStrictClose', true);
this._updateTopLineActive(false);
this.input.isFocused = false;
if (0 === event.button) {
if (1 === this.clickCounter.getClickCount() % 2) {
this.isSelectMode = c_oAscCellEditorSelectState.char;
if (!event.shiftKey) {
this._showCursor();
pos = this._findCursorPosition(coord);
if (pos !== undefined) {
pos >= 0 ? this._moveCursor(kPosition, pos) : this._moveCursor(pos);
}
} else {
this._changeSelection(coord);
}
} else {
// Dbl click
this.isSelectMode = c_oAscCellEditorSelectState.word;
// Окончание слова
var endWord = this.textRender.getNextWord(this.cursorPos);
// Начало слова (ищем по окончанию, т.к. могли попасть в пробел)
var startWord = this.textRender.getPrevWord(endWord);
this._moveCursor(kPosition, startWord);
this._selectChars(kPosition, endWord);
}
} else if (2 === event.button) {
this.handlers.trigger('onContextMenu', event);
}
return true;
};
/** @param event {MouseEvent} */
CellEditor.prototype._onMouseUp = function (event) {
AscCommon.global_mouseEvent.UnLockMouse();
if (2 === event.button) {
return true;
}
this.isSelectMode = c_oAscCellEditorSelectState.no;
return true;
};
/** @param event {MouseEvent} */
CellEditor.prototype._onMouseMove = function (event) {
var coord = this._getCoordinates(event);
this.clickCounter.mouseMoveEvent(coord.x, coord.y);
this.hasCursor = true;
if (c_oAscCellEditorSelectState.no !== this.isSelectMode) {
this._changeSelection(coord);
}
return true;
};
/** @param event {MouseEvent} */
CellEditor.prototype._onMouseLeave = function ( event ) {
this.hasCursor = false;
return true;
};
/** @param event {jQuery.Event} */
CellEditor.prototype._onInputTextArea = function (event) {
var t = this;
if (!this.handlers.trigger("canEdit") || this.loadFonts) {
return true;
}
this.loadFonts = true;
AscFonts.FontPickerByCharacter.checkText(this.input.value, this, function () {
t.loadFonts = false;
t.skipTLUpdate = true;
t.replaceText(0, t.textRender.getEndOfText(), t.input.value);
t._updateCursorByTopLine();
});
return true;
};
/** @param event {MouseEvent} */
CellEditor.prototype._getCoordinates = function (event) {
if (window['IS_NATIVE_EDITOR']) {
return {x: event.pageX, y: event.pageY};
}
var offs = this.canvasOverlay.getBoundingClientRect();
var x = (((event.pageX * AscBrowser.zoom) >> 0) - offs.left) / this.kx;
var y = (((event.pageY * AscBrowser.zoom) >> 0) - offs.top) / this.ky;
if (AscBrowser.isRetina) {
x *= AscCommon.AscBrowser.retinaPixelRatio;
y *= AscCommon.AscBrowser.retinaPixelRatio;
}
return {x: x, y: y};
};
CellEditor.prototype.Begin_CompositeInput = function () {
if (this.selectionBegin === this.selectionEnd) {
this.beginCompositePos = this.cursorPos;
this.compositeLength = 0;
} else {
this.beginCompositePos = Math.min(this.selectionBegin, this.selectionEnd);
this.compositeLength = Math.max(this.selectionBegin, this.selectionEnd) - this.beginCompositePos;
}
this.setTextStyle('u', Asc.EUnderline.underlineSingle);
};
CellEditor.prototype.Replace_CompositeText = function (arrCharCodes) {
if (!this.isOpened) {
return;
}
var code, codePt, newText = '';
for (var i = 0; i < arrCharCodes.length; ++i) {
code = arrCharCodes[i];
if (code < 0x10000) {
newText += String.fromCharCode(code);
} else {
codePt = code - 0x10000;
newText += String.fromCharCode(0xD800 + (codePt >> 10), 0xDC00 + (codePt & 0x3FF));
}
}
this.replaceText(this.beginCompositePos, this.compositeLength, newText);
this.compositeLength = newText.length;
var tmpBegin = this.selectionBegin, tmpEnd = this.selectionEnd;
this.selectionBegin = this.beginCompositePos;
this.selectionEnd = this.beginCompositePos + this.compositeLength;
this.setTextStyle('u', Asc.EUnderline.underlineSingle);
this.selectionBegin = tmpBegin;
this.selectionEnd = tmpEnd;
// Обновляем выделение
this._cleanSelection();
this._drawSelection();
};
CellEditor.prototype.End_CompositeInput = function () {
var tmpBegin = this.selectionBegin, tmpEnd = this.selectionEnd;
this.selectionBegin = this.beginCompositePos;
this.selectionEnd = this.beginCompositePos + this.compositeLength;
this.setTextStyle('u', Asc.EUnderline.underlineNone);
this.beginCompositePos = -1;
this.compositeLength = 0;
this.selectionBegin = tmpBegin;
this.selectionEnd = tmpEnd;
// Обновляем выделение
this._cleanSelection();
this._drawSelection();
};
CellEditor.prototype.Set_CursorPosInCompositeText = function (nPos) {
if (-1 !== this.beginCompositePos) {
nPos = Math.min(nPos, this.compositeLength);
this._moveCursor(kPosition, this.beginCompositePos + nPos);
}
};
CellEditor.prototype.Get_CursorPosInCompositeText = function () {
return this.cursorPos - this.beginCompositePos;
};
CellEditor.prototype.Get_MaxCursorPosInCompositeText = function () {
return this.compositeLength;
};
//------------------------------------------------------------export---------------------------------------------------
window['AscCommonExcel'] = window['AscCommonExcel'] || {};
window["AscCommonExcel"].CellEditor = CellEditor;
})(window);