UNPKG

vmes-flowable

Version:

ceshibao

151 lines (122 loc) 3.2 kB
'use strict'; /** * Calculate the selection update for the given * current and new input values. * * @param {Object} currentSelection as {start, end} * @param {String} currentValue * @param {String} newValue * * @return {Object} newSelection as {start, end} */ function calculateUpdate(currentSelection, currentValue, newValue) { var currentCursor = currentSelection.start, newCursor = currentCursor, diff = newValue.length - currentValue.length, idx; var lengthDelta = newValue.length - currentValue.length; var currentTail = currentValue.substring(currentCursor); // check if we can remove common ending from the equation // to be able to properly detect a selection change for // the following scenarios: // // * (AAATTT|TF) => (AAAT|TF) // * (AAAT|TF) => (AAATTT|TF) // if (newValue.lastIndexOf(currentTail) === newValue.length - currentTail.length) { currentValue = currentValue.substring(0, currentValue.length - currentTail.length); newValue = newValue.substring(0, newValue.length - currentTail.length); } // diff var diff = createDiff(currentValue, newValue); if (diff) { if (diff.type === 'remove') { newCursor = diff.newStart; } else { newCursor = diff.newEnd; } } return range(newCursor); } module.exports = calculateUpdate; function createDiff(currentValue, newValue) { var insert; var l_str, l_char, l_idx = 0, s_str, s_char, s_idx = 0; if (newValue.length > currentValue.length) { l_str = newValue; s_str = currentValue; } else { l_str = currentValue; s_str = newValue; } // assume there will be only one insert / remove and // detect that _first_ edit operation only while (l_idx < l_str.length) { l_char = l_str.charAt(l_idx); s_char = s_str.charAt(s_idx); // chars no not equal if (l_char !== s_char) { if (!insert) { insert = { l_start: l_idx, s_start: s_idx }; } l_idx++; } // chars equal (again?) else { if (insert && !insert.complete) { insert.l_end = l_idx; insert.s_end = s_idx; insert.complete = true; } s_idx++; l_idx++; } } if (insert && !insert.complete) { insert.complete = true; insert.s_end = s_str.length; insert.l_end = l_str.length; } // no diff if (!insert) { return; } if (newValue.length > currentValue.length) { return { newStart: insert.l_start, newEnd: insert.l_end, type: 'add' }; } else { return { newStart: insert.s_start, newEnd: insert.s_end, type: newValue.length < currentValue.length ? 'remove' : 'replace' }; } } /** * Utility method for creating a new selection range {start, end} object. * * @param {Number} start * @param {Number} [end] * * @return {Object} selection range as {start, end} */ function range(start, end) { return { start: start, end: end === undefined ? start : end }; } module.exports.range = range; function splitStr(str, position) { return { before: str.substring(0, position), after: str.substring(position) }; }