2
0
mirror of https://github.com/tenrok/vue-tribute.git synced 2026-06-18 09:50:34 +03:00
Files
vue-tribute/dist/vue-tribute.js
T
2019-02-08 15:33:20 -05:00

1836 lines
73 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.VueTribute = factory());
}(this, (function () { 'use strict';
function commonjsRequire () {
throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs');
}
function unwrapExports (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x.default : x;
}
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}
var tribute = createCommonjsModule(function (module, exports) {
(function(f){{module.exports=f();}})(function(){return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof commonjsRequire&&commonjsRequire;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t);}return n[i].exports}for(var u="function"==typeof commonjsRequire&&commonjsRequire,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _utils = require("./utils");
var _utils2 = _interopRequireDefault(_utils);
var _TributeEvents = require("./TributeEvents");
var _TributeEvents2 = _interopRequireDefault(_TributeEvents);
var _TributeMenuEvents = require("./TributeMenuEvents");
var _TributeMenuEvents2 = _interopRequireDefault(_TributeMenuEvents);
var _TributeRange = require("./TributeRange");
var _TributeRange2 = _interopRequireDefault(_TributeRange);
var _TributeSearch = require("./TributeSearch");
var _TributeSearch2 = _interopRequireDefault(_TributeSearch);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Tribute = function () {
function Tribute(_ref) {
var _this = this;
var _ref$values = _ref.values,
values = _ref$values === undefined ? null : _ref$values,
_ref$iframe = _ref.iframe,
iframe = _ref$iframe === undefined ? null : _ref$iframe,
_ref$selectClass = _ref.selectClass,
selectClass = _ref$selectClass === undefined ? 'highlight' : _ref$selectClass,
_ref$trigger = _ref.trigger,
trigger = _ref$trigger === undefined ? '@' : _ref$trigger,
_ref$selectTemplate = _ref.selectTemplate,
selectTemplate = _ref$selectTemplate === undefined ? null : _ref$selectTemplate,
_ref$menuItemTemplate = _ref.menuItemTemplate,
menuItemTemplate = _ref$menuItemTemplate === undefined ? null : _ref$menuItemTemplate,
_ref$lookup = _ref.lookup,
lookup = _ref$lookup === undefined ? 'key' : _ref$lookup,
_ref$fillAttr = _ref.fillAttr,
fillAttr = _ref$fillAttr === undefined ? 'value' : _ref$fillAttr,
_ref$collection = _ref.collection,
collection = _ref$collection === undefined ? null : _ref$collection,
_ref$menuContainer = _ref.menuContainer,
menuContainer = _ref$menuContainer === undefined ? null : _ref$menuContainer,
_ref$noMatchTemplate = _ref.noMatchTemplate,
noMatchTemplate = _ref$noMatchTemplate === undefined ? null : _ref$noMatchTemplate,
_ref$requireLeadingSp = _ref.requireLeadingSpace,
requireLeadingSpace = _ref$requireLeadingSp === undefined ? true : _ref$requireLeadingSp,
_ref$allowSpaces = _ref.allowSpaces,
allowSpaces = _ref$allowSpaces === undefined ? false : _ref$allowSpaces,
_ref$replaceTextSuffi = _ref.replaceTextSuffix,
replaceTextSuffix = _ref$replaceTextSuffi === undefined ? null : _ref$replaceTextSuffi,
_ref$positionMenu = _ref.positionMenu,
positionMenu = _ref$positionMenu === undefined ? true : _ref$positionMenu,
_ref$spaceSelectsMatc = _ref.spaceSelectsMatch,
spaceSelectsMatch = _ref$spaceSelectsMatc === undefined ? false : _ref$spaceSelectsMatc,
_ref$searchOpts = _ref.searchOpts,
searchOpts = _ref$searchOpts === undefined ? {} : _ref$searchOpts;
_classCallCheck(this, Tribute);
this.menuSelected = 0;
this.current = {};
this.inputEvent = false;
this.isActive = false;
this.menuContainer = menuContainer;
this.allowSpaces = allowSpaces;
this.replaceTextSuffix = replaceTextSuffix;
this.positionMenu = positionMenu;
this.hasTrailingSpace = false;
this.spaceSelectsMatch = spaceSelectsMatch;
if (values) {
this.collection = [{
// symbol that starts the lookup
trigger: trigger,
// is it wrapped in an iframe
iframe: iframe,
// class applied to selected item
selectClass: selectClass,
// function called on select that retuns the content to insert
selectTemplate: (selectTemplate || Tribute.defaultSelectTemplate).bind(this),
// function called that returns content for an item
menuItemTemplate: (menuItemTemplate || Tribute.defaultMenuItemTemplate).bind(this),
// function called when menu is empty, disables hiding of menu.
noMatchTemplate: function (t) {
if (typeof t === 'function') {
return t.bind(_this);
}
return noMatchTemplate || function () {
return '';
}.bind(_this);
}(noMatchTemplate),
// column to search against in the object
lookup: lookup,
// column that contains the content to insert by default
fillAttr: fillAttr,
// array of objects or a function returning an array of objects
values: values,
requireLeadingSpace: requireLeadingSpace,
searchOpts: searchOpts
}];
} else if (collection) {
this.collection = collection.map(function (item) {
return {
trigger: item.trigger || trigger,
iframe: item.iframe || iframe,
selectClass: item.selectClass || selectClass,
selectTemplate: (item.selectTemplate || Tribute.defaultSelectTemplate).bind(_this),
menuItemTemplate: (item.menuItemTemplate || Tribute.defaultMenuItemTemplate).bind(_this),
// function called when menu is empty, disables hiding of menu.
noMatchTemplate: function (t) {
if (typeof t === 'function') {
return t.bind(_this);
}
return null;
}(noMatchTemplate),
lookup: item.lookup || lookup,
fillAttr: item.fillAttr || fillAttr,
values: item.values,
requireLeadingSpace: item.requireLeadingSpace,
searchOpts: item.searchOpts || searchOpts
};
});
} else {
throw new Error('[Tribute] No collection specified.');
}
new _TributeRange2.default(this);
new _TributeEvents2.default(this);
new _TributeMenuEvents2.default(this);
new _TributeSearch2.default(this);
}
_createClass(Tribute, [{
key: "triggers",
value: function triggers() {
return this.collection.map(function (config) {
return config.trigger;
});
}
}, {
key: "attach",
value: function attach(el) {
if (!el) {
throw new Error('[Tribute] Must pass in a DOM node or NodeList.');
}
// Check if it is a jQuery collection
if (typeof jQuery !== 'undefined' && el instanceof jQuery) {
el = el.get();
}
// Is el an Array/Array-like object?
if (el.constructor === NodeList || el.constructor === HTMLCollection || el.constructor === Array) {
var length = el.length;
for (var i = 0; i < length; ++i) {
this._attach(el[i]);
}
} else {
this._attach(el);
}
}
}, {
key: "_attach",
value: function _attach(el) {
if (el.hasAttribute('data-tribute')) {
console.warn('Tribute was already bound to ' + el.nodeName);
}
this.ensureEditable(el);
this.events.bind(el);
el.setAttribute('data-tribute', true);
}
}, {
key: "ensureEditable",
value: function ensureEditable(element) {
if (Tribute.inputTypes().indexOf(element.nodeName) === -1) {
if (element.contentEditable) {
element.contentEditable = true;
} else {
throw new Error('[Tribute] Cannot bind to ' + element.nodeName);
}
}
}
}, {
key: "createMenu",
value: function createMenu() {
var wrapper = this.range.getDocument().createElement('div'),
ul = this.range.getDocument().createElement('ul');
wrapper.className = 'tribute-container';
wrapper.appendChild(ul);
if (this.menuContainer) {
return this.menuContainer.appendChild(wrapper);
}
return this.range.getDocument().body.appendChild(wrapper);
}
}, {
key: "showMenuFor",
value: function showMenuFor(element, scrollTo) {
var _this2 = this;
// Only proceed if menu isn't already shown for the current element & mentionText
if (this.isActive && this.current.element === element && this.current.mentionText === this.currentMentionTextSnapshot) {
return;
}
this.currentMentionTextSnapshot = this.current.mentionText;
// create the menu if it doesn't exist.
if (!this.menu) {
this.menu = this.createMenu();
element.tributeMenu = this.menu;
this.menuEvents.bind(this.menu);
}
this.isActive = true;
this.menuSelected = 0;
if (!this.current.mentionText) {
this.current.mentionText = '';
}
var processValues = function processValues(values) {
// Tribute may not be active any more by the time the value callback returns
if (!_this2.isActive) {
return;
}
var items = _this2.search.filter(_this2.current.mentionText, values, {
pre: _this2.current.collection.searchOpts.pre || '<span>',
post: _this2.current.collection.searchOpts.post || '</span>',
extract: function extract(el) {
if (typeof _this2.current.collection.lookup === 'string') {
return el[_this2.current.collection.lookup];
} else if (typeof _this2.current.collection.lookup === 'function') {
return _this2.current.collection.lookup(el, _this2.current.mentionText);
} else {
throw new Error('Invalid lookup attribute, lookup must be string or function.');
}
}
});
_this2.current.filteredItems = items;
var ul = _this2.menu.querySelector('ul');
_this2.range.positionMenuAtCaret(scrollTo);
if (!items.length) {
var noMatchEvent = new CustomEvent('tribute-no-match', { detail: _this2.menu });
_this2.current.element.dispatchEvent(noMatchEvent);
if (!_this2.current.collection.noMatchTemplate) {
_this2.hideMenu();
} else {
ul.innerHTML = _this2.current.collection.noMatchTemplate();
}
return;
}
ul.innerHTML = '';
items.forEach(function (item, index) {
var li = _this2.range.getDocument().createElement('li');
li.setAttribute('data-index', index);
li.addEventListener('mouseenter', function (e) {
var li = e.target;
var index = li.getAttribute('data-index');
_this2.events.setActiveLi(index);
});
if (_this2.menuSelected === index) {
li.className = _this2.current.collection.selectClass;
}
li.innerHTML = _this2.current.collection.menuItemTemplate(item);
ul.appendChild(li);
});
};
if (typeof this.current.collection.values === 'function') {
this.current.collection.values(this.current.mentionText, processValues);
} else {
processValues(this.current.collection.values);
}
}
}, {
key: "showMenuForCollection",
value: function showMenuForCollection(element, collectionIndex) {
if (element !== document.activeElement) {
this.placeCaretAtEnd(element);
}
this.current.collection = this.collection[collectionIndex || 0];
this.current.externalTrigger = true;
this.current.element = element;
if (element.isContentEditable) this.insertTextAtCursor(this.current.collection.trigger);else this.insertAtCaret(element, this.current.collection.trigger);
this.showMenuFor(element);
}
// TODO: make sure this works for inputs/textareas
}, {
key: "placeCaretAtEnd",
value: function placeCaretAtEnd(el) {
el.focus();
if (typeof window.getSelection != "undefined" && typeof document.createRange != "undefined") {
var range = document.createRange();
range.selectNodeContents(el);
range.collapse(false);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (typeof document.body.createTextRange != "undefined") {
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);
textRange.collapse(false);
textRange.select();
}
}
// for contenteditable
}, {
key: "insertTextAtCursor",
value: function insertTextAtCursor(text) {
var sel, range;
sel = window.getSelection();
range = sel.getRangeAt(0);
range.deleteContents();
var textNode = document.createTextNode(text);
range.insertNode(textNode);
range.selectNodeContents(textNode);
range.collapse(false);
sel.removeAllRanges();
sel.addRange(range);
}
// for regular inputs
}, {
key: "insertAtCaret",
value: function insertAtCaret(textarea, text) {
var scrollPos = textarea.scrollTop;
var caretPos = textarea.selectionStart;
var front = textarea.value.substring(0, caretPos);
var back = textarea.value.substring(textarea.selectionEnd, textarea.value.length);
textarea.value = front + text + back;
caretPos = caretPos + text.length;
textarea.selectionStart = caretPos;
textarea.selectionEnd = caretPos;
textarea.focus();
textarea.scrollTop = scrollPos;
}
}, {
key: "hideMenu",
value: function hideMenu() {
if (this.menu) {
this.menu.style.cssText = 'display: none;';
this.isActive = false;
this.menuSelected = 0;
this.current = {};
}
}
}, {
key: "selectItemAtIndex",
value: function selectItemAtIndex(index, originalEvent) {
index = parseInt(index);
if (typeof index !== 'number') return;
var item = this.current.filteredItems[index];
var content = this.current.collection.selectTemplate(item);
if (content !== null) this.replaceText(content, originalEvent, item);
}
}, {
key: "replaceText",
value: function replaceText(content, originalEvent, item) {
this.range.replaceTriggerText(content, true, true, originalEvent, item);
}
}, {
key: "_append",
value: function _append(collection, newValues, replace) {
if (typeof collection.values === 'function') {
throw new Error('Unable to append to values, as it is a function.');
} else if (!replace) {
collection.values = collection.values.concat(newValues);
} else {
collection.values = newValues;
}
}
}, {
key: "append",
value: function append(collectionIndex, newValues, replace) {
var index = parseInt(collectionIndex);
if (typeof index !== 'number') throw new Error('please provide an index for the collection to update.');
var collection = this.collection[index];
this._append(collection, newValues, replace);
}
}, {
key: "appendCurrent",
value: function appendCurrent(newValues, replace) {
if (this.isActive) {
this._append(this.current.collection, newValues, replace);
} else {
throw new Error('No active state. Please use append instead and pass an index.');
}
}
}, {
key: "detach",
value: function detach(el) {
if (!el) {
throw new Error('[Tribute] Must pass in a DOM node or NodeList.');
}
// Check if it is a jQuery collection
if (typeof jQuery !== 'undefined' && el instanceof jQuery) {
el = el.get();
}
// Is el an Array/Array-like object?
if (el.constructor === NodeList || el.constructor === HTMLCollection || el.constructor === Array) {
var length = el.length;
for (var i = 0; i < length; ++i) {
this._detach(el[i]);
}
} else {
this._detach(el);
}
}
}, {
key: "_detach",
value: function _detach(el) {
var _this3 = this;
this.events.unbind(el);
if (el.tributeMenu) {
this.menuEvents.unbind(el.tributeMenu);
}
setTimeout(function () {
el.removeAttribute('data-tribute');
_this3.isActive = false;
if (el.tributeMenu) {
el.tributeMenu.remove();
}
});
}
}], [{
key: "defaultSelectTemplate",
value: function defaultSelectTemplate(item) {
if (typeof item === 'undefined') return null;
if (this.range.isContentEditable(this.current.element)) {
return '<span class="tribute-mention">' + (this.current.collection.trigger + item.original[this.current.collection.fillAttr]) + '</span>';
}
return this.current.collection.trigger + item.original[this.current.collection.fillAttr];
}
}, {
key: "defaultMenuItemTemplate",
value: function defaultMenuItemTemplate(matchItem) {
return matchItem.string;
}
}, {
key: "inputTypes",
value: function inputTypes() {
return ['TEXTAREA', 'INPUT'];
}
}]);
return Tribute;
}();
exports.default = Tribute;
module.exports = exports["default"];
},{"./TributeEvents":2,"./TributeMenuEvents":3,"./TributeRange":4,"./TributeSearch":5,"./utils":7}],2:[function(require,module,exports){
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var TributeEvents = function () {
function TributeEvents(tribute) {
_classCallCheck(this, TributeEvents);
this.tribute = tribute;
this.tribute.events = this;
}
_createClass(TributeEvents, [{
key: 'bind',
value: function bind(element) {
element.boundKeydown = this.keydown.bind(element, this);
element.boundKeyup = this.keyup.bind(element, this);
element.boundInput = this.input.bind(element, this);
element.addEventListener('keydown', element.boundKeydown, false);
element.addEventListener('keyup', element.boundKeyup, false);
element.addEventListener('input', element.boundInput, false);
}
}, {
key: 'unbind',
value: function unbind(element) {
element.removeEventListener('keydown', element.boundKeydown, false);
element.removeEventListener('keyup', element.boundKeyup, false);
element.removeEventListener('input', element.boundInput, false);
delete element.boundKeydown;
delete element.boundKeyup;
delete element.boundInput;
}
}, {
key: 'keydown',
value: function keydown(instance, event) {
if (instance.shouldDeactivate(event)) {
instance.tribute.isActive = false;
instance.tribute.hideMenu();
}
var element = this;
instance.commandEvent = false;
TributeEvents.keys().forEach(function (o) {
if (o.key === event.keyCode) {
instance.commandEvent = true;
instance.callbacks()[o.value.toLowerCase()](event, element);
}
});
}
}, {
key: 'input',
value: function input(instance, event) {
instance.inputEvent = true;
instance.keyup.call(this, instance, event);
}
}, {
key: 'click',
value: function click(instance, event) {
var tribute = instance.tribute;
if (tribute.menu && tribute.menu.contains(event.target)) {
var li = event.target;
event.preventDefault();
event.stopPropagation();
while (li.nodeName.toLowerCase() !== 'li') {
li = li.parentNode;
if (!li || li === tribute.menu) {
throw new Error('cannot find the <li> container for the click');
}
}
tribute.selectItemAtIndex(li.getAttribute('data-index'), event);
tribute.hideMenu();
// TODO: should fire with externalTrigger and target is outside of menu
} else if (tribute.current.element && !tribute.current.externalTrigger) {
tribute.current.externalTrigger = false;
setTimeout(function () {
return tribute.hideMenu();
});
}
}
}, {
key: 'keyup',
value: function keyup(instance, event) {
if (instance.inputEvent) {
instance.inputEvent = false;
}
instance.updateSelection(this);
if (event.keyCode === 27) return;
if (!instance.tribute.allowSpaces && instance.tribute.hasTrailingSpace) {
instance.tribute.hasTrailingSpace = false;
instance.commandEvent = true;
instance.callbacks()["space"](event, this);
return;
}
if (!instance.tribute.isActive) {
var keyCode = instance.getKeyCode(instance, this, event);
if (isNaN(keyCode) || !keyCode) return;
var trigger = instance.tribute.triggers().find(function (trigger) {
return trigger.charCodeAt(0) === keyCode;
});
if (typeof trigger !== 'undefined') {
instance.callbacks().triggerChar(event, this, trigger);
}
}
if (instance.tribute.current.trigger && instance.commandEvent === false || instance.tribute.isActive && event.keyCode === 8) {
instance.tribute.showMenuFor(this, true);
}
}
}, {
key: 'shouldDeactivate',
value: function shouldDeactivate(event) {
if (!this.tribute.isActive) return false;
if (this.tribute.current.mentionText.length === 0) {
var eventKeyPressed = false;
TributeEvents.keys().forEach(function (o) {
if (event.keyCode === o.key) eventKeyPressed = true;
});
return !eventKeyPressed;
}
return false;
}
}, {
key: 'getKeyCode',
value: function getKeyCode(instance, el, event) {
var tribute = instance.tribute;
var info = tribute.range.getTriggerInfo(false, tribute.hasTrailingSpace, true, tribute.allowSpaces);
if (info) {
return info.mentionTriggerChar.charCodeAt(0);
} else {
return false;
}
}
}, {
key: 'updateSelection',
value: function updateSelection(el) {
this.tribute.current.element = el;
var info = this.tribute.range.getTriggerInfo(false, this.tribute.hasTrailingSpace, true, this.tribute.allowSpaces);
if (info) {
this.tribute.current.selectedPath = info.mentionSelectedPath;
this.tribute.current.mentionText = info.mentionText;
this.tribute.current.selectedOffset = info.mentionSelectedOffset;
}
}
}, {
key: 'callbacks',
value: function callbacks() {
var _this = this;
return {
triggerChar: function triggerChar(e, el, trigger) {
var tribute = _this.tribute;
tribute.current.trigger = trigger;
var collectionItem = tribute.collection.find(function (item) {
return item.trigger === trigger;
});
tribute.current.collection = collectionItem;
if (tribute.inputEvent) tribute.showMenuFor(el, true);
},
enter: function enter(e, el) {
// choose selection
if (_this.tribute.isActive) {
e.preventDefault();
e.stopPropagation();
setTimeout(function () {
_this.tribute.selectItemAtIndex(_this.tribute.menuSelected, e);
_this.tribute.hideMenu();
}, 0);
}
},
escape: function escape(e, el) {
if (_this.tribute.isActive) {
e.preventDefault();
e.stopPropagation();
_this.tribute.isActive = false;
_this.tribute.hideMenu();
}
},
tab: function tab(e, el) {
// choose first match
_this.callbacks().enter(e, el);
},
space: function space(e, el) {
if (_this.tribute.isActive) {
if (_this.tribute.spaceSelectsMatch) {
_this.callbacks().enter(e, el);
} else if (!_this.tribute.allowSpaces) {
e.stopPropagation();
setTimeout(function () {
_this.tribute.hideMenu();
_this.tribute.isActive = false;
}, 0);
}
}
},
up: function up(e, el) {
// navigate up ul
if (_this.tribute.isActive) {
e.preventDefault();
e.stopPropagation();
var count = _this.tribute.current.filteredItems.length,
selected = _this.tribute.menuSelected;
if (count > selected && selected > 0) {
_this.tribute.menuSelected--;
_this.setActiveLi();
} else if (selected === 0) {
_this.tribute.menuSelected = count - 1;
_this.setActiveLi();
_this.tribute.menu.scrollTop = _this.tribute.menu.scrollHeight;
}
}
},
down: function down(e, el) {
// navigate down ul
if (_this.tribute.isActive) {
e.preventDefault();
e.stopPropagation();
var count = _this.tribute.current.filteredItems.length - 1,
selected = _this.tribute.menuSelected;
if (count > selected) {
_this.tribute.menuSelected++;
_this.setActiveLi();
} else if (count === selected) {
_this.tribute.menuSelected = 0;
_this.setActiveLi();
_this.tribute.menu.scrollTop = 0;
}
}
},
delete: function _delete(e, el) {
if (_this.tribute.isActive && _this.tribute.current.mentionText.length < 1) {
_this.tribute.hideMenu();
} else if (_this.tribute.isActive) {
_this.tribute.showMenuFor(el);
}
}
};
}
}, {
key: 'setActiveLi',
value: function setActiveLi(index) {
var lis = this.tribute.menu.querySelectorAll('li'),
length = lis.length >>> 0;
// get heights
var menuFullHeight = this.getFullHeight(this.tribute.menu),
liHeight = this.getFullHeight(lis[0]);
if (index) this.tribute.menuSelected = index;
for (var i = 0; i < length; i++) {
var li = lis[i];
if (i === this.tribute.menuSelected) {
var offset = liHeight * (i + 1);
var scrollTop = this.tribute.menu.scrollTop;
var totalScroll = scrollTop + menuFullHeight;
if (offset > totalScroll) {
this.tribute.menu.scrollTop += liHeight;
} else if (offset < totalScroll) {
this.tribute.menu.scrollTop -= liHeight;
}
li.className = this.tribute.current.collection.selectClass;
} else {
li.className = '';
}
}
}
}, {
key: 'getFullHeight',
value: function getFullHeight(elem, includeMargin) {
var height = elem.getBoundingClientRect().height;
if (includeMargin) {
var style = elem.currentStyle || window.getComputedStyle(elem);
return height + parseFloat(style.marginTop) + parseFloat(style.marginBottom);
}
return height;
}
}], [{
key: 'keys',
value: function keys() {
return [{
key: 9,
value: 'TAB'
}, {
key: 8,
value: 'DELETE'
}, {
key: 13,
value: 'ENTER'
}, {
key: 27,
value: 'ESCAPE'
}, {
key: 32,
value: 'SPACE'
}, {
key: 38,
value: 'UP'
}, {
key: 40,
value: 'DOWN'
}];
}
}]);
return TributeEvents;
}();
exports.default = TributeEvents;
module.exports = exports['default'];
},{}],3:[function(require,module,exports){
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var TributeMenuEvents = function () {
function TributeMenuEvents(tribute) {
_classCallCheck(this, TributeMenuEvents);
this.tribute = tribute;
this.tribute.menuEvents = this;
this.menu = this.tribute.menu;
}
_createClass(TributeMenuEvents, [{
key: 'bind',
value: function bind(menu) {
var _this = this;
this.menuClickEvent = this.tribute.events.click.bind(null, this);
this.menuContainerScrollEvent = this.debounce(function () {
if (_this.tribute.isActive) {
_this.tribute.showMenuFor(_this.tribute.current.element, false);
}
}, 300, false);
this.windowResizeEvent = this.debounce(function () {
if (_this.tribute.isActive) {
_this.tribute.range.positionMenuAtCaret(true);
}
}, 300, false);
// fixes IE11 issues with mousedown
this.tribute.range.getDocument().addEventListener('MSPointerDown', this.menuClickEvent, false);
this.tribute.range.getDocument().addEventListener('mousedown', this.menuClickEvent, false);
window.addEventListener('resize', this.windowResizeEvent);
if (this.menuContainer) {
this.menuContainer.addEventListener('scroll', this.menuContainerScrollEvent, false);
} else {
window.addEventListener('scroll', this.menuContainerScrollEvent);
}
}
}, {
key: 'unbind',
value: function unbind(menu) {
this.tribute.range.getDocument().removeEventListener('mousedown', this.menuClickEvent, false);
this.tribute.range.getDocument().removeEventListener('MSPointerDown', this.menuClickEvent, false);
window.removeEventListener('resize', this.windowResizeEvent);
if (this.menuContainer) {
this.menuContainer.removeEventListener('scroll', this.menuContainerScrollEvent, false);
} else {
window.removeEventListener('scroll', this.menuContainerScrollEvent);
}
}
}, {
key: 'debounce',
value: function debounce(func, wait, immediate) {
var _this2 = this,
_arguments = arguments;
var timeout;
return function () {
var context = _this2,
args = _arguments;
var later = function later() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
}]);
return TributeMenuEvents;
}();
exports.default = TributeMenuEvents;
module.exports = exports['default'];
},{}],4:[function(require,module,exports){
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
// Thanks to https://github.com/jeff-collins/ment.io
var TributeRange = function () {
function TributeRange(tribute) {
_classCallCheck(this, TributeRange);
this.tribute = tribute;
this.tribute.range = this;
}
_createClass(TributeRange, [{
key: 'getDocument',
value: function getDocument() {
var iframe = void 0;
if (this.tribute.current.collection) {
iframe = this.tribute.current.collection.iframe;
}
if (!iframe) {
return document;
}
return iframe.contentWindow.document;
}
}, {
key: 'positionMenuAtCaret',
value: function positionMenuAtCaret(scrollTo) {
var _this = this;
var context = this.tribute.current,
coordinates = void 0;
var info = this.getTriggerInfo(false, this.tribute.hasTrailingSpace, true, this.tribute.allowSpaces);
if (typeof info !== 'undefined') {
if (!this.tribute.positionMenu) {
this.tribute.menu.style.cssText = 'display: block;';
return;
}
if (!this.isContentEditable(context.element)) {
coordinates = this.getTextAreaOrInputUnderlinePosition(this.tribute.current.element, info.mentionPosition);
} else {
coordinates = this.getContentEditableCaretPosition(info.mentionPosition);
}
this.tribute.menu.style.cssText = 'top: ' + coordinates.top + 'px;\n left: ' + coordinates.left + 'px;\n right: ' + coordinates.right + 'px;\n bottom: ' + coordinates.bottom + 'px;\n position: absolute;\n zIndex: 10000;\n display: block;';
if (coordinates.left === 'auto') {
this.tribute.menu.style.left = 'auto';
}
if (coordinates.top === 'auto') {
this.tribute.menu.style.top = 'auto';
}
if (scrollTo) this.scrollIntoView();
window.setTimeout(function () {
var menuDimensions = {
width: _this.tribute.menu.offsetWidth,
height: _this.tribute.menu.offsetHeight
};
var menuIsOffScreen = _this.isMenuOffScreen(coordinates, menuDimensions);
var menuIsOffScreenHorizontally = window.innerWidth > menuDimensions.width && (menuIsOffScreen.left || menuIsOffScreen.right);
var menuIsOffScreenVertically = window.innerHeight > menuDimensions.height && (menuIsOffScreen.top || menuIsOffScreen.bottom);
if (menuIsOffScreenHorizontally || menuIsOffScreenVertically) {
_this.tribute.menu.style.cssText = 'display: none';
_this.positionMenuAtCaret(scrollTo);
}
}, 0);
} else {
this.tribute.menu.style.cssText = 'display: none';
}
}
}, {
key: 'selectElement',
value: function selectElement(targetElement, path, offset) {
var range = void 0;
var elem = targetElement;
if (path) {
for (var i = 0; i < path.length; i++) {
elem = elem.childNodes[path[i]];
if (elem === undefined) {
return;
}
while (elem.length < offset) {
offset -= elem.length;
elem = elem.nextSibling;
}
if (elem.childNodes.length === 0 && !elem.length) {
elem = elem.previousSibling;
}
}
}
var sel = this.getWindowSelection();
range = this.getDocument().createRange();
range.setStart(elem, offset);
range.setEnd(elem, offset);
range.collapse(true);
try {
sel.removeAllRanges();
} catch (error) {}
sel.addRange(range);
targetElement.focus();
}
}, {
key: 'replaceTriggerText',
value: function replaceTriggerText(text, requireLeadingSpace, hasTrailingSpace, originalEvent, item) {
var context = this.tribute.current;
var info = this.getTriggerInfo(true, hasTrailingSpace, requireLeadingSpace, this.tribute.allowSpaces);
// Create the event
var replaceEvent = new CustomEvent('tribute-replaced', {
detail: {
item: item,
event: originalEvent
}
});
if (info !== undefined) {
if (!this.isContentEditable(context.element)) {
var myField = this.tribute.current.element;
var textSuffix = typeof this.tribute.replaceTextSuffix == 'string' ? this.tribute.replaceTextSuffix : ' ';
text += textSuffix;
var startPos = info.mentionPosition;
var endPos = info.mentionPosition + info.mentionText.length + textSuffix.length;
myField.value = myField.value.substring(0, startPos) + text + myField.value.substring(endPos, myField.value.length);
myField.selectionStart = startPos + text.length;
myField.selectionEnd = startPos + text.length;
} else {
// add a space to the end of the pasted text
var _textSuffix = typeof this.tribute.replaceTextSuffix == 'string' ? this.tribute.replaceTextSuffix : '\xA0';
text += _textSuffix;
this.pasteHtml(text, info.mentionPosition, info.mentionPosition + info.mentionText.length + 1);
}
context.element.dispatchEvent(replaceEvent);
}
}
}, {
key: 'pasteHtml',
value: function pasteHtml(html, startPos, endPos) {
var range = void 0,
sel = void 0;
sel = this.getWindowSelection();
range = this.getDocument().createRange();
range.setStart(sel.anchorNode, startPos);
range.setEnd(sel.anchorNode, endPos);
range.deleteContents();
var el = this.getDocument().createElement('div');
el.innerHTML = html;
var frag = this.getDocument().createDocumentFragment(),
node = void 0,
lastNode = void 0;
while (node = el.firstChild) {
lastNode = frag.appendChild(node);
}
range.insertNode(frag);
// Preserve the selection
if (lastNode) {
range = range.cloneRange();
range.setStartAfter(lastNode);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
}
}, {
key: 'getWindowSelection',
value: function getWindowSelection() {
if (this.tribute.collection.iframe) {
return this.tribute.collection.iframe.contentWindow.getSelection();
}
return window.getSelection();
}
}, {
key: 'getNodePositionInParent',
value: function getNodePositionInParent(element) {
if (element.parentNode === null) {
return 0;
}
for (var i = 0; i < element.parentNode.childNodes.length; i++) {
var node = element.parentNode.childNodes[i];
if (node === element) {
return i;
}
}
}
}, {
key: 'getContentEditableSelectedPath',
value: function getContentEditableSelectedPath(ctx) {
var sel = this.getWindowSelection();
var selected = sel.anchorNode;
var path = [];
var offset = void 0;
if (selected != null) {
var i = void 0;
var ce = selected.contentEditable;
while (selected !== null && ce !== 'true') {
i = this.getNodePositionInParent(selected);
path.push(i);
selected = selected.parentNode;
if (selected !== null) {
ce = selected.contentEditable;
}
}
path.reverse();
// getRangeAt may not exist, need alternative
offset = sel.getRangeAt(0).startOffset;
return {
selected: selected,
path: path,
offset: offset
};
}
}
}, {
key: 'getTextPrecedingCurrentSelection',
value: function getTextPrecedingCurrentSelection() {
var context = this.tribute.current,
text = '';
if (!this.isContentEditable(context.element)) {
var textComponent = this.tribute.current.element;
if (textComponent) {
var startPos = textComponent.selectionStart;
if (textComponent.value && startPos >= 0) {
text = textComponent.value.substring(0, startPos);
}
}
} else {
var selectedElem = this.getWindowSelection().anchorNode;
if (selectedElem != null) {
var workingNodeContent = selectedElem.textContent;
var selectStartOffset = this.getWindowSelection().getRangeAt(0).startOffset;
if (workingNodeContent && selectStartOffset >= 0) {
text = workingNodeContent.substring(0, selectStartOffset);
}
}
}
return text;
}
}, {
key: 'getTriggerInfo',
value: function getTriggerInfo(menuAlreadyActive, hasTrailingSpace, requireLeadingSpace, allowSpaces) {
var _this2 = this;
var ctx = this.tribute.current;
var selected = void 0,
path = void 0,
offset = void 0;
if (!this.isContentEditable(ctx.element)) {
selected = this.tribute.current.element;
} else {
var selectionInfo = this.getContentEditableSelectedPath(ctx);
if (selectionInfo) {
selected = selectionInfo.selected;
path = selectionInfo.path;
offset = selectionInfo.offset;
}
}
var effectiveRange = this.getTextPrecedingCurrentSelection();
if (effectiveRange !== undefined && effectiveRange !== null) {
var mostRecentTriggerCharPos = -1;
var triggerChar = void 0;
this.tribute.collection.forEach(function (config) {
var c = config.trigger;
var idx = config.requireLeadingSpace ? _this2.lastIndexWithLeadingSpace(effectiveRange, c) : effectiveRange.lastIndexOf(c);
if (idx > mostRecentTriggerCharPos) {
mostRecentTriggerCharPos = idx;
triggerChar = c;
requireLeadingSpace = config.requireLeadingSpace;
}
});
if (mostRecentTriggerCharPos >= 0 && (mostRecentTriggerCharPos === 0 || !requireLeadingSpace || /[\xA0\s]/g.test(effectiveRange.substring(mostRecentTriggerCharPos - 1, mostRecentTriggerCharPos)))) {
var currentTriggerSnippet = effectiveRange.substring(mostRecentTriggerCharPos + 1, effectiveRange.length);
triggerChar = effectiveRange.substring(mostRecentTriggerCharPos, mostRecentTriggerCharPos + 1);
var firstSnippetChar = currentTriggerSnippet.substring(0, 1);
var leadingSpace = currentTriggerSnippet.length > 0 && (firstSnippetChar === ' ' || firstSnippetChar === '\xA0');
if (hasTrailingSpace) {
currentTriggerSnippet = currentTriggerSnippet.trim();
}
var regex = allowSpaces ? /[^\S ]/g : /[\xA0\s]/g;
this.tribute.hasTrailingSpace = regex.test(currentTriggerSnippet);
if (!leadingSpace && (menuAlreadyActive || !regex.test(currentTriggerSnippet))) {
return {
mentionPosition: mostRecentTriggerCharPos,
mentionText: currentTriggerSnippet,
mentionSelectedElement: selected,
mentionSelectedPath: path,
mentionSelectedOffset: offset,
mentionTriggerChar: triggerChar
};
}
}
}
}
}, {
key: 'lastIndexWithLeadingSpace',
value: function lastIndexWithLeadingSpace(str, char) {
var reversedStr = str.split('').reverse().join('');
var index = -1;
for (var cidx = 0, len = str.length; cidx < len; cidx++) {
var firstChar = cidx === str.length - 1;
var leadingSpace = /\s/.test(reversedStr[cidx + 1]);
var match = char === reversedStr[cidx];
if (match && (firstChar || leadingSpace)) {
index = str.length - 1 - cidx;
break;
}
}
return index;
}
}, {
key: 'isContentEditable',
value: function isContentEditable(element) {
return element.nodeName !== 'INPUT' && element.nodeName !== 'TEXTAREA';
}
}, {
key: 'isMenuOffScreen',
value: function isMenuOffScreen(coordinates, menuDimensions) {
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
var doc = document.documentElement;
var windowLeft = (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0);
var windowTop = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
var menuTop = typeof coordinates.top === 'number' ? coordinates.top : windowTop + windowHeight - coordinates.bottom - menuDimensions.height;
var menuRight = typeof coordinates.right === 'number' ? coordinates.right : coordinates.left + menuDimensions.width;
var menuBottom = typeof coordinates.bottom === 'number' ? coordinates.bottom : coordinates.top + menuDimensions.height;
var menuLeft = typeof coordinates.left === 'number' ? coordinates.left : windowLeft + windowWidth - coordinates.right - menuDimensions.width;
return {
top: menuTop < Math.floor(windowTop),
right: menuRight > Math.ceil(windowLeft + windowWidth),
bottom: menuBottom > Math.ceil(windowTop + windowHeight),
left: menuLeft < Math.floor(windowLeft)
};
}
}, {
key: 'getMenuDimensions',
value: function getMenuDimensions() {
// Width of the menu depends of its contents and position
// We must check what its width would be without any obstruction
// This way, we can achieve good positioning for flipping the menu
var dimensions = {
width: null,
height: null
};
this.tribute.menu.style.cssText = 'top: 0px;\n left: 0px;\n position: fixed;\n zIndex: 10000;\n display: block;\n visibility; hidden;';
dimensions.width = this.tribute.menu.offsetWidth;
dimensions.height = this.tribute.menu.offsetHeight;
this.tribute.menu.style.cssText = 'display: none;';
return dimensions;
}
}, {
key: 'getTextAreaOrInputUnderlinePosition',
value: function getTextAreaOrInputUnderlinePosition(element, position, flipped) {
var properties = ['direction', 'boxSizing', 'width', 'height', 'overflowX', 'overflowY', 'borderTopWidth', 'borderRightWidth', 'borderBottomWidth', 'borderLeftWidth', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft', 'fontStyle', 'fontVariant', 'fontWeight', 'fontStretch', 'fontSize', 'fontSizeAdjust', 'lineHeight', 'fontFamily', 'textAlign', 'textTransform', 'textIndent', 'textDecoration', 'letterSpacing', 'wordSpacing'];
var isFirefox = window.mozInnerScreenX !== null;
var div = this.getDocument().createElement('div');
div.id = 'input-textarea-caret-position-mirror-div';
this.getDocument().body.appendChild(div);
var style = div.style;
var computed = window.getComputedStyle ? getComputedStyle(element) : element.currentStyle;
style.whiteSpace = 'pre-wrap';
if (element.nodeName !== 'INPUT') {
style.wordWrap = 'break-word';
}
// position off-screen
style.position = 'absolute';
style.visibility = 'hidden';
// transfer the element's properties to the div
properties.forEach(function (prop) {
style[prop] = computed[prop];
});
if (isFirefox) {
style.width = parseInt(computed.width) - 2 + 'px';
if (element.scrollHeight > parseInt(computed.height)) style.overflowY = 'scroll';
} else {
style.overflow = 'hidden';
}
div.textContent = element.value.substring(0, position);
if (element.nodeName === 'INPUT') {
div.textContent = div.textContent.replace(/\s/g, ' ');
}
var span = this.getDocument().createElement('span');
span.textContent = element.value.substring(position) || '.';
div.appendChild(span);
var rect = element.getBoundingClientRect();
var doc = document.documentElement;
var windowLeft = (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0);
var windowTop = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
var coordinates = {
top: rect.top + windowTop + span.offsetTop + parseInt(computed.borderTopWidth) + parseInt(computed.fontSize) - element.scrollTop,
left: rect.left + windowLeft + span.offsetLeft + parseInt(computed.borderLeftWidth)
};
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
var menuDimensions = this.getMenuDimensions();
var menuIsOffScreen = this.isMenuOffScreen(coordinates, menuDimensions);
if (menuIsOffScreen.right) {
coordinates.right = windowWidth - coordinates.left;
coordinates.left = 'auto';
}
var parentHeight = this.tribute.menuContainer ? this.tribute.menuContainer.offsetHeight : this.getDocument().body.offsetHeight;
if (menuIsOffScreen.bottom) {
var parentRect = this.tribute.menuContainer ? this.tribute.menuContainer.getBoundingClientRect() : this.getDocument().body.getBoundingClientRect();
var scrollStillAvailable = parentHeight - (windowHeight - parentRect.top);
coordinates.bottom = scrollStillAvailable + (windowHeight - rect.top - span.offsetTop);
coordinates.top = 'auto';
}
menuIsOffScreen = this.isMenuOffScreen(coordinates, menuDimensions);
if (menuIsOffScreen.left) {
coordinates.left = windowWidth > menuDimensions.width ? windowLeft + windowWidth - menuDimensions.width : windowLeft;
delete coordinates.right;
}
if (menuIsOffScreen.top) {
coordinates.top = windowHeight > menuDimensions.height ? windowTop + windowHeight - menuDimensions.height : windowTop;
delete coordinates.bottom;
}
this.getDocument().body.removeChild(div);
return coordinates;
}
}, {
key: 'getContentEditableCaretPosition',
value: function getContentEditableCaretPosition(selectedNodePosition) {
var markerTextChar = '';
var markerEl = void 0,
markerId = 'sel_' + new Date().getTime() + '_' + Math.random().toString().substr(2);
var range = void 0;
var sel = this.getWindowSelection();
var prevRange = sel.getRangeAt(0);
range = this.getDocument().createRange();
range.setStart(sel.anchorNode, selectedNodePosition);
range.setEnd(sel.anchorNode, selectedNodePosition);
range.collapse(false);
// Create the marker element containing a single invisible character using DOM methods and insert it
markerEl = this.getDocument().createElement('span');
markerEl.id = markerId;
markerEl.appendChild(this.getDocument().createTextNode(markerTextChar));
range.insertNode(markerEl);
sel.removeAllRanges();
sel.addRange(prevRange);
var rect = markerEl.getBoundingClientRect();
var doc = document.documentElement;
var windowLeft = (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0);
var windowTop = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
var coordinates = {
left: rect.left + windowLeft,
top: rect.top + markerEl.offsetHeight + windowTop
};
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
var menuDimensions = this.getMenuDimensions();
var menuIsOffScreen = this.isMenuOffScreen(coordinates, menuDimensions);
if (menuIsOffScreen.right) {
coordinates.left = 'auto';
coordinates.right = windowWidth - rect.left - windowLeft;
}
var parentHeight = this.tribute.menuContainer ? this.tribute.menuContainer.offsetHeight : this.getDocument().body.offsetHeight;
if (menuIsOffScreen.bottom) {
var parentRect = this.tribute.menuContainer ? this.tribute.menuContainer.getBoundingClientRect() : this.getDocument().body.getBoundingClientRect();
var scrollStillAvailable = parentHeight - (windowHeight - parentRect.top);
coordinates.top = 'auto';
coordinates.bottom = scrollStillAvailable + (windowHeight - rect.top);
}
menuIsOffScreen = this.isMenuOffScreen(coordinates, menuDimensions);
if (menuIsOffScreen.left) {
coordinates.left = windowWidth > menuDimensions.width ? windowLeft + windowWidth - menuDimensions.width : windowLeft;
delete coordinates.right;
}
if (menuIsOffScreen.top) {
coordinates.top = windowHeight > menuDimensions.height ? windowTop + windowHeight - menuDimensions.height : windowTop;
delete coordinates.bottom;
}
markerEl.parentNode.removeChild(markerEl);
return coordinates;
}
}, {
key: 'scrollIntoView',
value: function scrollIntoView(elem) {
var reasonableBuffer = 20,
clientRect = void 0;
var maxScrollDisplacement = 100;
var e = this.menu;
if (typeof e === 'undefined') return;
while (clientRect === undefined || clientRect.height === 0) {
clientRect = e.getBoundingClientRect();
if (clientRect.height === 0) {
e = e.childNodes[0];
if (e === undefined || !e.getBoundingClientRect) {
return;
}
}
}
var elemTop = clientRect.top;
var elemBottom = elemTop + clientRect.height;
if (elemTop < 0) {
window.scrollTo(0, window.pageYOffset + clientRect.top - reasonableBuffer);
} else if (elemBottom > window.innerHeight) {
var maxY = window.pageYOffset + clientRect.top - reasonableBuffer;
if (maxY - window.pageYOffset > maxScrollDisplacement) {
maxY = window.pageYOffset + maxScrollDisplacement;
}
var targetY = window.pageYOffset - (window.innerHeight - elemBottom);
if (targetY > maxY) {
targetY = maxY;
}
window.scrollTo(0, targetY);
}
}
}]);
return TributeRange;
}();
exports.default = TributeRange;
module.exports = exports['default'];
},{}],5:[function(require,module,exports){
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
// Thanks to https://github.com/mattyork/fuzzy
var TributeSearch = function () {
function TributeSearch(tribute) {
_classCallCheck(this, TributeSearch);
this.tribute = tribute;
this.tribute.search = this;
}
_createClass(TributeSearch, [{
key: 'simpleFilter',
value: function simpleFilter(pattern, array) {
var _this = this;
return array.filter(function (string) {
return _this.test(pattern, string);
});
}
}, {
key: 'test',
value: function test(pattern, string) {
return this.match(pattern, string) !== null;
}
}, {
key: 'match',
value: function match(pattern, string, opts) {
opts = opts || {};
var len = string.length,
pre = opts.pre || '',
post = opts.post || '',
compareString = opts.caseSensitive && string || string.toLowerCase();
pattern = opts.caseSensitive && pattern || pattern.toLowerCase();
var patternCache = this.traverse(compareString, pattern, 0, 0, []);
if (!patternCache) {
return null;
}
return {
rendered: this.render(string, patternCache.cache, pre, post),
score: patternCache.score
};
}
}, {
key: 'traverse',
value: function traverse(string, pattern, stringIndex, patternIndex, patternCache) {
// if the pattern search at end
if (pattern.length === patternIndex) {
// calculate score and copy the cache containing the indices where it's found
return {
score: this.calculateScore(patternCache),
cache: patternCache.slice()
};
}
// if string at end or remaining pattern > remaining string
if (string.length === stringIndex || pattern.length - patternIndex > string.length - stringIndex) {
return undefined;
}
var c = pattern[patternIndex];
var index = string.indexOf(c, stringIndex);
var best = void 0,
temp = void 0;
while (index > -1) {
patternCache.push(index);
temp = this.traverse(string, pattern, index + 1, patternIndex + 1, patternCache);
patternCache.pop();
// if downstream traversal failed, return best answer so far
if (!temp) {
return best;
}
if (!best || best.score < temp.score) {
best = temp;
}
index = string.indexOf(c, index + 1);
}
return best;
}
}, {
key: 'calculateScore',
value: function calculateScore(patternCache) {
var score = 0;
var temp = 1;
patternCache.forEach(function (index, i) {
if (i > 0) {
if (patternCache[i - 1] + 1 === index) {
temp += temp + 1;
} else {
temp = 1;
}
}
score += temp;
});
return score;
}
}, {
key: 'render',
value: function render(string, indices, pre, post) {
var rendered = string.substring(0, indices[0]);
indices.forEach(function (index, i) {
rendered += pre + string[index] + post + string.substring(index + 1, indices[i + 1] ? indices[i + 1] : string.length);
});
return rendered;
}
}, {
key: 'filter',
value: function filter(pattern, arr, opts) {
var _this2 = this;
opts = opts || {};
return arr.reduce(function (prev, element, idx, arr) {
var str = element;
if (opts.extract) {
str = opts.extract(element);
if (!str) {
// take care of undefineds / nulls / etc.
str = '';
}
}
var rendered = _this2.match(pattern, str, opts);
if (rendered != null) {
prev[prev.length] = {
string: rendered.rendered,
score: rendered.score,
index: idx,
original: element
};
}
return prev;
}, []).sort(function (a, b) {
var compare = b.score - a.score;
if (compare) return compare;
return a.index - b.index;
});
}
}]);
return TributeSearch;
}();
exports.default = TributeSearch;
module.exports = exports['default'];
},{}],6:[function(require,module,exports){
Object.defineProperty(exports, "__esModule", {
value: true
});
var _Tribute = require("./Tribute");
var _Tribute2 = _interopRequireDefault(_Tribute);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
exports.default = _Tribute2.default; /**
* Tribute.js
* Native ES6 JavaScript @mention Plugin
**/
module.exports = exports["default"];
},{"./Tribute":1}],7:[function(require,module,exports){
if (!Array.prototype.find) {
Array.prototype.find = function (predicate) {
if (this === null) {
throw new TypeError('Array.prototype.find called on null or undefined');
}
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}
var list = Object(this);
var length = list.length >>> 0;
var thisArg = arguments[1];
var value;
for (var i = 0; i < length; i++) {
value = list[i];
if (predicate.call(thisArg, value, i, list)) {
return value;
}
}
return undefined;
};
}
if (window && typeof window.CustomEvent !== "function") {
var CustomEvent = function CustomEvent(event, params) {
params = params || {
bubbles: false,
cancelable: false,
detail: undefined
};
var evt = document.createEvent('CustomEvent');
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
return evt;
};
if (typeof window.Event !== 'undefined') {
CustomEvent.prototype = window.Event.prototype;
}
window.CustomEvent = CustomEvent;
}
},{}]},{},[6])(6)
});
});
var Tribute = unwrapExports(tribute);
var VueTribute = {
name: "vue-tribute",
props: {
options: {
type: Object,
required: true
}
},
mounted: function mounted() {
if (typeof Tribute === "undefined") {
throw new Error("[vue-tribute] cannot locate tributejs!");
}
var $el = this.$slots.default[0].elm;
this.tribute = new Tribute(this.options);
this.tribute.attach($el);
},
beforeDestroy: function beforeDestroy() {
var $el = this.$slots.default[0].elm;
if (this.tribute) {
this.tribute.detach($el);
}
},
render: function render(h) {
return h("div", {
staticClass: "v-tribute"
}, this.$slots.default);
}
};
if (typeof window !== "undefined" && window.Vue) {
window.Vue.component(VueTribute.name, VueTribute);
}
return VueTribute;
})));