UNPKG

upfront-editable

Version:
266 lines (212 loc) 8.63 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 _jquery = require('jquery'); var _jquery2 = _interopRequireDefault(_jquery); var _nodeType = require('./node-type'); var nodeType = _interopRequireWildcard(_nodeType); var _content = require('./content'); var content = _interopRequireWildcard(_content); var _highlightText = require('./highlight-text'); var _highlightText2 = _interopRequireDefault(_highlightText); var _spellcheckService = require('./plugins/highlighting/spellcheck-service'); var _spellcheckService2 = _interopRequireDefault(_spellcheckService); var _whitespaceHighlighting = require('./plugins/highlighting/whitespace-highlighting'); var _whitespaceHighlighting2 = _interopRequireDefault(_whitespaceHighlighting); var _textHighlighting = require('./plugins/highlighting/text-highlighting'); var _textHighlighting2 = _interopRequireDefault(_textHighlighting); var _matchCollection = require('./plugins/highlighting/match-collection'); var _matchCollection2 = _interopRequireDefault(_matchCollection); var _highlightSupport = require('./highlight-support'); var _highlightSupport2 = _interopRequireDefault(_highlightSupport); 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 }; } var Highlighting = function () { function Highlighting(editable, configuration, spellcheckConfig) { (0, _classCallCheck3.default)(this, Highlighting); this.editable = editable; this.win = editable.win; this.focusedEditableHost = undefined; this.currentlyCheckedEditableHost = undefined; this.timeout = {}; var defaultConfig = { checkOnInit: false, checkOnFocus: false, checkOnChange: true, // unbounce rate in ms before calling the spellcheck service after changes throttle: 1000, // remove highlights after a change if the cursor is inside a highlight removeOnCorrection: true, spellcheck: { marker: '<span class="highlight-spellcheck"></span>', throttle: 1000, spellcheckService: function spellcheckService() {} }, whitespace: { marker: '<span class="highlight-whitespace"></span>' } }; this.config = _jquery2.default.extend(true, defaultConfig, configuration); var spellcheckService = this.config.spellcheck.spellcheckService; var spellcheckMarker = this.config.spellcheck.marker; var whitespaceMarker = this.config.whitespace.marker; var spellcheckMarkerNode = _highlightSupport2.default.createMarkerNode(spellcheckMarker, 'spellcheck', this.win); var whitespaceMarkerNode = _highlightSupport2.default.createMarkerNode(whitespaceMarker, 'spellcheck', this.win); this.spellcheckService = new _spellcheckService2.default(spellcheckService); this.spellcheck = new _textHighlighting2.default(spellcheckMarkerNode); this.whitespace = new _whitespaceHighlighting2.default(whitespaceMarkerNode); this.setupListeners(); } // Events // ------ (0, _createClass3.default)(Highlighting, [{ key: 'setupListeners', value: function setupListeners() { if (this.config.checkOnFocus) { this.editable.on('focus', _jquery2.default.proxy(this, 'onFocus')); this.editable.on('blur', _jquery2.default.proxy(this, 'onBlur')); } if (this.config.checkOnChange || this.config.removeOnCorrection) { this.editable.on('change', _jquery2.default.proxy(this, 'onChange')); } if (this.config.checkOnInit) { this.editable.on('init', _jquery2.default.proxy(this, 'onInit')); } } }, { key: 'onInit', value: function onInit(editableHost) { this.highlight(editableHost); } }, { key: 'onFocus', value: function onFocus(editableHost) { if (this.focusedEditableHost !== editableHost) { this.focusedEditableHost = editableHost; this.editableHasChanged(editableHost); } } }, { key: 'onBlur', value: function onBlur(editableHost) { if (this.focusedEditableHost === editableHost) { this.focusedEditableHost = undefined; } } }, { key: 'onChange', value: function onChange(editableHost) { if (this.config.checkOnChange) { this.editableHasChanged(editableHost, this.config.throttle); } if (this.config.removeOnCorrection) { this.removeHighlightsAtCursor(editableHost); } } // Manage Highlights // ----------------- }, { key: 'editableHasChanged', value: function editableHasChanged(editableHost, throttle) { var _this = this; if (this.timeout.id && this.timeout.editableHost === editableHost) { clearTimeout(this.timeout.id); } var timeoutId = setTimeout(function () { _this.highlight(editableHost); _this.timeout = {}; }, throttle || 0); this.timeout = { id: timeoutId, editableHost: editableHost }; } }, { key: 'highlight', value: function highlight(editableHost) { var _this2 = this; var text = _highlightText2.default.extractText(editableHost); // getSpellcheck this.spellcheckService.check(text, function (err, misspelledWords) { if (err) { return; } // refresh the text text = _highlightText2.default.extractText(editableHost); var matchCollection = new _matchCollection2.default(); var matches = _this2.spellcheck.findMatches(text, misspelledWords); matchCollection.addMatches('spellcheck', matches); matches = _this2.whitespace.findMatches(text); matchCollection.addMatches('whitespace', matches); _this2.safeHighlightMatches(editableHost, matchCollection.matches); }); } // Calls highlightMatches internally but ensures // that the selection stays the same }, { key: 'safeHighlightMatches', value: function safeHighlightMatches(editableHost, matches) { var _this3 = this; var selection = this.editable.getSelection(editableHost); if (selection) { selection.retainVisibleSelection(function () { _this3.highlightMatches(editableHost, matches); }); } else { this.highlightMatches(editableHost, matches); } } }, { key: 'highlightMatches', value: function highlightMatches(editableHost, matches) { // Remove old highlights this.removeHighlights(editableHost); // Create new highlights if (matches && matches.length > 0) { // const span = this.createMarkerNode() _highlightText2.default.highlightMatches(editableHost, matches); } } }, { key: 'removeHighlights', value: function removeHighlights(editableHost) { (0, _jquery2.default)(editableHost).find('[data-highlight="spellcheck"]').each(function (index, elem) { content.unwrap(elem); }); } }, { key: 'removeHighlightsAtCursor', value: function removeHighlightsAtCursor(editableHost) { var selection = this.editable.getSelection(editableHost); if (selection && selection.isCursor) { var elementAtCursor = selection.range.startContainer; if (elementAtCursor.nodeType === nodeType.textNode) { elementAtCursor = elementAtCursor.parentNode; } var wordId = void 0; do { if (elementAtCursor === editableHost) return; var highlightType = elementAtCursor.getAttribute('data-highlight'); if (highlightType === 'spellcheck') { wordId = elementAtCursor.getAttribute('data-word-id'); break; } } while (elementAtCursor = elementAtCursor.parentNode); if (wordId) { selection.retainVisibleSelection(function () { (0, _jquery2.default)(editableHost).find('[data-word-id=' + wordId + ']').each(function (index, elem) { content.unwrap(elem); }); }); } } } }]); return Highlighting; }(); exports.default = Highlighting;