UNPKG

upfront-editable

Version:
416 lines (339 loc) 12.1 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = require('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _inherits2 = require('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); require('rangy/lib/rangy-textrange'); var _jquery = require('jquery'); var _jquery2 = _interopRequireDefault(_jquery); var _cursor = require('./cursor'); var _cursor2 = _interopRequireDefault(_cursor); var _content = require('./content'); var content = _interopRequireWildcard(_content); var _parser = require('./parser'); var parser = _interopRequireWildcard(_parser); var _config = require('./config'); var config = _interopRequireWildcard(_config); var _highlightSupport = require('./highlight-support'); var _highlightSupport2 = _interopRequireDefault(_highlightSupport); var _highlightText = require('./highlight-text'); var _highlightText2 = _interopRequireDefault(_highlightText); 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 Selection module provides a cross-browser abstraction layer for range * and selection. * * @module core * @submodule selection */ /** * Class that represents a selection and provides functionality to access or * modify the selection. * * @class Selection * @constructor */ var Selection = function (_Cursor) { (0, _inherits3.default)(Selection, _Cursor); function Selection() { (0, _classCallCheck3.default)(this, Selection); var _this = (0, _possibleConstructorReturn3.default)(this, (Selection.__proto__ || (0, _getPrototypeOf2.default)(Selection)).apply(this, arguments)); delete _this.isCursor; _this.isSelection = true; return _this; } // Get the text inside the selection. (0, _createClass3.default)(Selection, [{ key: 'text', value: function text() { return this.range.toString(); } // Get the html inside the selection. }, { key: 'html', value: function html() { return this.range.toHtml(); } }, { key: 'isAllSelected', value: function isAllSelected() { return parser.isBeginningOfHost(this.host, this.range.startContainer, this.range.startOffset) && parser.isTextEndOfHost(this.host, this.range.endContainer, this.range.endOffset); } }, { key: 'getTextRange', value: function getTextRange() { return this.range.toCharacterRange(this.host); } // Get the ClientRects of this selection. // Use this if you want more precision than getBoundingClientRect can give. }, { key: 'getRects', value: function getRects() { // consider: translate into absolute positions // just like Cursor#getCoordinates() return this.range.nativeRange.getClientRects(); } }, { key: 'link', value: function link(href) { var attrs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var $link = (0, _jquery2.default)(this.createElement(config.linkMarkup.name, config.linkMarkup.attribs)); if (href) attrs.href = href; $link.attr(attrs); this.forceWrap($link[0]); } }, { key: 'unlink', value: function unlink() { this.removeFormatting(config.linkMarkup.name); } }, { key: 'toggleLink', value: function toggleLink(href, attrs) { var links = this.getTagsByName(config.linkMarkup.name); if (links.length >= 1) { var firstLink = links[0]; if (this.isExactSelection(firstLink, 'visible')) { this.unlink(); } else { this.expandTo(firstLink); } } else { this.link(href, attrs); } } // Manually add a highlight // Note: the current code does not work with newlines (LP) }, { key: 'highlight', value: function highlight(_ref) { var highlightId = _ref.highlightId; var textBefore = this.textBefore(); var currentTextContent = this.text(); var marker = '<span class="highlight-comment"></span>'; var markerNode = _highlightSupport2.default.createMarkerNode(marker, this.win); markerNode.setAttribute('data-match', currentTextContent); var match = { startIndex: textBefore.length, endIndex: textBefore.length + currentTextContent.length, match: currentTextContent, marker: markerNode // Note: highlighting won't retain the selection };_highlightText2.default.highlightMatches(this.host, [match]); } // toggle('<em>') }, { key: 'toggle', value: function toggle(elem) { elem = this.adoptElement(elem); this.range = content.toggleTag(this.host, this.range, elem); this.setSelection(); } }, { key: 'toggleCustom', value: function toggleCustom(_ref2) { var tagName = _ref2.tagName, attributes = _ref2.attributes; var customElem = this.createElement(tagName, attributes); this.toggle(customElem); } }, { key: 'makeCustom', value: function makeCustom(_ref3) { var tagName = _ref3.tagName, attributes = _ref3.attributes; var customElem = this.createElement(tagName, attributes); this.forceWrap(customElem); } }, { key: 'makeBold', value: function makeBold() { var bold = this.createElement(config.boldMarkup.name, config.boldMarkup.attribs); this.forceWrap(bold); } }, { key: 'toggleBold', value: function toggleBold() { var bold = this.createElement(config.boldMarkup.name, config.boldMarkup.attribs); this.toggle(bold); } }, { key: 'giveEmphasis', value: function giveEmphasis() { var em = this.createElement(config.italicMarkup.name, config.italicMarkup.attribs); this.forceWrap(em); } }, { key: 'toggleEmphasis', value: function toggleEmphasis() { var em = this.createElement(config.italicMarkup.name, config.italicMarkup.attribs); this.toggle(em); } }, { key: 'makeUnderline', value: function makeUnderline() { var u = this.createElement(config.underlineMarkup.name, config.underlineMarkup.attribs); this.forceWrap(u); } }, { key: 'toggleUnderline', value: function toggleUnderline() { var u = this.createElement(config.underlineMarkup.name, config.underlineMarkup.attribs); this.toggle(u); } }, { key: 'insertCharacter', value: function insertCharacter(character) { var cursor = this.deleteContent(); var textNode = cursor.createTextNode(character); cursor.insertBefore(textNode); cursor.setSelection(); return cursor; } // Surround the selection with characters like quotes. // // @param {String} E.g. '«' // @param {String} E.g. '»' }, { key: 'surround', value: function surround(startCharacter, endCharacter) { this.range = content.surround(this.host, this.range, startCharacter, endCharacter); this.setSelection(); } }, { key: 'removeSurround', value: function removeSurround(startCharacter, endCharacter) { this.range = content.deleteCharacter(this.host, this.range, startCharacter); this.range = content.deleteCharacter(this.host, this.range, endCharacter); this.setSelection(); } }, { key: 'toggleSurround', value: function toggleSurround(startCharacter, endCharacter) { if (this.containsString(startCharacter) && this.containsString(endCharacter)) { this.removeSurround(startCharacter, endCharacter); } else { this.surround(startCharacter, endCharacter); } } // @param {String} tagName. E.g. 'a' to remove all links. }, { key: 'removeFormatting', value: function removeFormatting(tagName) { this.range = content.removeFormatting(this.host, this.range, tagName); this.setSelection(); } // Delete the contents inside the range. After that the selection will be a // cursor. // // @return Cursor instance }, { key: 'deleteContent', value: function deleteContent() { this.range.deleteContents(); return new _cursor2.default(this.host, this.range); } // Expand the current selection. // // @param {DOM Node} }, { key: 'expandTo', value: function expandTo(elem) { this.range = content.expandTo(this.host, this.range, elem); this.setSelection(); } // Collapse the selection at the beginning of the selection // // @return Cursor instance }, { key: 'collapseAtBeginning', value: function collapseAtBeginning(elem) { this.range.collapse(true); this.setSelection(); return new _cursor2.default(this.host, this.range); } // Collapse the selection at the end of the selection // // @return Cursor instance }, { key: 'collapseAtEnd', value: function collapseAtEnd(elem) { this.range.collapse(false); this.setSelection(); return new _cursor2.default(this.host, this.range); } // Wrap the selection with the specified tag. If any other tag with // the same tagName is affecting the selection this tag will be // remove first. }, { key: 'forceWrap', value: function forceWrap(elem) { elem = this.adoptElement(elem); this.range = content.forceWrap(this.host, this.range, elem); this.setSelection(); } // Get all tags that affect the current selection. Optionally pass a // method to filter the returned elements. // // @param {Function filter(node)} [Optional] Method to filter the returned // DOM Nodes. // @return {Array of DOM Nodes} }, { key: 'getTags', value: function getTags(filterFunc) { return content.getTags(this.host, this.range, filterFunc); } // Get all tags of the specified type that affect the current selection. // // @method getTagsByName // @param {String} tagName. E.g. 'a' to get all links. // @return {Array of DOM Nodes} }, { key: 'getTagsByName', value: function getTagsByName(tagName) { return content.getTagsByName(this.host, this.range, tagName); } // Check if the selection is the same as the elements contents. // // @method isExactSelection // @param {DOM Node} // @param {flag: undefined or 'visible'} if 'visible' is passed // whitespaces at the beginning or end of the selection will // be ignored. // @return {Boolean} }, { key: 'isExactSelection', value: function isExactSelection(elem, onlyVisible) { return content.isExactSelection(this.range, elem, onlyVisible); } // Check if the selection contains the passed string. // // @method containsString // @return {Boolean} }, { key: 'containsString', value: function containsString(str) { return content.containsString(this.range, str); } // Delete all occurences of the specified character from the // selection. }, { key: 'deleteCharacter', value: function deleteCharacter(character) { this.range = content.deleteCharacter(this.host, this.range, character); this.setSelection(); } }]); return Selection; }(_cursor2.default); exports.default = Selection;