diff --git a/Sources/Actions/Credits.php b/Sources/Actions/Credits.php index 7c7f45b6ab..f69191d7ef 100644 --- a/Sources/Actions/Credits.php +++ b/Sources/Actions/Credits.php @@ -332,7 +332,7 @@ public function execute(): void 'animaDrag | © Abel Mohler | Licensed under The MIT License (MIT)', 'jQuery Custom Scrollbar | © Maciej Zubala | Licensed under The MIT License (MIT)', 'jQuery Responsive Slider | © booncon ROCKETS | Licensed under The MIT License (MIT)', - 'At.js | © chord.luo@gmail.com | Licensed under The MIT License (MIT)', + 'Tribute | © Matt York and contributors | Licensed under The MIT License (MIT)', 'HTML5 Desktop Notifications | © Tsvetan Tsvetkov | Licensed under The Apache License Version 2.0', 'GAuth Code Generator/Validator | © Chris Cornutt | Licensed under The MIT License (MIT)', 'Dropzone.js | © Matias Meno | Licensed under The MIT License (MIT)', diff --git a/Sources/Actions/Display.php b/Sources/Actions/Display.php index c234039183..b835545f1d 100644 --- a/Sources/Actions/Display.php +++ b/Sources/Actions/Display.php @@ -1041,8 +1041,8 @@ protected function setupTemplate(): void // Mentions if (!empty(Config::$modSettings['enable_mentions']) && User::$me->allowedTo('mention')) { - Theme::loadJavaScriptFile('jquery.atwho.min.js', ['defer' => true], 'smf_atwho'); - Theme::loadJavaScriptFile('jquery.caret.min.js', ['defer' => true], 'smf_caret'); + Theme::loadCSSFile('tribute.css', ['minimize' => true], 'smf_tribute'); + Theme::loadJavaScriptFile('tribute.js', ['defer' => true, 'minimize' => true], 'smf_tribute'); Theme::loadJavaScriptFile('mentions.js', ['defer' => true, 'minimize' => true], 'smf_mentions'); } diff --git a/Sources/Actions/Post.php b/Sources/Actions/Post.php index 55f690b3c7..da602ab1bf 100644 --- a/Sources/Actions/Post.php +++ b/Sources/Actions/Post.php @@ -355,8 +355,8 @@ public function show(): void // Mentions if (!empty(Config::$modSettings['enable_mentions']) && User::$me->allowedTo('mention')) { - Theme::loadJavaScriptFile('jquery.caret.min.js', ['defer' => true], 'smf_caret'); - Theme::loadJavaScriptFile('jquery.atwho.min.js', ['defer' => true], 'smf_atwho'); + Theme::loadCSSFile('tribute.css', ['minimize' => true], 'smf_tribute'); + Theme::loadJavaScriptFile('tribute.js', ['defer' => true, 'minimize' => true], 'smf_tribute'); Theme::loadJavaScriptFile('mentions.js', ['defer' => true, 'minimize' => true], 'smf_mentions'); } diff --git a/Themes/default/css/index.css b/Themes/default/css/index.css index 3493cbb612..2115d5a4e3 100644 --- a/Themes/default/css/index.css +++ b/Themes/default/css/index.css @@ -3814,50 +3814,6 @@ p.information img { .topic_pages::after { content: " \00bb" } -/* Mentions */ -.atwho-view { - position: absolute; - top: 0; - left: 0; - display: none; - margin-top: 18px; - background: #fff; - border: 1px solid #ddd; - border-radius: 3px; - box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); - min-width: 120px; - z-index: 11110 !important; -} -.atwho-view .cur { - background: #3366ff; - color: #fff; -} -.atwho-view .cur small { - color: #fff; -} -.atwho-view strong { - color: #3366ff; -} -.atwho-view .cur strong { - color: #fff; - font-weight: bold; -} -.atwho-view ul { - list-style: none; - padding: 0; - margin: auto; -} -.atwho-view ul li { - display: block; - padding: 5px 10px; - border-bottom: 1px solid #ddd; - cursor: pointer; -} -.atwho-view small { - font-size: smaller; - color: #777; - font-weight: normal; -} /* On/Off Icons (User) */ .on, .off { display: inline-block; diff --git a/Themes/default/css/tribute.css b/Themes/default/css/tribute.css new file mode 100644 index 0000000000..3268c09aac --- /dev/null +++ b/Themes/default/css/tribute.css @@ -0,0 +1,32 @@ +.tribute-container { + position: absolute; + top: 0; + left: 0; + height: auto; + overflow: auto; + display: block; + z-index: 999999; +} +.tribute-container ul { + margin: 0; + margin-top: 2px; + padding: 0; + list-style: none; + background: #efefef; +} +.tribute-container li { + padding: 5px 5px; + cursor: pointer; +} +.tribute-container li.highlight { + background: #ddd; +} +.tribute-container li span { + font-weight: bold; +} +.tribute-container li.no-match { + cursor: default; +} +.tribute-container .menu-highlighted { + font-weight: bold; +} \ No newline at end of file diff --git a/Themes/default/scripts/jquery.atwho.min.js b/Themes/default/scripts/jquery.atwho.min.js deleted file mode 100644 index e5d9dfada3..0000000000 --- a/Themes/default/scripts/jquery.atwho.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):"object"==typeof exports?module.exports=b(require("jquery")):b(jQuery)}(this,function(a){var b,c,d,e,f,g,h,i,j,k=[].slice,l=function(a,b){function c(){this.constructor=a}for(var d in b)m.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},m={}.hasOwnProperty;c=function(){function a(a){this.currentFlag=null,this.controllers={},this.aliasMaps={},this.$inputor=$(a),this.setupRootElement(),this.listen()}return a.prototype.createContainer=function(a){var b;return null!=(b=this.$el)&&b.remove(),$(a.body).append(this.$el=$("
"))},a.prototype.setupRootElement=function(a,b){var c;if(null==b&&(b=!1),a)this.window=a.contentWindow,this.document=a.contentDocument||this.window.document,this.iframe=a;else{this.document=this.$inputor[0].ownerDocument,this.window=this.document.defaultView||this.document.parentWindow;try{this.iframe=this.window.frameElement}catch(d){if(c=d,this.iframe=null,$.fn.atwho.debug)throw new Error("iframe auto-discovery is failed.\nPlease use `setIframe` to set the target iframe manually.\n"+c)}}return this.createContainer((this.iframeAsRoot=b)?this.document:document)},a.prototype.controller=function(a){var b,c,d,e;if(this.aliasMaps[a])c=this.controllers[this.aliasMaps[a]];else{e=this.controllers;for(d in e)if(b=e[d],d===a){c=b;break}}return c?c:this.controllers[this.currentFlag]},a.prototype.setContextFor=function(a){return this.currentFlag=a,this},a.prototype.reg=function(a,b){var c,d;return d=(c=this.controllers)[a]||(c[a]=this.$inputor.is("[contentEditable]")?new f(this,a):new i(this,a)),b.alias&&(this.aliasMaps[b.alias]=a),d.init(b),this},a.prototype.listen=function(){return this.$inputor.on("compositionstart",function(a){return function(b){var c;return null!=(c=a.controller())&&c.view.hide(),a.isComposing=!0}}(this)).on("compositionend",function(a){return function(b){return a.isComposing=!1}}(this)).on("keyup.atwhoInner",function(a){return function(b){return a.onKeyup(b)}}(this)).on("keydown.atwhoInner",function(a){return function(b){return a.onKeydown(b)}}(this)).on("scroll.atwhoInner",function(a){return function(b){var c;return null!=(c=a.controller())?c.view.hide(b):void 0}}(this)).on("blur.atwhoInner",function(a){return function(b){var c;return(c=a.controller())?c.view.hide(b,c.getOpt("displayTimeout")):void 0}}(this)).on("click.atwhoInner",function(a){return function(b){return a.dispatch(b)}}(this))},a.prototype.shutdown=function(){var a,b,c;c=this.controllers;for(a in c)b=c[a],b.destroy(),delete this.controllers[a];return this.$inputor.off(".atwhoInner"),this.$el.remove()},a.prototype.dispatch=function(a){var b,c,d,e;d=this.controllers,e=[];for(b in d)c=d[b],e.push(c.lookUp(a));return e},a.prototype.onKeyup=function(a){var b;switch(a.keyCode){case g.ESC:a.preventDefault(),null!=(b=this.controller())&&b.view.hide();break;case g.DOWN:case g.UP:case g.CTRL:$.noop();break;case g.P:case g.N:a.ctrlKey||this.dispatch(a);break;default:this.dispatch(a)}},a.prototype.onKeydown=function(a){var b,c;if(c=null!=(b=this.controller())?b.view:void 0,c&&c.visible())switch(a.keyCode){case g.ESC:a.preventDefault(),c.hide(a);break;case g.UP:a.preventDefault(),c.prev();break;case g.DOWN:a.preventDefault(),c.next();break;case g.P:if(!a.ctrlKey)return;a.preventDefault(),c.prev();break;case g.N:if(!a.ctrlKey)return;a.preventDefault(),c.next();break;case g.TAB:case g.ENTER:case g.SPACE:if(!c.visible())return;if(!this.controller().getOpt("spaceSelectsMatch")&&a.keyCode===g.SPACE)return;c.highlighted()?(a.preventDefault(),c.choose(a)):c.hide(a);break;default:$.noop()}},a}(),d=function(){function a(a,b){this.app=a,this.at=b,this.$inputor=this.app.$inputor,this.id=this.$inputor[0].id||this.uid(),this.setting=null,this.query=null,this.pos=0,this.range=null,0===(this.$el=$("#atwho-ground-"+this.id,this.app.$el)).length&&this.app.$el.append(this.$el=$("
")),this.model=new h(this),this.view=new j(this)}return a.prototype.uid=function(){return(Math.random().toString(16)+"000000000").substr(2,8)+(new Date).getTime()},a.prototype.init=function(a){return this.setting=$.extend({},this.setting||$.fn.atwho["default"],a),this.view.init(),this.model.reload(this.setting.data)},a.prototype.destroy=function(){return this.trigger("beforeDestroy"),this.model.destroy(),this.view.destroy(),this.$el.remove()},a.prototype.callDefault=function(){var a,b,c;c=arguments[0],a=2<=arguments.length?k.call(arguments,1):[];try{return e[c].apply(this,a)}catch(d){return b=d,$.error(b+" Or maybe At.js doesn't have function "+c)}},a.prototype.trigger=function(a,b){var c,d;return null==b&&(b=[]),b.push(this),c=this.getOpt("alias"),d=c?a+"-"+c+".atwho":a+".atwho",this.$inputor.trigger(d,b)},a.prototype.callbacks=function(a){return this.getOpt("callbacks")[a]||e[a]},a.prototype.getOpt=function(a,b){var c;try{return this.setting[a]}catch(d){return c=d,null}},a.prototype.insertContentFor=function(a){var b,c;return c=this.getOpt("insertTpl"),b=$.extend({},a.data("item-data"),{"atwho-at":this.at}),this.callbacks("tplEval").call(this,c,b,"onInsert")},a.prototype.renderView=function(a){var b;return b=this.getOpt("searchKey"),a=this.callbacks("sorter").call(this,this.query.text,a.slice(0,1001),b),this.view.render(a.slice(0,this.getOpt("limit")))},a.arrayToDefaultHash=function(a){var b,c,d,e;if(!$.isArray(a))return a;for(e=[],b=0,d=a.length;d>b;b++)c=a[b],e.push($.isPlainObject(c)?c:{name:c});return e},a.prototype.lookUp=function(a){var b,c;if(b=this.catchQuery(a))return this.app.setContextFor(this.at),(c=this.getOpt("delay"))?this._delayLookUp(b,c):this._lookUp(b),b},a.prototype._delayLookUp=function(a,b){var c,d;return c=Date.now?Date.now():(new Date).getTime(),this.previousCallTime||(this.previousCallTime=c),d=b-(c-this.previousCallTime),d>0&&b>d?(this.previousCallTime=c,this._stopDelayedCall(),this.delayedCallTimeout=setTimeout(function(b){return function(){return b.previousCallTime=0,b.delayedCallTimeout=null,b._lookUp(a)}}(this),b)):(this._stopDelayedCall(),this.previousCallTime!==c&&(this.previousCallTime=0),this._lookUp(a))},a.prototype._stopDelayedCall=function(){return this.delayedCallTimeout?(clearTimeout(this.delayedCallTimeout),this.delayedCallTimeout=null):void 0},a.prototype._lookUp=function(a){var b;return b=function(a){return a&&a.length>0?this.renderView(this.constructor.arrayToDefaultHash(a)):this.view.hide()},this.model.query(a.text,$.proxy(b,this))},a}(),i=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return l(b,a),b.prototype.catchQuery=function(){var a,b,c,d,e,f;return b=this.$inputor.val(),a=this.$inputor.caret("pos",{iframe:this.app.iframe}),f=b.slice(0,a),d=this.callbacks("matcher").call(this,this.at,f,this.getOpt("startWithSpace")),"string"==typeof d&&d.length<=this.getOpt("maxLen",20)?(e=a-d.length,c=e+d.length,this.pos=e,d={text:d,headPos:e,endPos:c},this.trigger("matched",[this.at,d.text])):(d=null,this.view.hide()),this.query=d},b.prototype.rect=function(){var a,b,c;if(a=this.$inputor.caret("offset",this.pos-1,{iframe:this.app.iframe}))return this.app.iframe&&!this.app.iframeAsRoot&&(b=$(this.app.iframe).offset(),a.left+=b.left,a.top+=b.top),c=this.app.document.selection?0:2,{left:a.left,top:a.top,bottom:a.top+a.height+c}},b.prototype.insert=function(a,b){var c,d,e,f,g;return c=this.$inputor,d=c.val(),e=d.slice(0,Math.max(this.query.headPos-this.at.length,0)),f=""===(f=this.getOpt("suffix"))?f:f||" ",a+=f,g=""+e+a+d.slice(this.query.endPos||0),c.val(g),c.caret("pos",e.length+a.length,{iframe:this.app.iframe}),c.is(":focus")||c.focus(),c.change()},b}(d),f=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return l(b,a),b.prototype._getRange=function(){var a;return a=this.app.window.getSelection(),a.rangeCount>0?a.getRangeAt(0):void 0},b.prototype._setRange=function(a,b,c){return null==c&&(c=this._getRange()),c?(b=$(b)[0],"after"===a?(c.setEndAfter(b),c.setStartAfter(b)):(c.setEndBefore(b),c.setStartBefore(b)),c.collapse(!1),this._clearRange(c)):void 0},b.prototype._clearRange=function(a){var b;return null==a&&(a=this._getRange()),b=this.app.window.getSelection(),null==this.ctrl_a_pressed?(b.removeAllRanges(),b.addRange(a)):void 0},b.prototype._movingEvent=function(a){var b;return"click"===a.type||(b=a.which)===g.RIGHT||b===g.LEFT||b===g.UP||b===g.DOWN},b.prototype._unwrap=function(a){var b;return a=$(a).unwrap().get(0),(b=a.nextSibling)&&b.nodeValue&&(a.nodeValue+=b.nodeValue,$(b).remove()),a},b.prototype.catchQuery=function(a){var b,c,d,e,f,h,i,j,k,l;if(!this.app.isComposing&&(l=this._getRange())){if(a.which===g.CTRL?this.ctrl_pressed=!0:a.which===g.A?null==this.ctrl_pressed&&(this.ctrl_a_pressed=!0):(delete this.ctrl_a_pressed,delete this.ctrl_pressed),a.which===g.ENTER)return(c=$(l.startContainer).closest(".atwho-query")).contents().unwrap(),c.is(":empty")&&c.remove(),(c=$(".atwho-query",this.app.document)).text(c.text()).contents().last().unwrap(),void this._clearRange();if(/firefox/i.test(navigator.userAgent)){if($(l.startContainer).is(this.$inputor))return void this._clearRange();a.which===g.BACKSPACE&&l.startContainer.nodeType===document.ELEMENT_NODE&&(j=l.startOffset-1)>=0?(d=l.cloneRange(),d.setStart(l.startContainer,j),$(d.cloneContents()).contents().last().is(".atwho-inserted")&&(f=$(l.startContainer).contents().get(j),this._setRange("after",$(f).contents().last()))):a.which===g.LEFT&&l.startContainer.nodeType===document.TEXT_NODE&&(b=$(l.startContainer.previousSibling),b.is(".atwho-inserted")&&0===l.startOffset&&this._setRange("after",b.contents().last()))}return $(l.startContainer).closest(".atwho-inserted").addClass("atwho-query").siblings().removeClass("atwho-query"),(c=$(".atwho-query",this.app.document)).length>0&&c.is(":empty")&&0===c.text().length&&c.remove(),this._movingEvent(a)||c.removeClass("atwho-inserted"),d=l.cloneRange(),d.setStart(l.startContainer,0),i=this.callbacks("matcher").call(this,this.at,d.toString(),this.getOpt("startWithSpace")),0===c.length&&"string"==typeof i&&(e=l.startOffset-this.at.length-i.length)>=0&&(l.setStart(l.startContainer,e),c=$("",this.app.document).attr(this.getOpt("editableAtwhoQueryAttrs")).addClass("atwho-query"),l.surroundContents(c.get(0)),h=c.contents().last().get(0),/firefox/i.test(navigator.userAgent)?(l.setStart(h,h.length),l.setEnd(h,h.length),this._clearRange(l)):this._setRange("after",h,l)),"string"==typeof i&&i.length<=this.getOpt("maxLen",20)?(k={text:i,el:c},this.trigger("matched",[this.at,k.text]),this.query=k):(this.view.hide(),this.query={el:c},c.text().indexOf(this.at)>=0&&(this._movingEvent(a)&&c.hasClass("atwho-inserted")?c.removeClass("atwho-query"):!1!==this.callbacks("afterMatchFailed").call(this,this.at,c)&&this._setRange("after",this._unwrap(c.text(c.text()).contents().first()))),null)}},b.prototype.rect=function(){var a,b,c;return c=this.query.el.offset(),this.app.iframe&&!this.app.iframeAsRoot&&(b=(a=$(this.app.iframe)).offset(),c.left+=b.left-this.$inputor.scrollLeft(),c.top+=b.top-this.$inputor.scrollTop()),c.bottom=c.top+this.query.el.height(),c},b.prototype.insert=function(a,b){var c,d,e;return d=(d=this.getOpt("suffix"))?d:d||" ",this.query.el.removeClass("atwho-query").addClass("atwho-inserted").html(a),(c=this._getRange())&&(c.setEndAfter(this.query.el[0]),c.collapse(!1),c.insertNode(e=this.app.document.createTextNode(d)),this._setRange("after",e,c)),this.$inputor.is(":focus")||this.$inputor.focus(),this.$inputor.change()},b}(d),h=function(){function a(a){this.context=a,this.at=this.context.at,this.storage=this.context.$inputor}return a.prototype.destroy=function(){return this.storage.data(this.at,null)},a.prototype.saved=function(){return this.fetch()>0},a.prototype.query=function(a,b){var c,d,e;return d=this.fetch(),e=this.context.getOpt("searchKey"),d=this.context.callbacks("filter").call(this.context,a,d,e)||[],c=this.context.callbacks("remoteFilter"),d.length>0||!c&&0===d.length?b(d):c.call(this.context,a,b)},a.prototype.fetch=function(){return this.storage.data(this.at)||[]},a.prototype.save=function(a){return this.storage.data(this.at,this.context.callbacks("beforeSave").call(this.context,a||[]))},a.prototype.load=function(a){return!this.saved()&&a?this._load(a):void 0},a.prototype.reload=function(a){return this._load(a)},a.prototype._load=function(a){return"string"==typeof a?$.ajax(a,{dataType:"json"}).done(function(a){return function(b){return a.save(b)}}(this)):this.save(a)},a}(),j=function(){function a(a){this.context=a,this.$el=$("
"),this.timeoutID=null,this.context.$el.append(this.$el),this.bindEvent()}return a.prototype.init=function(){var a;return a=this.context.getOpt("alias")||this.context.at.charCodeAt(0),this.$el.attr({id:"at-view-"+a})},a.prototype.destroy=function(){return this.$el.remove()},a.prototype.bindEvent=function(){var a;return a=this.$el.find("ul"),a.on("mouseenter.atwho-view","li",function(b){return a.find(".cur").removeClass("cur"),$(b.currentTarget).addClass("cur")}).on("click.atwho-view","li",function(b){return function(c){return a.find(".cur").removeClass("cur"),$(c.currentTarget).addClass("cur"),b.choose(c),c.preventDefault()}}(this))},a.prototype.visible=function(){return this.$el.is(":visible")},a.prototype.highlighted=function(){return this.$el.find(".cur").length>0},a.prototype.choose=function(a){var b,c;return(b=this.$el.find(".cur")).length&&(c=this.context.insertContentFor(b),this.context.insert(this.context.callbacks("beforeInsert").call(this.context,c,b),b),this.context.trigger("inserted",[b,a]),this.hide(a)),this.context.getOpt("hideWithoutSuffix")?this.stopShowing=!0:void 0},a.prototype.reposition=function(a){var b,c,d,e;return b=this.context.app.iframeAsRoot?this.context.app.window:window,a.bottom+this.$el.height()-$(b).scrollTop()>$(b).height()&&(a.bottom=a.top-this.$el.height()),a.left>(d=$(b).width()-this.$el.width()-5)&&(a.left=d),c={left:a.left,top:a.bottom},null!=(e=this.context.callbacks("beforeReposition"))&&e.call(this.context,c),this.$el.offset(c),this.context.trigger("reposition",[c])},a.prototype.next=function(){var a,b;return a=this.$el.find(".cur").removeClass("cur"),b=a.next(),b.length||(b=this.$el.find("li:first")),b.addClass("cur"),this.scrollTop(Math.max(0,a.innerHeight()*(b.index()+2)-this.$el.height()))},a.prototype.prev=function(){var a,b;return a=this.$el.find(".cur").removeClass("cur"),b=a.prev(),b.length||(b=this.$el.find("li:last")),b.addClass("cur"),this.scrollTop(Math.max(0,a.innerHeight()*(b.index()+2)-this.$el.height()))},a.prototype.scrollTop=function(a){var b;return b=this.context.getOpt("scrollDuration"),b?this.$el.animate({scrollTop:a},b):this.$el.scrollTop(a)},a.prototype.show=function(){var a;return this.stopShowing?void(this.stopShowing=!1):(this.visible()||(this.$el.show(),this.$el.scrollTop(0),this.context.trigger("shown")),(a=this.context.rect())?this.reposition(a):void 0)},a.prototype.hide=function(a,b){var c;if(this.visible())return isNaN(b)?(this.$el.hide(),this.context.trigger("hidden",[a])):(c=function(a){return function(){return a.hide()}}(this),clearTimeout(this.timeoutID),this.timeoutID=setTimeout(c,b))},a.prototype.render=function(a){var b,c,d,e,f,g,h;if(!($.isArray(a)&&a.length>0))return void this.hide();for(this.$el.find("ul").empty(),c=this.$el.find("ul"),h=this.context.getOpt("displayTpl"),d=0,f=a.length;f>d;d++)e=a[d],e=$.extend({},e,{"atwho-at":this.context.at}),g=this.context.callbacks("tplEval").call(this.context,h,e,"onDisplay"),b=$(this.context.callbacks("highlighter").call(this.context,g,this.context.query.text)),b.data("item-data",e),c.append(b);return this.show(),this.context.getOpt("highlightFirst")?c.find("li:first").addClass("cur"):void 0},a}(),g={DOWN:40,UP:38,ESC:27,TAB:9,ENTER:13,CTRL:17,A:65,P:80,N:78,LEFT:37,UP:38,RIGHT:39,DOWN:40,BACKSPACE:8,SPACE:32},e={beforeSave:function(a){return d.arrayToDefaultHash(a)},matcher:function(a,b,c,d){var e,f,g,h,i;return a=a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&"),c&&(a="(?:^|\\s)"+a),e=decodeURI("%C3%80"),f=decodeURI("%C3%BF"),i=d?" ":"",h=new RegExp(a+"([A-Za-z"+e+"-"+f+"0-9_"+i+".+-]*)$|"+a+"([^\\x00-\\xff]*)$","gi"),g=h.exec(b),g?g[2]||g[1]:null},filter:function(a,b,c){var d,e,f,g;for(d=[],e=0,g=b.length;g>e;e++)f=b[e],~new String(f[c]).toLowerCase().indexOf(a.toLowerCase())&&d.push(f);return d},remoteFilter:null,sorter:function(a,b,c){var d,e,f,g;if(!a)return b;for(d=[],e=0,g=b.length;g>e;e++)f=b[e],f.atwho_order=new String(f[c]).toLowerCase().indexOf(a.toLowerCase()),f.atwho_order>-1&&d.push(f);return d.sort(function(a,b){return a.atwho_order-b.atwho_order})},tplEval:function(a,b){var c,d;d=a;try{return"string"!=typeof a&&(d=a(b)),d.replace(/\$\{([^\}]*)\}/g,function(a,c,d){return b[c]})}catch(e){return c=e,""}},highlighter:function(a,b){var c;return b?(c=new RegExp(">\\s*(\\w*?)("+b.replace("+","\\+")+")(\\w*)\\s*<","ig"),a.replace(c,function(a,b,c,d){return"> "+b+""+c+""+d+" <"})):a},beforeInsert:function(a,b){return a},beforeReposition:function(a){return a},afterMatchFailed:function(a,b){}},b={load:function(a,b){var c;return(c=this.controller(a))?c.model.load(b):void 0},isSelecting:function(){var a;return null!=(a=this.controller())?a.view.visible():void 0},hide:function(){var a;return null!=(a=this.controller())?a.view.hide():void 0},reposition:function(){var a;return(a=this.controller())?(a.view.reposition(a.rect()),console.log("reposition",a)):void 0},setIframe:function(a,b){return this.setupRootElement(a,b),null},run:function(){return this.dispatch()},destroy:function(){return this.shutdown(),this.$inputor.data("atwho",null)}},$.fn.atwho=function(a){var d,e;return d=arguments,e=null,this.filter('textarea, input, [contenteditable=""], [contenteditable=true]').each(function(){var f,g;return(g=(f=$(this)).data("atwho"))||f.data("atwho",g=new c(this)),"object"!=typeof a&&a?b[a]&&g?e=b[a].apply(g,Array.prototype.slice.call(d,1)):$.error("Method "+a+" does not exist on jQuery.atwho"):g.reg(a.at,a)}),e||this},$.fn.atwho["default"]={at:void 0,alias:void 0,data:null,displayTpl:"
  • ${name}
  • ",insertTpl:"${atwho-at}${name}",callbacks:e,searchKey:"name",suffix:void 0,hideWithoutSuffix:!1,startWithSpace:!0,highlightFirst:!0,limit:5,maxLen:20,displayTimeout:300,delay:null,spaceSelectsMatch:!1,editableAtwhoQueryAttrs:{},scrollDuration:150},$.fn.atwho.debug=!1}); \ No newline at end of file diff --git a/Themes/default/scripts/jquery.caret.min.js b/Themes/default/scripts/jquery.caret.min.js deleted file mode 100644 index a4d02eae24..0000000000 --- a/Themes/default/scripts/jquery.caret.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jquery.caret 2015-02-01 */ -!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(c){return a.returnExportsGlobal=b(c)}):"object"==typeof exports?module.exports=b(require("jquery")):b(jQuery)}(this,function(a){"use strict";var b,c,d,e,f,g,h,i,j,k,l;k="caret",b=function(){function b(a){this.$inputor=a,this.domInputor=this.$inputor[0]}return b.prototype.setPos=function(){return this.domInputor},b.prototype.getIEPosition=function(){return this.getPosition()},b.prototype.getPosition=function(){var a,b;return b=this.getOffset(),a=this.$inputor.offset(),b.left-=a.left,b.top-=a.top,b},b.prototype.getOldIEPos=function(){var a,b;return b=h.selection.createRange(),a=h.body.createTextRange(),a.moveToElementText(this.domInputor),a.setEndPoint("EndToEnd",b),a.text.length},b.prototype.getPos=function(){var a,b,c;return(c=this.range())?(a=c.cloneRange(),a.selectNodeContents(this.domInputor),a.setEnd(c.endContainer,c.endOffset),b=a.toString().length,a.detach(),b):h.selection?this.getOldIEPos():void 0},b.prototype.getOldIEOffset=function(){var a,b;return a=h.selection.createRange().duplicate(),a.moveStart("character",-1),b=a.getBoundingClientRect(),{height:b.bottom-b.top,left:b.left,top:b.top}},b.prototype.getOffset=function(){var b,c,d,e,f;return j.getSelection&&(d=this.range())?(d.endOffset-1>0&&d.endContainer===!this.domInputor&&(b=d.cloneRange(),b.setStart(d.endContainer,d.endOffset-1),b.setEnd(d.endContainer,d.endOffset),e=b.getBoundingClientRect(),c={height:e.height,left:e.left+e.width,top:e.top},b.detach()),c&&0!==(null!=c?c.height:void 0)||(b=d.cloneRange(),f=a(h.createTextNode("|")),b.insertNode(f[0]),b.selectNode(f[0]),e=b.getBoundingClientRect(),c={height:e.height,left:e.left,top:e.top},f.remove(),b.detach())):h.selection&&(c=this.getOldIEOffset()),c&&(c.top+=a(j).scrollTop(),c.left+=a(j).scrollLeft()),c},b.prototype.range=function(){var a;if(j.getSelection)return a=j.getSelection(),a.rangeCount>0?a.getRangeAt(0):null},b}(),c=function(){function b(a){this.$inputor=a,this.domInputor=this.$inputor[0]}return b.prototype.getIEPos=function(){var a,b,c,d,e,f,g;return b=this.domInputor,f=h.selection.createRange(),e=0,f&&f.parentElement()===b&&(d=b.value.replace(/\r\n/g,"\n"),c=d.length,g=b.createTextRange(),g.moveToBookmark(f.getBookmark()),a=b.createTextRange(),a.collapse(!1),e=g.compareEndPoints("StartToEnd",a)>-1?c:-g.moveStart("character",-c)),e},b.prototype.getPos=function(){return h.selection?this.getIEPos():this.domInputor.selectionStart},b.prototype.setPos=function(a){var b,c;return b=this.domInputor,h.selection?(c=b.createTextRange(),c.move("character",a),c.select()):b.setSelectionRange&&b.setSelectionRange(a,a),b},b.prototype.getIEOffset=function(a){var b,c,d,e;return c=this.domInputor.createTextRange(),a||(a=this.getPos()),c.move("character",a),d=c.boundingLeft,e=c.boundingTop,b=c.boundingHeight,{left:d,top:e,height:b}},b.prototype.getOffset=function(b){var c,d,e;return c=this.$inputor,h.selection?(d=this.getIEOffset(b),d.top+=a(j).scrollTop()+c.scrollTop(),d.left+=a(j).scrollLeft()+c.scrollLeft(),d):(d=c.offset(),e=this.getPosition(b),d={left:d.left+e.left-c.scrollLeft(),top:d.top+e.top-c.scrollTop(),height:e.height})},b.prototype.getPosition=function(a){var b,c,e,f,g,h,i;return b=this.$inputor,f=function(a){return a=a.replace(/<|>|`|"|&/g,"?").replace(/\r\n|\r|\n/g,"
    "),/firefox/i.test(navigator.userAgent)&&(a=a.replace(/\s/g," ")),a},void 0===a&&(a=this.getPos()),i=b.val().slice(0,a),e=b.val().slice(a),g=""+f(i)+"",g+="|",g+=""+f(e)+"",h=new d(b),c=h.create(g).rect()},b.prototype.getIEPosition=function(a){var b,c,d,e,f;return d=this.getIEOffset(a),c=this.$inputor.offset(),e=d.left-c.left,f=d.top-c.top,b=d.height,{left:e,top:f,height:b}},b}(),d=function(){function b(a){this.$inputor=a}return b.prototype.css_attr=["borderBottomWidth","borderLeftWidth","borderRightWidth","borderTopStyle","borderRightStyle","borderBottomStyle","borderLeftStyle","borderTopWidth","boxSizing","fontFamily","fontSize","fontWeight","height","letterSpacing","lineHeight","marginBottom","marginLeft","marginRight","marginTop","outlineWidth","overflow","overflowX","overflowY","paddingBottom","paddingLeft","paddingRight","paddingTop","textAlign","textOverflow","textTransform","whiteSpace","wordBreak","wordWrap"],b.prototype.mirrorCss=function(){var b,c=this;return b={position:"absolute",left:-9999,top:0,zIndex:-2e4},"TEXTAREA"===this.$inputor.prop("tagName")&&this.css_attr.push("width"),a.each(this.css_attr,function(a,d){return b[d]=c.$inputor.css(d)}),b},b.prototype.create=function(b){return this.$mirror=a("
    "),this.$mirror.css(this.mirrorCss()),this.$mirror.html(b),this.$inputor.after(this.$mirror),this},b.prototype.rect=function(){var a,b,c;return a=this.$mirror.find("#caret"),b=a.position(),c={left:b.left,top:b.top,height:a.height()},this.$mirror.remove(),c},b}(),e={contentEditable:function(a){return!(!a[0].contentEditable||"true"!==a[0].contentEditable)}},g={pos:function(a){return a||0===a?this.setPos(a):this.getPos()},position:function(a){return h.selection?this.getIEPosition(a):this.getPosition(a)},offset:function(a){var b;return b=this.getOffset(a)}},h=null,j=null,i=null,l=function(a){var b;return(b=null!=a?a.iframe:void 0)?(i=b,j=b.contentWindow,h=b.contentDocument||j.document):(i=void 0,j=window,h=document)},f=function(a){var b;h=a[0].ownerDocument,j=h.defaultView||h.parentWindow;try{return i=j.frameElement}catch(c){b=c}},a.fn.caret=function(d,f,h){var i;return g[d]?(a.isPlainObject(f)?(l(f),f=void 0):l(h),i=e.contentEditable(this)?new b(this):new c(this),g[d].apply(i,[f])):a.error("Method "+d+" does not exist on jQuery.caret")},a.fn.caret.EditableCaret=b,a.fn.caret.InputCaret=c,a.fn.caret.Utils=e,a.fn.caret.apis=g}); \ No newline at end of file diff --git a/Themes/default/scripts/jquery.sceditor.smf.js b/Themes/default/scripts/jquery.sceditor.smf.js index 6d6e7e73a6..e6f95c426a 100644 --- a/Themes/default/scripts/jquery.sceditor.smf.js +++ b/Themes/default/scripts/jquery.sceditor.smf.js @@ -198,8 +198,16 @@ * Only resize the text areas instead. */ document.querySelector(".sceditor-container").removeAttribute("style"); - document.querySelector(".sceditor-container textarea").style.height = options.height; - document.querySelector(".sceditor-container textarea").style.flexBasis = options.height; + + const textarea = document.querySelector('.sceditor-container textarea'); + textarea.style.height = options.height; + textarea.style.flexBasis = options.height; + + // Add Tribute.js + if (typeof tribute === 'object') { + tribute.attach(textarea); + tribute.attach(instance.getBody()); + } isPatched = true; } diff --git a/Themes/default/scripts/mentions.js b/Themes/default/scripts/mentions.js index 7ca21fd2e5..e7df1b0641 100644 --- a/Themes/default/scripts/mentions.js +++ b/Themes/default/scripts/mentions.js @@ -1,56 +1,40 @@ -var fails = []; +const tributeRemoteSearch = (query, callback) => { + const URL = smf_scripturl + '?action=suggest;' + smf_session_var + '=' + smf_session_id + ';xml'; -var atwhoConfig = { - at: '@', - data: [], - show_the_at: true, - startWithSpace: true, - limit: 10, - callbacks: { - remoteFilter: function (query, callback) { - if (typeof query == 'undefined' || query.length < 2 || query.length > 60) - return; + xhr = new XMLHttpRequest(); + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + if (xhr.status === 200) { + const xmlDoc = xhr.responseXML; + const items = xmlDoc.getElementsByTagName('item'); + const users = []; - for (i in fails) - if (query.substr(0, fails[i].length) == fails[i]) - return; + for (let i = 0; i < items.length; i++) { + users.push({ key: items[i].id, value: items[i].textContent }); + } - $.ajax({ - url: smf_scripturl + '?action=suggest;' + smf_session_var + '=' + smf_session_id + ';xml', - method: 'GET', - headers: { - "X-SMF-AJAX": 1 - }, - xhrFields: { - withCredentials: typeof allow_xhjr_credentials !== "undefined" ? allow_xhjr_credentials : false - }, - data: { - search: query, - suggest_type: 'member' - }, - success: function (data) { - var members = $(data).find('smf > items > item'); - if (members.length == 0) - fails[fails.length] = query; - - var callbackArray = []; - $.each(members, function (index, item) { - callbackArray[callbackArray.length] = { - name: $(item).text() - }; - }); + callback(users); + } else if (xhr.status === 403) { + callback([]); + } + } + }; + xhr.open('GET', URL + ';suggest_type=member;search=' + query, true); + xhr.setRequestHeader('X-SMF-AJAX', '1'); + xhr.withCredentials = + typeof allow_xhjr_credentials !== 'undefined' ? allow_xhjr_credentials : false; + xhr.send(); +}; - callback(callbackArray); - } - }); - } - } +const tributeConfig = { + values: function (query, callback) { + tributeRemoteSearch(query, (users) => callback(users)); + }, + lookup: 'value', + menuItemLimit: 10, + noMatchTemplate: function () { + return ''; + }, }; -$(function() -{ - $('textarea[name=message]').atwho(atwhoConfig); - $('.sceditor-container').find('textarea').atwho(atwhoConfig); - var iframe = $('.sceditor-container').find('iframe')[0]; - if (typeof iframe != 'undefined') - $(iframe.contentDocument.body).atwho(atwhoConfig); -}); \ No newline at end of file + +const tribute = new Tribute(tributeConfig); diff --git a/Themes/default/scripts/tribute.js b/Themes/default/scripts/tribute.js new file mode 100644 index 0000000000..fc7b4c017c --- /dev/null +++ b/Themes/default/scripts/tribute.js @@ -0,0 +1,1781 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, global.Tribute = factory()); +}(this, (function () { 'use strict'; + + function _iterableToArrayLimit(r, l) { + var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; + if (null != t) { + var e, + n, + i, + u, + a = [], + f = !0, + o = !1; + try { + if (i = (t = t.call(r)).next, 0 === l) { + if (Object(t) !== t) return; + f = !1; + } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); + } catch (r) { + o = !0, n = r; + } finally { + try { + if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; + } finally { + if (o) throw n; + } + } + return a; + } + } + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a 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, _toPropertyKey(descriptor.key), descriptor); + } + } + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + Object.defineProperty(Constructor, "prototype", { + writable: false + }); + return Constructor; + } + function _slicedToArray(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); + } + function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; + } + function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); + } + function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + return arr2; + } + function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); + } + function _toPrimitive(input, hint) { + if (typeof input !== "object" || input === null) return input; + var prim = input[Symbol.toPrimitive]; + if (prim !== undefined) { + var res = prim.call(input, hint || "default"); + if (typeof res !== "object") return res; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + return (hint === "string" ? String : Number)(input); + } + function _toPropertyKey(arg) { + var key = _toPrimitive(arg, "string"); + return typeof key === "symbol" ? key : String(key); + } + + if (!Array.prototype.find) { + Object.defineProperty(Array.prototype, 'find', { + value: function value(predicate) { + // 1. Let O be ? ToObject(this value). + if (this == null) { + throw TypeError('"this" is null or not defined'); + } + var o = Object(this); + + // 2. Let len be ? ToLength(? Get(O, "length")). + var len = o.length >>> 0; + + // 3. If IsCallable(predicate) is false, throw a TypeError exception. + if (typeof predicate !== 'function') { + throw TypeError('predicate must be a function'); + } + + // 4. If thisArg was supplied, let T be thisArg; else let T be undefined. + var thisArg = arguments[1]; + + // 5. Let k be 0. + var k = 0; + + // 6. Repeat, while k < len + while (k < len) { + // a. Let Pk be ! ToString(k). + // b. Let kValue be ? Get(O, Pk). + // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)). + // d. If testResult is true, return kValue. + var kValue = o[k]; + if (predicate.call(thisArg, kValue, k, o)) { + return kValue; + } + // e. Increase k by 1. + k++; + } + + // 7. Return undefined. + return undefined; + }, + configurable: true, + writable: true + }); + } + if (typeof window !== 'undefined' && typeof window.CustomEvent !== "function") { + var CustomEvent$1 = 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$1.prototype = window.Event.prototype; + } + window.CustomEvent = CustomEvent$1; + } + + var TributeEvents = /*#__PURE__*/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, true); + element.addEventListener("keyup", element.boundKeyup, true); + element.addEventListener("input", element.boundInput, true); + } + }, { + key: "unbind", + value: function unbind(element) { + element.removeEventListener("keydown", element.boundKeydown, true); + element.removeEventListener("keyup", element.boundKeyup, true); + element.removeEventListener("input", element.boundInput, true); + 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) { + // When li === tribute.menu, it's either a click on the entire component or on the scrollbar (if visible) + li = undefined; + break; + } + } + if (!li) { + return; + } + if (tribute.current.filteredItems.length === 0) li.setAttribute("data-index", -1); + if (li.getAttribute("data-disabled") === "true") return; + tribute.selectItemAtIndex(li.getAttribute("data-index"), event); + tribute.hideMenu(); + + // TODO: should fire with externalTrigger and target is outside of menu + } else if (tribute.current.externalTrigger) { + tribute.current.externalTrigger = false; + } else if (tribute.current.element && !tribute.current.externalTrigger) { + setTimeout(function () { + return tribute.hideMenu(); + }); + } + } + }, { + key: "keyup", + value: function keyup(instance, event) { + if (instance.inputEvent) { + instance.inputEvent = false; + } + instance.updateSelection(this); + if (!event.keyCode || 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) { + if (instance.tribute.autocompleteMode) { + instance.callbacks().triggerChar(event, this, ""); + } else { + 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.mentionText.length < instance.tribute.current.collection.menuShowMinLength) { + instance.tribute.hideMenu(); + return; + } + if ((instance.tribute.current.trigger || instance.tribute.autocompleteMode) && 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, tribute.autocompleteMode); + 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, this.tribute.autocompleteMode); + 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.current.mentionText.length >= tribute.current.collection.menuShowMinLength && tribute.inputEvent) { + tribute.showMenuFor(el, true); + } + }, + enter: function enter(e, el) { + // choose selection + var filteredItems = _this.tribute.current.filteredItems; + if (_this.tribute.isActive && filteredItems && filteredItems.length) { + e.preventDefault(); + e.stopPropagation(); + if (_this.tribute.current.filteredItems.length === 0) _this.tribute.menuSelected = -1; + 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 && _this.tribute.current.filteredItems) { + e.preventDefault(); + e.stopPropagation(); + var count = _this.tribute.current.filteredItems.length; + var lis = _this.tribute.menu.querySelectorAll("li"); + + //If menuSelected is -1 then there are no valid, non-disabled items + //to navigate through + if (_this.tribute.menuSelected === -1) { + return; + } + do { + _this.tribute.menuSelected--; + if (_this.tribute.menuSelected === -1) { + _this.tribute.menuSelected = count - 1; + _this.tribute.menu.scrollTop = _this.tribute.menu.scrollHeight; + } + } while (lis[_this.tribute.menuSelected].getAttribute("data-disabled") === "true"); + _this.setActiveLi(); + } + }, + down: function down(e, el) { + // navigate down ul + if (_this.tribute.isActive && _this.tribute.current.filteredItems) { + e.preventDefault(); + e.stopPropagation(); + var count = _this.tribute.current.filteredItems.length; + var lis = _this.tribute.menu.querySelectorAll("li"); + + //If menuSelected is -1 then there are no valid, non-disabled items + //to navigate through + if (_this.tribute.menuSelected === -1) { + return; + } + do { + _this.tribute.menuSelected++; + if (_this.tribute.menuSelected >= count) { + _this.tribute.menuSelected = 0; + _this.tribute.menu.scrollTop = 0; + } + } while (lis[_this.tribute.menuSelected].getAttribute("data-disabled") === "true"); + _this.setActiveLi(); + } + }, + "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; + if (index) this.tribute.menuSelected = parseInt(index); + for (var i = 0; i < length; i++) { + var li = lis[i]; + if (i === this.tribute.menuSelected) { + if (li.getAttribute("data-disabled") !== "true") { + li.classList.add(this.tribute.current.collection.selectClass); + } + var liClientRect = li.getBoundingClientRect(); + var menuClientRect = this.tribute.menu.getBoundingClientRect(); + if (liClientRect.bottom > menuClientRect.bottom) { + var scrollDistance = liClientRect.bottom - menuClientRect.bottom; + this.tribute.menu.scrollTop += scrollDistance; + } else if (liClientRect.top < menuClientRect.top) { + var _scrollDistance = menuClientRect.top - liClientRect.top; + this.tribute.menu.scrollTop -= _scrollDistance; + } + } else { + li.classList.remove(this.tribute.current.collection.selectClass); + } + } + } + }, { + 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; + }(); + + var TributeMenuEvents = /*#__PURE__*/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.hideMenu(); + } + }, 10, false); + this.windowResizeEvent = this.debounce(function () { + if (_this.tribute.isActive) { + _this.tribute.hideMenu(); + } + }, 10, false); + this.closeOnScrollEvent = this.debounce(function () { + if (_this.tribute.isActive) { + _this.tribute.hideMenu(); + } + }, 10, 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.tribute.closeOnScroll == true) { + window.addEventListener('scroll', this.closeOnScrollEvent); + } else if (this.tribute.closeOnScroll != false) { + this.tribute.closeOnScroll.addEventListener('scroll', this.closeOnScrollEvent, false); + } else { + 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.tribute.closeOnScroll === true) { + window.removeEventListener('scroll', this.closeOnScrollEvent); + } else if (this.tribute.closeOnScroll != false) { + this.tribute.closeOnScroll.removeEventListener('scroll', this.closeOnScrollEvent); + } else { + 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 _arguments = arguments, + _this2 = this; + 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; + }(); + + var TributeRange = /*#__PURE__*/function () { + function TributeRange(tribute) { + _classCallCheck(this, TributeRange); + this.tribute = tribute; + this.tribute.range = this; + } + _createClass(TributeRange, [{ + key: "getDocument", + value: function getDocument() { + var iframe; + 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 context = this.tribute.current, + coordinates; + var info = this.getTriggerInfo(false, this.tribute.hasTrailingSpace, true, this.tribute.allowSpaces, this.tribute.autocompleteMode); + 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: ".concat(coordinates.top, "px;\n left: ").concat(coordinates.left, "px;\n right: ").concat(coordinates.right, "px;\n bottom: ").concat(coordinates.bottom, "px;\n max-height: ").concat(coordinates.maxHeight || 500, "px;\n max-width: ").concat(coordinates.maxWidth || 300, "px;\n position: ").concat(coordinates.position || 'absolute', ";\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(); + } else { + this.tribute.menu.style.cssText = 'display: none'; + } + } + }, { + key: "menuContainerIsBody", + get: function get() { + return this.tribute.menuContainer === document.body || !this.tribute.menuContainer; + } + }, { + key: "selectElement", + value: function selectElement(targetElement, path, offset) { + var range; + 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 info = this.getTriggerInfo(true, hasTrailingSpace, requireLeadingSpace, this.tribute.allowSpaces, this.tribute.autocompleteMode); + if (info !== undefined) { + var context = this.tribute.current; + var replaceEvent = new CustomEvent('tribute-replaced', { + detail: { + item: item, + instance: context, + context: info, + event: originalEvent + } + }); + 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 === '' ? 1 : textSuffix.length); + if (!this.tribute.autocompleteMode) { + endPos += info.mentionTriggerChar.length - 1; + } + 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; + var _endPos = info.mentionPosition + info.mentionText.length; + if (!this.tribute.autocompleteMode) { + _endPos += info.mentionTriggerChar.length; + } + this.pasteHtml(text, info.mentionPosition, _endPos); + } + context.element.dispatchEvent(new CustomEvent('input', { + bubbles: true + })); + context.element.dispatchEvent(replaceEvent); + } + } + }, { + key: "pasteHtml", + value: function pasteHtml(html, startPos, endPos) { + var range, sel; + 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, + lastNode; + 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(); + } + if (this.tribute.collection[0].shadowRoot) { + return this.tribute.collection[0].shadowRoot.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; + if (selected != null) { + var i; + 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: "getLastWordInText", + value: function getLastWordInText(text) { + var wordsArray; + if (this.tribute.autocompleteMode) { + if (this.tribute.autocompleteSeparator) { + wordsArray = text.split(this.tribute.autocompleteSeparator); + } else { + wordsArray = [text]; + } + } else { + wordsArray = text.split(/\s+/); + } + var wordsCount = wordsArray.length - 1; + return wordsArray[wordsCount]; + } + }, { + key: "getTriggerInfo", + value: function getTriggerInfo(menuAlreadyActive, hasTrailingSpace, requireLeadingSpace, allowSpaces, isAutocomplete) { + var _this = this; + var ctx = this.tribute.current; + var selected, path, offset; + 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(); + var lastWordOfEffectiveRange = this.getLastWordInText(effectiveRange); + if (isAutocomplete) { + return { + mentionPosition: effectiveRange.length - lastWordOfEffectiveRange.length, + mentionText: lastWordOfEffectiveRange, + mentionSelectedElement: selected, + mentionSelectedPath: path, + mentionSelectedOffset: offset + }; + } + if (effectiveRange !== undefined && effectiveRange !== null) { + var mostRecentTriggerCharPos = -1; + var triggerChar; + this.tribute.collection.forEach(function (config) { + var c = config.trigger; + var idx = config.requireLeadingSpace ? _this.lastIndexWithLeadingSpace(effectiveRange, c) : effectiveRange.lastIndexOf(c); + if (idx > mostRecentTriggerCharPos) { + mostRecentTriggerCharPos = idx; + triggerChar = c; + requireLeadingSpace = config.requireLeadingSpace; + } + }); + if (mostRecentTriggerCharPos >= 0 && (mostRecentTriggerCharPos === 0 || !requireLeadingSpace || /\s/.test(effectiveRange.substring(mostRecentTriggerCharPos - 1, mostRecentTriggerCharPos)))) { + var currentTriggerSnippet = effectiveRange.substring(mostRecentTriggerCharPos + triggerChar.length, effectiveRange.length); + triggerChar = effectiveRange.substring(mostRecentTriggerCharPos, mostRecentTriggerCharPos + triggerChar.length); + 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, trigger) { + 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 = true; + for (var triggerIdx = trigger.length - 1; triggerIdx >= 0; triggerIdx--) { + if (trigger[triggerIdx] !== reversedStr[cidx - triggerIdx]) { + match = false; + break; + } + } + 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 display: block;\n visibility; hidden;\n max-height:500px;"; + 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', 'borderStyle', 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft', 'fontStyle', 'fontVariant', 'fontWeight', 'fontStretch', 'fontSize', 'fontSizeAdjust', 'lineHeight', 'fontFamily', 'textAlign', 'textTransform', 'textIndent', 'textDecoration', 'letterSpacing', 'wordSpacing']; + 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'; + } + style.position = 'absolute'; + style.visibility = 'hidden'; + + // transfer the element's properties to the div + properties.forEach(function (prop) { + style[prop] = computed[prop]; + }); + + //NOT SURE WHY THIS IS HERE AND IT DOESNT SEEM HELPFUL + // if (isFirefox) { + // style.width = `${(parseInt(computed.width) - 2)}px` + // if (element.scrollHeight > parseInt(computed.height)) + // style.overflowY = 'scroll' + // } else { + // style.overflow = 'hidden' + // } + + var span0 = document.createElement('span'); + span0.textContent = element.value.substring(0, position); + div.appendChild(span0); + if (element.nodeName === 'INPUT') { + div.textContent = div.textContent.replace(/\s/g, ' '); + } + + //Create a span in the div that represents where the cursor + //should be + var span = this.getDocument().createElement('span'); + //we give it no content as this represents the cursor + span.textContent = '​'; + div.appendChild(span); + var span2 = this.getDocument().createElement('span'); + span2.textContent = element.value.substring(position); + div.appendChild(span2); + var rect = element.getBoundingClientRect(); + + //position the div exactly over the element + //so we can get the bounding client rect for the span and + //it should represent exactly where the cursor is + div.style.position = 'fixed'; + div.style.left = rect.left + 'px'; + div.style.top = rect.top + 'px'; + div.style.width = rect.width + 'px'; + div.style.height = rect.height + 'px'; + div.scrollTop = element.scrollTop; + var spanRect = span.getBoundingClientRect(); + this.getDocument().body.removeChild(div); + return this.getFixedCoordinatesRelativeToRect(spanRect); + } + }, { + key: "getContentEditableCaretPosition", + value: function getContentEditableCaretPosition(selectedNodePosition) { + var range; + var sel = this.getWindowSelection(); + range = this.getDocument().createRange(); + range.setStart(sel.anchorNode, selectedNodePosition); + range.setEnd(sel.anchorNode, selectedNodePosition); + range.collapse(false); + var rect = range.getBoundingClientRect(); + return this.getFixedCoordinatesRelativeToRect(rect); + } + }, { + key: "getFixedCoordinatesRelativeToRect", + value: function getFixedCoordinatesRelativeToRect(rect) { + var coordinates = { + position: 'fixed', + left: rect.left, + top: rect.top + rect.height + }; + var menuDimensions = this.getMenuDimensions(); + var availableSpaceOnTop = rect.top; + var availableSpaceOnBottom = window.innerHeight - (rect.top + rect.height); + + //check to see where's the right place to put the menu vertically + if (availableSpaceOnBottom < menuDimensions.height) { + if (availableSpaceOnTop >= menuDimensions.height || availableSpaceOnTop > availableSpaceOnBottom) { + coordinates.top = 'auto'; + coordinates.bottom = window.innerHeight - rect.top; + if (availableSpaceOnBottom < menuDimensions.height) { + coordinates.maxHeight = availableSpaceOnTop; + } + } else { + if (availableSpaceOnTop < menuDimensions.height) { + coordinates.maxHeight = availableSpaceOnBottom; + } + } + } + var availableSpaceOnLeft = rect.left; + var availableSpaceOnRight = window.innerWidth - rect.left; + + //check to see where's the right place to put the menu horizontally + if (availableSpaceOnRight < menuDimensions.width) { + if (availableSpaceOnLeft >= menuDimensions.width || availableSpaceOnLeft > availableSpaceOnRight) { + coordinates.left = 'auto'; + coordinates.right = window.innerWidth - rect.left; + if (availableSpaceOnRight < menuDimensions.width) { + coordinates.maxWidth = availableSpaceOnLeft; + } + } else { + if (availableSpaceOnLeft < menuDimensions.width) { + coordinates.maxWidth = availableSpaceOnRight; + } + } + } + return coordinates; + } + }, { + key: "scrollIntoView", + value: function scrollIntoView(elem) { + var reasonableBuffer = 20, + clientRect; + 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; + }(); + + // Thanks to https://github.com/mattyork/fuzzy + var TributeSearch = /*#__PURE__*/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(); + if (opts.skip) { + return { + rendered: string, + score: 0 + }; + } + 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 (this.tribute.autocompleteSeparator) { + // if the pattern search at end + pattern = pattern.split(this.tribute.autocompleteSeparator).splice(-1)[0]; + } + 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, temp; + 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; + }(); + + var Tribute = /*#__PURE__*/function () { + function Tribute(_ref) { + var _this = this; + var _ref$values = _ref.values, + values = _ref$values === void 0 ? null : _ref$values, + _ref$loadingItemTempl = _ref.loadingItemTemplate, + loadingItemTemplate = _ref$loadingItemTempl === void 0 ? null : _ref$loadingItemTempl, + _ref$iframe = _ref.iframe, + iframe = _ref$iframe === void 0 ? null : _ref$iframe, + _ref$shadowRoot = _ref.shadowRoot, + shadowRoot = _ref$shadowRoot === void 0 ? null : _ref$shadowRoot, + _ref$selectClass = _ref.selectClass, + selectClass = _ref$selectClass === void 0 ? "highlight" : _ref$selectClass, + _ref$containerClass = _ref.containerClass, + containerClass = _ref$containerClass === void 0 ? "tribute-container" : _ref$containerClass, + _ref$itemClass = _ref.itemClass, + itemClass = _ref$itemClass === void 0 ? "" : _ref$itemClass, + _ref$trigger = _ref.trigger, + trigger = _ref$trigger === void 0 ? "@" : _ref$trigger, + _ref$autocompleteMode = _ref.autocompleteMode, + autocompleteMode = _ref$autocompleteMode === void 0 ? false : _ref$autocompleteMode, + _ref$autocompleteSepa = _ref.autocompleteSeparator, + autocompleteSeparator = _ref$autocompleteSepa === void 0 ? /\s+/ : _ref$autocompleteSepa, + _ref$selectTemplate = _ref.selectTemplate, + selectTemplate = _ref$selectTemplate === void 0 ? null : _ref$selectTemplate, + _ref$menuItemTemplate = _ref.menuItemTemplate, + menuItemTemplate = _ref$menuItemTemplate === void 0 ? null : _ref$menuItemTemplate, + _ref$lookup = _ref.lookup, + lookup = _ref$lookup === void 0 ? "key" : _ref$lookup, + _ref$fillAttr = _ref.fillAttr, + fillAttr = _ref$fillAttr === void 0 ? "value" : _ref$fillAttr, + _ref$collection = _ref.collection, + collection = _ref$collection === void 0 ? null : _ref$collection, + _ref$menuContainer = _ref.menuContainer, + menuContainer = _ref$menuContainer === void 0 ? null : _ref$menuContainer, + _ref$noMatchTemplate = _ref.noMatchTemplate, + noMatchTemplate = _ref$noMatchTemplate === void 0 ? null : _ref$noMatchTemplate, + _ref$requireLeadingSp = _ref.requireLeadingSpace, + requireLeadingSpace = _ref$requireLeadingSp === void 0 ? true : _ref$requireLeadingSp, + _ref$allowSpaces = _ref.allowSpaces, + allowSpaces = _ref$allowSpaces === void 0 ? false : _ref$allowSpaces, + _ref$replaceTextSuffi = _ref.replaceTextSuffix, + replaceTextSuffix = _ref$replaceTextSuffi === void 0 ? null : _ref$replaceTextSuffi, + _ref$positionMenu = _ref.positionMenu, + positionMenu = _ref$positionMenu === void 0 ? true : _ref$positionMenu, + _ref$spaceSelectsMatc = _ref.spaceSelectsMatch, + spaceSelectsMatch = _ref$spaceSelectsMatc === void 0 ? false : _ref$spaceSelectsMatc, + _ref$searchOpts = _ref.searchOpts, + searchOpts = _ref$searchOpts === void 0 ? {} : _ref$searchOpts, + _ref$menuItemLimit = _ref.menuItemLimit, + menuItemLimit = _ref$menuItemLimit === void 0 ? null : _ref$menuItemLimit, + _ref$menuShowMinLengt = _ref.menuShowMinLength, + menuShowMinLength = _ref$menuShowMinLengt === void 0 ? 0 : _ref$menuShowMinLengt, + _ref$closeOnScroll = _ref.closeOnScroll, + closeOnScroll = _ref$closeOnScroll === void 0 ? false : _ref$closeOnScroll, + _ref$maxDisplayItems = _ref.maxDisplayItems, + maxDisplayItems = _ref$maxDisplayItems === void 0 ? null : _ref$maxDisplayItems, + _ref$isBlocked = _ref.isBlocked, + isBlocked = _ref$isBlocked === void 0 ? false : _ref$isBlocked; + _classCallCheck(this, Tribute); + this.autocompleteMode = autocompleteMode; + this.autocompleteSeparator = autocompleteSeparator; + 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; + this.closeOnScroll = closeOnScroll; + if (this.autocompleteMode) { + trigger = ""; + allowSpaces = false; + } + if (values) { + this.collection = [{ + // symbol that starts the lookup + trigger: trigger, + // is it wrapped in an iframe + iframe: iframe, + // is it wrapped in a web component + shadowRoot: shadowRoot, + // class applied to selected item + selectClass: selectClass, + // class applied to the Container + containerClass: containerClass, + // class applied to each item + itemClass: itemClass, + // 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 === "string") { + if (t.trim() === "") return null; + return t; + } + if (typeof t === "function") { + return t.bind(_this); + } + return noMatchTemplate || function () { + return "
  • No Match Found!
  • "; + }.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, + // useful for when values is an async function + loadingItemTemplate: loadingItemTemplate, + requireLeadingSpace: requireLeadingSpace, + searchOpts: searchOpts, + menuItemLimit: menuItemLimit, + menuShowMinLength: menuShowMinLength, + // Fix for maximum number of items added to the input for the specific Collection + maxDisplayItems: maxDisplayItems, + isBlocked: isBlocked + }]; + } else if (collection) { + if (this.autocompleteMode) console.warn("Tribute in autocomplete mode does not work for collections"); + this.collection = collection.map(function (item) { + return { + trigger: item.trigger || trigger, + iframe: item.iframe || iframe, + shadowRoot: item.shadowRoot || shadowRoot, + selectClass: item.selectClass || selectClass, + containerClass: item.containerClass || containerClass, + itemClass: item.itemClass || itemClass, + 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 === "string") { + if (t.trim() === "") return null; + return t; + } + if (typeof t === "function") { + return t.bind(_this); + } + return noMatchTemplate || function () { + return "
  • No Match Found!
  • "; + }.bind(_this); + }(noMatchTemplate), + lookup: item.lookup || lookup, + fillAttr: item.fillAttr || fillAttr, + values: item.values, + loadingItemTemplate: item.loadingItemTemplate, + requireLeadingSpace: item.requireLeadingSpace, + searchOpts: item.searchOpts || searchOpts, + menuItemLimit: item.menuItemLimit || menuItemLimit, + menuShowMinLength: item.menuShowMinLength || menuShowMinLength, + // Set maximum number of items added to the input for the specific Collection + maxDisplayItems: item.maxDisplayItems || maxDisplayItems, + isBlocked: item.isBlocked || isBlocked + }; + }); + } else { + throw new Error("[Tribute] No collection specified."); + } + new TributeRange(this); + new TributeEvents(this); + new TributeMenuEvents(this); + new TributeSearch(this); + } + _createClass(Tribute, [{ + key: "isActive", + get: function get() { + return this._isActive; + }, + set: function set(val) { + if (this._isActive != val) { + this._isActive = val; + if (this.current.element) { + var noMatchEvent = new CustomEvent("tribute-active-".concat(val)); + this.current.element.dispatchEvent(noMatchEvent); + } + } + } + }, { + 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) { + throw new Error("[Tribute] Cannot bind to " + element.nodeName + ", not contentEditable"); + } + } + } + }, { + key: "createMenu", + value: function createMenu(containerClass) { + var wrapper = this.range.getDocument().createElement("div"), + ul = this.range.getDocument().createElement("ul"); + wrapper.className = containerClass; + 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; + // Check for maximum number of items added to the input for the specific Collection + if (this.current.collection.maxDisplayItems && element.querySelectorAll('[data-tribute-trigger="' + this.current.collection.trigger + '"]').length >= this.current.collection.maxDisplayItems || this.current.collection.isBlocked) { + //console.log("Tribute: Maximum number of items added!"); + return; + } + this.currentMentionTextSnapshot = this.current.mentionText; + + // create the menu if it doesn't exist. + if (!this.menu) { + this.menu = this.createMenu(this.current.collection.containerClass); + element.tributeMenu = this.menu; + this.menuEvents.bind(this.menu); + } + this.isActive = true; + this.menuSelected = 0; + window.setTimeout(function () { + _this2.menu.scrollTop = 0; + }, 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 || "", + post: _this2.current.collection.searchOpts.post || "", + skip: _this2.current.collection.searchOpts.skip || false, + caseSensitive: _this2.current.collection.searchOpts.caseSensitive || false, + 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."); + } + } + }); + if (_this2.current.collection.menuItemLimit) { + items = items.slice(0, _this2.current.collection.menuItemLimit); + } + _this2.current.filteredItems = items; + var ul = _this2.menu.querySelector("ul"); + if (!items.length) { + var noMatchEvent = new CustomEvent("tribute-no-match", { + detail: _this2.menu + }); + _this2.current.element.dispatchEvent(noMatchEvent); + if (typeof _this2.current.collection.noMatchTemplate === "function" && !_this2.current.collection.noMatchTemplate() || !_this2.current.collection.noMatchTemplate) { + _this2.hideMenu(); + } else { + typeof _this2.current.collection.noMatchTemplate === "function" ? ul.innerHTML = _this2.current.collection.noMatchTemplate() : ul.innerHTML = _this2.current.collection.noMatchTemplate; + _this2.range.positionMenuAtCaret(scrollTo); + } + return; + } + ul.innerHTML = ""; + var fragment = _this2.range.getDocument().createDocumentFragment(); + _this2.menuSelected = items.findIndex(function (item) { + return item.original.disabled !== true; + }); + items.forEach(function (item, index) { + var li = _this2.range.getDocument().createElement("li"); + li.setAttribute("data-index", index); + if (item.original.disabled) li.setAttribute("data-disabled", "true"); + li.className = _this2.current.collection.itemClass; + li.addEventListener("mousemove", function (e) { + var _this2$_findLiTarget = _this2._findLiTarget(e.target), + _this2$_findLiTarget2 = _slicedToArray(_this2$_findLiTarget, 2), + li = _this2$_findLiTarget2[0], + index = _this2$_findLiTarget2[1]; + if (e.movementY !== 0) { + _this2.events.setActiveLi(index); + } + }); + if (_this2.menuSelected === index) { + li.classList.add(_this2.current.collection.selectClass); + } + li.innerHTML = _this2.current.collection.menuItemTemplate(item); + fragment.appendChild(li); + }); + ul.appendChild(fragment); + _this2.range.positionMenuAtCaret(scrollTo); + }; + if (typeof this.current.collection.values === "function") { + if (this.current.collection.loadingItemTemplate) { + this.menu.querySelector("ul").innerHTML = this.current.collection.loadingItemTemplate; + this.range.positionMenuAtCaret(scrollTo); + } + this.current.collection.values(this.current.mentionText, processValues); + } else { + processValues(this.current.collection.values); + } + } + }, { + key: "_findLiTarget", + value: function _findLiTarget(el) { + if (!el) return []; + var index = el.getAttribute("data-index"); + return !index ? this._findLiTarget(el.parentNode) : [el, index]; + } + }, { + key: "showMenuForCollection", + value: function showMenuForCollection(element, collectionIndex) { + // Check for maximum number of items added to the input for the specific Collection + if (this.collection[collectionIndex || 0].maxDisplayItems && element.querySelectorAll('[data-tribute-trigger="' + this.collection[collectionIndex || 0].trigger + '"]').length >= this.collection[collectionIndex || 0].maxDisplayItems || this.collection[collectionIndex || 0].isBlocked) { + //console.log("Tribute: Maximum number of items added!"); + return; + } + 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" || isNaN(index) || !originalEvent.target) return; + var item = this.current.filteredItems[index]; + var content = this.current.collection.selectTemplate(item); + if (index === -1) { + var selectedNoMatchEvent = new CustomEvent('tribute-selected-no-match', { + detail: content + }); + this.current.element.dispatchEvent(selectedNoMatchEvent); + return; + } + 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 "".concat(this.current.collection.trigger).concat(this.current.mentionText); + if (this.range.isContentEditable(this.current.element)) { + return '' + (this.current.collection.trigger + item.original[this.current.collection.fillAttr]) + ""; + } + 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; + }(); + + /** + * Tribute.js + * Native ES6 JavaScript @mention Plugin + **/ + + return Tribute; + +})));