'use strict'; var _keys = require('babel-runtime/core-js/object/keys'); var _keys2 = _interopRequireDefault(_keys); 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 _get2 = require('babel-runtime/helpers/get'); var _get3 = _interopRequireDefault(_get2); var _inherits2 = require('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); var _quill = require('quill'); var _quill2 = _interopRequireDefault(_quill); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var BlockEmbed = _quill2.default.import('blots/block/embed'); // write ES2015 code and import modules from npm // and then press "Execute" to run your program var VideoBlot = function (_BlockEmbed) { (0, _inherits3.default)(VideoBlot, _BlockEmbed); function VideoBlot() { (0, _classCallCheck3.default)(this, VideoBlot); return (0, _possibleConstructorReturn3.default)(this, (0, _getPrototypeOf2.default)(VideoBlot).apply(this, arguments)); } (0, _createClass3.default)(VideoBlot, [{ key: 'format', value: function format(name, value) { // Handle unregistered embed formats if (name === 'height' || name === 'width') { if (value) { this.domNode.setAttribute(name, value); } else { this.domNode.removeAttribute(name, value); } } else { (0, _get3.default)((0, _getPrototypeOf2.default)(VideoBlot.prototype), 'format', this).call(this, name, value); } } }], [{ key: 'create', value: function create(url) { var node = (0, _get3.default)((0, _getPrototypeOf2.default)(VideoBlot), 'create', this).call(this); // Set non-format related attributes with static values node.setAttribute('frameborder', '0'); node.setAttribute('allowfullscreen', true); return node; } }, { key: 'formats', value: function formats(node) { // We still need to report unregistered embed formats var format = {}; if (node.hasAttribute('height')) { format.height = node.getAttribute('height'); } if (node.hasAttribute('width')) { format.width = node.getAttribute('width'); } return format; } }, { key: 'value', value: function value(node) { return node.getAttribute('src'); } }]); return VideoBlot; }(BlockEmbed); VideoBlot.blotName = 'video'; VideoBlot.tagName = 'iframe'; //Quill.register(VideoBlot); /* Credits go to: http://codepen.io/anon/pen/MjNeVM */ var Inline = _quill2.default.import('blots/inline'); var MentionBlot = function (_Inline) { (0, _inherits3.default)(MentionBlot, _Inline); function MentionBlot() { (0, _classCallCheck3.default)(this, MentionBlot); return (0, _possibleConstructorReturn3.default)(this, (0, _getPrototypeOf2.default)(MentionBlot).apply(this, arguments)); } (0, _createClass3.default)(MentionBlot, [{ key: 'format', value: function format(name, value) { if (name === "mention" && value) { this.domNode.dataset.id = value; } else { (0, _get3.default)((0, _getPrototypeOf2.default)(MentionBlot.prototype), 'format', this).call(this, name, value); } } }, { key: 'formats', value: function formats() { var formats = (0, _get3.default)((0, _getPrototypeOf2.default)(MentionBlot.prototype), 'formats', this).call(this); formats['mention'] = MentionBlot.formats(this.domNode); return formats; } }], [{ key: 'create', value: function create(id) { var node = (0, _get3.default)((0, _getPrototypeOf2.default)(MentionBlot), 'create', this).call(this); node.dataset.id = id; return node; } }, { key: 'formats', value: function formats(node) { return node.dataset.id; } }]); return MentionBlot; }(Inline); MentionBlot.blotName = "mention"; MentionBlot.tagName = "SPAN"; MentionBlot.className = "mention"; _quill2.default.register({ 'formats/mention': MentionBlot }); var h = function h(tag, attrs) { for (var _len = arguments.length, children = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { children[_key - 2] = arguments[_key]; } var elem = document.createElement(tag); (0, _keys2.default)(attrs).forEach(function (key) { return elem[key] = attrs[key]; }); children.forEach(function (child) { if (typeof child === "string") child = document.createTextNode(child); elem.appendChild(child); }); return elem; }; var Mentions = function () { function Mentions(quill, props) { (0, _classCallCheck3.default)(this, Mentions); this.quill = quill; this.onClose = props.onClose; this.onOpen = props.onOpen; this.users = props.users; this.container = this.quill.container.parentNode.querySelector(props.container); this.container.style.position = "absolute"; this.container.style.display = "none"; this.onSelectionChange = this.maybeUnfocus.bind(this); this.onTextChange = this.update.bind(this); this.open = false; this.atIndex = null; this.focusedButton = null; quill.keyboard.addBinding({ // TODO: Once Quill supports using event.key (#1091) use that instead of shift-2 key: 50, // 2 shiftKey: true }, this.onAtKey.bind(this)); quill.keyboard.addBinding({ // TODO: Once Quill supports using event.key (#1091) use that instead of shift-2 key: 81, // 2 altKey: true }, this.onAtKey.bind(this)); quill.keyboard.addBinding({ key: 40, // ArrowDown collapsed: true, format: ["mention"] }, this.handleArrow.bind(this)); // TODO: Add keybindings for Enter (13) and Tab (9) directly on the quill editor } (0, _createClass3.default)(Mentions, [{ key: 'onAtKey', value: function onAtKey(range, context) { if (this.open) return true; if (range.length > 0) { this.quill.deleteText(range.index, range.length, _quill2.default.sources.USER); } this.quill.insertText(range.index, "@", "mention", "0", _quill2.default.sources.USER); var atSignBounds = this.quill.getBounds(range.index); this.quill.setSelection(range.index + 1, _quill2.default.sources.SILENT); this.atIndex = range.index; this.container.style.left = atSignBounds.left + "px"; this.container.style.top = atSignBounds.top + atSignBounds.height + "px", this.open = true; this.quill.on('text-change', this.onTextChange); this.quill.once('selection-change', this.onSelectionChange); this.update(); this.onOpen && this.onOpen(); } }, { key: 'handleArrow', value: function handleArrow() { if (!this.open) return true; this.buttons[0].focus(); } }, { key: 'update', value: function update() { var _this3 = this; var sel = this.quill.getSelection().index; if (this.atIndex >= sel) { // Deleted the at character return this.close(null); } this.query = this.quill.getText(this.atIndex + 1, sel - this.atIndex - 1); // TODO: Should use fuse.js or similar fuzzy-matcher var users = this.users.filter(function (u) { return u.name.startsWith(_this3.query); }).sort(function (u1, u2) { return u1.name > u2.name; }); this.renderCompletions(users); } }, { key: 'maybeUnfocus', value: function maybeUnfocus() { if (this.container.querySelector("*:focus")) return; this.close(null); } }, { key: 'renderCompletions', value: function renderCompletions(users) { var _this4 = this; while (this.container.firstChild) { this.container.removeChild(this.container.firstChild); }var buttons = Array(users.length); this.buttons = buttons; var handler = function handler(i, user) { return function (event) { if (event.key === "ArrowDown" || event.keyCode === 40) { event.preventDefault(); buttons[Math.min(buttons.length - 1, i + 1)].focus(); } else if (event.key === "ArrowUp" || event.keyCode === 38) { event.preventDefault(); buttons[Math.max(0, i - 1)].focus(); } else if (event.key === "Enter" || event.keyCode === 13 || event.key === " " || event.keyCode === 32 || event.key === "Tab" || event.keyCode === 9) { event.preventDefault(); _this4.close(user); } }; }; users.forEach(function (user, i) { var li = h('li', {}, h('button', { type: "button" }, h('span', { className: "matched" }, "@" + _this4.query), h('span', { className: "unmatched" }, user.name.slice(_this4.query.length)))); _this4.container.appendChild(li); buttons[i] = li.firstChild; // Events will be GC-ed with button on each re-render: buttons[i].addEventListener('keydown', handler(i, user)); buttons[i].addEventListener("mousedown", function () { return _this4.close(user); }); buttons[i].addEventListener("focus", function () { return _this4.focusedButton = i; }); buttons[i].addEventListener("unfocus", function () { return _this4.focusedButton = null; }); }); this.container.style.display = "block"; } }, { key: 'close', value: function close(value) { this.container.style.display = "none"; while (this.container.firstChild) { this.container.removeChild(this.container.firstChild); }this.quill.off('selection-change', this.onSelectionChange); this.quill.off('text-change', this.onTextChange); if (value) { var id = value.id; var name = value.name; this.quill.deleteText(this.atIndex, this.query.length + 1, _quill2.default.sources.USER); this.quill.insertText(this.atIndex, "@" + name, "mention", id, _quill2.default.sources.USER); this.quill.insertText(this.atIndex + name.length + 1, " ", 'mention', false, _quill2.default.sources.USER); this.quill.setSelection(this.atIndex + name.length + 1, 0, _quill2.default.sources.SILENT); } this.quill.focus(); this.open = false; this.onClose && this.onClose(value); } }]); return Mentions; }(); _quill2.default.register('modules/mentions', Mentions); var quill = new _quill2.default('#editor-container', { modules: { mentions: { container: '.completions', onClose: function onClose(val) { return console.log("Closing: ", val); }, onOpen: function onOpen() { return console.log("Opening"); }, users: [{ id: 1, name: 'Christy' }, { id: 2, name: 'Micha' }, { id: 3, name: 'Sima' }, { id: 4, name: 'Coreen' }, { id: 5, name: 'Aimee' }, { id: 6, name: 'Brant' }, { id: 7, name: 'Maryetta' }, { id: 8, name: 'Nicol' }, { id: 9, name: 'Thresa' }, { id: 10, name: 'Pura' }, { id: 11, name: 'Audie' }, { id: 12, name: 'Jacob' }, { id: 13, name: 'Mika' }, { id: 14, name: 'Nubia' }, { id: 15, name: 'Ana' }, { id: 16, name: 'Sudie' }, { id: 17, name: 'Raymundo' }, { id: 18, name: 'Carolyne' }, { id: 19, name: 'Doretha' }, { id: 20, name: 'Milo' }] } } }); quill.on('text-change', function (dlt, oldDlt, source) { console.log('text-change', dlt, oldDlt, source); });