UNPKG

upfront-editable

Version:
181 lines (143 loc) 5.61 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = require('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _rangy = require('rangy'); var _rangy2 = _interopRequireDefault(_rangy); var _parser = require('./parser'); var parser = _interopRequireWildcard(_parser); var _rangeContainer = require('./range-container'); var _rangeContainer2 = _interopRequireDefault(_rangeContainer); var _cursor = require('./cursor'); var _cursor2 = _interopRequireDefault(_cursor); var _selection = require('./selection'); var _selection2 = _interopRequireDefault(_selection); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * The SelectionWatcher module watches for selection changes inside * of editable blocks. * * @module core * @submodule selectionWatcher */ var SelectionWatcher = function () { function SelectionWatcher(dispatcher, win) { (0, _classCallCheck3.default)(this, SelectionWatcher); this.dispatcher = dispatcher; this.win = win || window; this.rangySelection = undefined; this.currentSelection = undefined; this.currentRange = undefined; } /** * Updates the internal selection pointer to the current rangy selection. * Returns true if no exception occured. */ (0, _createClass3.default)(SelectionWatcher, [{ key: 'syncSelection', value: function syncSelection() { // it is possible that rangy has a problem with the nativeSelection try { this.rangySelection = _rangy2.default.getSelection(this.win); } catch (err) { return false; } return true; } /** * Return a RangeContainer if the current selection is within an editable * otherwise return an empty RangeContainer */ }, { key: 'getRangeContainer', value: function getRangeContainer() { var successfulSync = this.syncSelection(); // rangeCount is 0 or 1 in all browsers except firefox // firefox can work with multiple ranges // (on a mac hold down the command key to select multiple ranges) if (this.rangySelection.rangeCount && successfulSync) { var range = this.rangySelection.getRangeAt(0); var hostNode = parser.getHost(range.commonAncestorContainer); if (hostNode) return new _rangeContainer2.default(hostNode, range); } // return an empty range container return new _rangeContainer2.default(); } /** * Gets a fresh RangeContainer with the current selection or cursor. * * @return RangeContainer instance */ }, { key: 'getFreshRange', value: function getFreshRange() { return this.getRangeContainer(); } /** * Gets a fresh RangeContainer with the current selection or cursor. * * @return Either a Cursor or Selection instance or undefined if * there is neither a selection or cursor. */ }, { key: 'getFreshSelection', value: function getFreshSelection() { var range = this.getRangeContainer(); return range.isCursor ? range.getCursor(this.win) : range.getSelection(this.win); } /** * Get the selection set by the last selectionChanged event. * Sometimes the event does not fire fast enough and the seleciton * you get is not the one the user sees. * In those cases use #getFreshSelection() * * @return Either a Cursor or Selection instance or undefined if * there is neither a selection or cursor. */ }, { key: 'getSelection', value: function getSelection() { return this.currentSelection; } }, { key: 'forceCursor', value: function forceCursor() { var range = this.getRangeContainer(); return range.forceCursor(); } }, { key: 'selectionChanged', value: function selectionChanged() { var newRange = this.getRangeContainer(); if (newRange.isDifferentFrom(this.currentRange)) { var lastSelection = this.currentSelection; this.currentRange = newRange; // empty selection or cursor if (lastSelection) { if (lastSelection.isCursor && !this.currentRange.isCursor) { this.dispatcher.notify('cursor', lastSelection.host); } else if (lastSelection.isSelection && !this.currentRange.isSelection) { this.dispatcher.notify('selection', lastSelection.host); } } // set new selection or cursor and fire event if (this.currentRange.isCursor) { this.currentSelection = new _cursor2.default(this.currentRange.host, this.currentRange.range); this.dispatcher.notify('cursor', this.currentSelection.host, this.currentSelection); } else if (this.currentRange.isSelection) { this.currentSelection = new _selection2.default(this.currentRange.host, this.currentRange.range); this.dispatcher.notify('selection', this.currentSelection.host, this.currentSelection); } else { this.currentSelection = undefined; } } } }]); return SelectionWatcher; }(); exports.default = SelectionWatcher;