diff --git a/dist/mentio.js b/dist/mentio.js
index d81993b..8c595f9 100644
--- a/dist/mentio.js
+++ b/dist/mentio.js
@@ -536,9 +536,11 @@ angular.module('mentio', [])
};
}],
- link: function (scope, element) {
- element[0].parentNode.removeChild(element[0]);
- $document[0].body.appendChild(element[0]);
+ link: function (scope, element, attrs) {
+ if (attrs.mentioApplyElement === undefined) {
+ element[0].parentNode.removeChild(element[0]);
+ $document[0].body.appendChild(element[0]);
+ }
scope.menuElement = element; // for testing
if (scope.parentScope) {
@@ -606,7 +608,7 @@ angular.module('mentio', [])
scope.adjustScroll = function (direction) {
var menuEl = element[0];
var menuItemsList = menuEl.querySelector('ul');
- var menuItem = (menuEl.querySelector('[mentio-menu-item].active') ||
+ var menuItem = (menuEl.querySelector('[mentio-menu-item].active') ||
menuEl.querySelector('[data-mentio-menu-item].active'));
if (scope.isFirstItemActive()) {
@@ -694,9 +696,9 @@ angular.module('mentio')
if (selectedElementIsTextAreaOrInput(ctx)) {
coordinates = getTextAreaOrInputUnderlinePosition(ctx, getDocument(ctx).activeElement,
- mentionInfo.mentionPosition);
+ mentionInfo.mentionPosition, selectionEl);
} else {
- coordinates = getContentEditableCaretPosition(ctx, mentionInfo.mentionPosition);
+ coordinates = getContentEditableCaretPosition(ctx, mentionInfo.mentionPosition, selectionEl);
}
// Move the button into place.
@@ -856,7 +858,7 @@ angular.module('mentio')
}
// public
- function replaceTriggerText (ctx, targetElement, path, offset, triggerCharSet,
+ function replaceTriggerText (ctx, targetElement, path, offset, triggerCharSet,
text, requireLeadingSpace, hasTrailingSpace) {
resetSelection(ctx, targetElement, path, offset);
@@ -979,7 +981,7 @@ angular.module('mentio')
// public
function getTriggerInfo (ctx, triggerCharSet, requireLeadingSpace, menuAlreadyActive, hasTrailingSpace) {
/*jshint maxcomplexity:11 */
- // yes this function needs refactoring
+ // yes this function needs refactoring
var selected, path, offset;
if (selectedElementIsTextAreaOrInput(ctx)) {
selected = getDocument(ctx).activeElement;
@@ -1008,7 +1010,7 @@ angular.module('mentio')
(
mostRecentTriggerCharPos === 0 ||
!requireLeadingSpace ||
- /[\xA0\s]/g.test
+ /[([\-\xA0\s]/g.test
(
effectiveRange.substring(
mostRecentTriggerCharPos - 1,
@@ -1030,7 +1032,7 @@ angular.module('mentio')
if (hasTrailingSpace) {
currentTriggerSnippet = currentTriggerSnippet.trim();
}
- if (!leadingSpace && (menuAlreadyActive || !(/[\xA0\s]/g.test(currentTriggerSnippet)))) {
+ if (!leadingSpace) {
return {
mentionPosition: mostRecentTriggerCharPos,
mentionText: currentTriggerSnippet,
@@ -1080,7 +1082,7 @@ angular.module('mentio')
return text;
}
- function getContentEditableCaretPosition (ctx, selectedNodePosition) {
+ function getContentEditableCaretPosition (ctx, selectedNodePosition, selectionEl) {
var markerTextChar = '\ufeff';
var markerEl, markerId = 'sel_' + new Date().getTime() + '_' + Math.random().toString().substr(2);
@@ -1107,7 +1109,12 @@ angular.module('mentio')
top: markerEl.offsetHeight
};
- localToGlobalCoordinates(ctx, markerEl, coordinates);
+ if (selectionEl[0].parentNode === document.body) {
+ localToGlobalCoordinates(ctx, markerEl, coordinates);
+ } else {
+ coordinates.left += markerEl.offsetLeft;
+ coordinates.top += markerEl.offsetTop;
+ }
markerEl.parentNode.removeChild(markerEl);
return coordinates;
@@ -1124,7 +1131,7 @@ angular.module('mentio')
obj = iframe;
iframe = null;
}
- }
+ }
obj = element;
iframe = ctx ? ctx.iframe : null;
while(obj !== getDocument().body) {
@@ -1139,10 +1146,10 @@ angular.module('mentio')
obj = iframe;
iframe = null;
}
- }
+ }
}
- function getTextAreaOrInputUnderlinePosition (ctx, element, position) {
+ function getTextAreaOrInputUnderlinePosition (ctx, element, position, selectionEl) {
var properties = [
'direction',
'boxSizing',
@@ -1220,7 +1227,12 @@ angular.module('mentio')
left: span.offsetLeft + parseInt(computed.borderLeftWidth)
};
- localToGlobalCoordinates(ctx, element, coordinates);
+ if (selectionEl[0].parentNode === document.body) {
+ localToGlobalCoordinates(ctx, element, coordinates);
+ } else {
+ coordinates.left += element.offsetLeft;
+ coordinates.top += element.offsetTop;
+ }
getDocument(ctx).body.removeChild(div);
@@ -1251,4 +1263,4 @@ angular.module('mentio')
};
}]);
-angular.module("mentio").run(["$templateCache", function($templateCache) {$templateCache.put("mentio-menu.tpl.html","\n
");}]);
\ No newline at end of file
+angular.module("mentio").run(["$templateCache", function($templateCache) {$templateCache.put("mentio-menu.tpl.html","\r\n");}]);
\ No newline at end of file
diff --git a/dist/mentio.min.js b/dist/mentio.min.js
index 2cd5416..bfc9f6a 100644
--- a/dist/mentio.min.js
+++ b/dist/mentio.min.js
@@ -1 +1 @@
-"use strict";angular.module("mentio",[]).directive("mentio",["mentioUtil","$document","$compile","$log","$timeout",function(e,t,n,r,i){return{restrict:"A",scope:{macros:"=mentioMacros",search:"&mentioSearch",select:"&mentioSelect",items:"=mentioItems",typedTerm:"=mentioTypedTerm",altId:"=mentioId",iframeElement:"=mentioIframeElement",requireLeadingSpace:"=mentioRequireLeadingSpace",selectNotFound:"=mentioSelectNotFound",trimTerm:"=mentioTrimTerm",ngModel:"="},controller:["$scope","$timeout","$attrs",function(n,r,i){n.query=function(e,t){var r=n.triggerCharMap[e];(void 0===n.trimTerm||n.trimTerm)&&(t=t.trim()),r.showMenu(),r.search({term:t}),r.typedTerm=t},n.defaultSearch=function(e){var t=[];angular.forEach(n.items,function(n){n.label.toUpperCase().indexOf(e.term.toUpperCase())>=0&&t.push(n)}),n.localItems=t},n.bridgeSearch=function(e){var t=i.mentioSearch?n.search:n.defaultSearch;t({term:e})},n.defaultSelect=function(e){return n.defaultTriggerChar+e.item.label},n.bridgeSelect=function(e){var t=i.mentioSelect?n.select:n.defaultSelect;return t({item:e})},n.setTriggerText=function(e){n.syncTriggerText&&(n.typedTerm=void 0===n.trimTerm||n.trimTerm?e.trim():e)},n.context=function(){return n.iframeElement?{iframe:n.iframeElement}:void 0},n.replaceText=function(t,i){if(n.hideAll(),e.replaceTriggerText(n.context(),n.targetElement,n.targetElementPath,n.targetElementSelectedOffset,n.triggerCharSet,t,n.requireLeadingSpace,i),!i&&(n.setTriggerText(""),angular.element(n.targetElement).triggerHandler("change"),n.isContentEditable())){n.contentEditableMenuPasted=!0;var o=r(function(){n.contentEditableMenuPasted=!1},200);n.$on("$destroy",function(){r.cancel(o)})}},n.hideAll=function(){for(var e in n.triggerCharMap)n.triggerCharMap.hasOwnProperty(e)&&n.triggerCharMap[e].hideMenu()},n.getActiveMenuScope=function(){for(var e in n.triggerCharMap)if(n.triggerCharMap.hasOwnProperty(e)&&n.triggerCharMap[e].visible)return n.triggerCharMap[e];return null},n.selectActive=function(){for(var e in n.triggerCharMap)n.triggerCharMap.hasOwnProperty(e)&&n.triggerCharMap[e].visible&&n.triggerCharMap[e].selectActive()},n.isActive=function(){for(var e in n.triggerCharMap)if(n.triggerCharMap.hasOwnProperty(e)&&n.triggerCharMap[e].visible)return!0;return!1},n.isContentEditable=function(){return"INPUT"!==n.targetElement.nodeName&&"TEXTAREA"!==n.targetElement.nodeName},n.replaceMacro=function(t,i){i?e.replaceMacroText(n.context(),n.targetElement,n.targetElementPath,n.targetElementSelectedOffset,n.macros,n.macros[t]):(n.replacingMacro=!0,n.timer=r(function(){e.replaceMacroText(n.context(),n.targetElement,n.targetElementPath,n.targetElementSelectedOffset,n.macros,n.macros[t]),angular.element(n.targetElement).triggerHandler("change"),n.replacingMacro=!1},300),n.$on("$destroy",function(){r.cancel(n.timer)}))},n.addMenu=function(e){e.parentScope&&n.triggerCharMap.hasOwnProperty(e.triggerChar)||(n.triggerCharMap[e.triggerChar]=e,void 0===n.triggerCharSet&&(n.triggerCharSet=[]),n.triggerCharSet.push(e.triggerChar),e.setParent(n))},n.$on("menuCreated",function(e,t){(void 0!==i.id||void 0!==i.mentioId)&&(i.id===t.targetElement||void 0!==i.mentioId&&n.altId===t.targetElement)&&n.addMenu(t.scope)}),t.on("click",function(){n.isActive()&&n.$apply(function(){n.hideAll()})}),t.on("keydown keypress paste",function(e){var t=n.getActiveMenuScope();t&&((9===e.which||13===e.which)&&(e.preventDefault(),t.selectActive()),27===e.which&&(e.preventDefault(),t.$apply(function(){t.hideMenu()})),40===e.which&&(e.preventDefault(),t.$apply(function(){t.activateNextItem()}),t.adjustScroll(1)),38===e.which&&(e.preventDefault(),t.$apply(function(){t.activatePreviousItem()}),t.adjustScroll(-1)),(37===e.which||39===e.which)&&e.preventDefault())})}],link:function(t,o,a){function c(e){function n(e){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation()}var r=t.getActiveMenuScope();if(r){if(9===e.which||13===e.which)return n(e),r.selectActive(),!1;if(27===e.which)return n(e),r.$apply(function(){r.hideMenu()}),!1;if(40===e.which)return n(e),r.$apply(function(){r.activateNextItem()}),r.adjustScroll(1),!1;if(38===e.which)return n(e),r.$apply(function(){r.activatePreviousItem()}),r.adjustScroll(-1),!1;if(37===e.which||39===e.which)return n(e),!1}}if(t.triggerCharMap={},t.targetElement=o,a.$set("autocomplete","off"),a.mentioItems){t.localItems=[],t.parentScope=t;var l=a.mentioSearch?' mentio-items="items"':' mentio-items="localItems"';t.defaultTriggerChar=a.mentioTriggerChar?t.$eval(a.mentioTriggerChar):"@";var s='';var m=n(s),u=m(t);o.parent().append(u),t.$on("$destroy",function(){u.remove()})}a.mentioTypedTerm&&(t.syncTriggerText=!0),t.$watch("iframeElement",function(e){if(e){var n=e.contentWindow.document;n.addEventListener("click",function(){t.isActive()&&t.$apply(function(){t.hideAll()})}),n.addEventListener("keydown",c,!0),t.$on("$destroy",function(){n.removeEventListener("keydown",c)})}}),t.$watch("ngModel",function(n){if(n&&""!==n||t.isActive()){if(void 0===t.triggerCharSet)return void r.error("Error, no mentio-items attribute was provided, and no separate mentio-menus were specified. Nothing to do.");if(t.contentEditableMenuPasted)return void(t.contentEditableMenuPasted=!1);t.replacingMacro&&(i.cancel(t.timer),t.replacingMacro=!1);var o=t.isActive(),a=t.isContentEditable(),c=e.getTriggerInfo(t.context(),t.triggerCharSet,t.requireLeadingSpace,o);if(void 0!==c&&(!o||o&&(a&&c.mentionTriggerChar===t.currentMentionTriggerChar||!a&&c.mentionPosition===t.currentMentionPosition)))c.mentionSelectedElement&&(t.targetElement=c.mentionSelectedElement,t.targetElementPath=c.mentionSelectedPath,t.targetElementSelectedOffset=c.mentionSelectedOffset),t.setTriggerText(c.mentionText),t.currentMentionPosition=c.mentionPosition,t.currentMentionTriggerChar=c.mentionTriggerChar,t.query(c.mentionTriggerChar,c.mentionText);else{var l=t.typedTerm;t.setTriggerText(""),t.hideAll();var s=e.getMacroMatch(t.context(),t.macros);if(void 0!==s)t.targetElement=s.macroSelectedElement,t.targetElementPath=s.macroSelectedPath,t.targetElementSelectedOffset=s.macroSelectedOffset,t.replaceMacro(s.macroText,s.macroHasTrailingSpace);else if(t.selectNotFound&&l&&""!==l){var m=t.triggerCharMap[t.currentMentionTriggerChar];if(m){var u=m.select({item:{label:l}});"function"==typeof u.then?u.then(t.replaceText):t.replaceText(u,!0)}}}}})}}}]).directive("mentioMenu",["mentioUtil","$rootScope","$log","$window","$document",function(e,t,n,r,i){return{restrict:"E",scope:{search:"&mentioSearch",select:"&mentioSelect",items:"=mentioItems",triggerChar:"=mentioTriggerChar",forElem:"=mentioFor",parentScope:"=mentioParentScope"},templateUrl:function(e,t){return void 0!==t.mentioTemplateUrl?t.mentioTemplateUrl:"mentio-menu.tpl.html"},controller:["$scope",function(e){e.visible=!1,this.activate=e.activate=function(t){e.activeItem=t},this.isActive=e.isActive=function(t){return e.activeItem===t},this.selectItem=e.selectItem=function(t){var n=e.select({item:t});"function"==typeof n.then?n.then(e.parentMentio.replaceText):e.parentMentio.replaceText(n)},e.activateNextItem=function(){var t=e.items.indexOf(e.activeItem);this.activate(e.items[(t+1)%e.items.length])},e.activatePreviousItem=function(){var t=e.items.indexOf(e.activeItem);this.activate(e.items[0===t?e.items.length-1:t-1])},e.isFirstItemActive=function(){var t=e.items.indexOf(e.activeItem);return 0===t},e.isLastItemActive=function(){var t=e.items.indexOf(e.activeItem);return t===e.items.length-1},e.selectActive=function(){e.selectItem(e.activeItem)},e.isVisible=function(){return e.visible},e.showMenu=function(){e.visible||(e.requestVisiblePendingSearch=!0)},e.setParent=function(t){e.parentMentio=t,e.targetElement=t.targetElement}}],link:function(o,a){if(a[0].parentNode.removeChild(a[0]),i[0].body.appendChild(a[0]),o.menuElement=a,o.parentScope)o.parentScope.addMenu(o);else{if(!o.forElem)return void n.error("mentio-menu requires a target element in tbe mentio-for attribute");if(!o.triggerChar)return void n.error("mentio-menu requires a trigger char");t.$broadcast("menuCreated",{targetElement:o.forElem,scope:o})}angular.element(r).bind("resize",function(){if(o.isVisible()){var t=[];t.push(o.triggerChar),e.popUnderMention(o.parentMentio.context(),t,a,o.requireLeadingSpace)}}),o.$watch("items",function(e){e&&e.length>0?(o.activate(e[0]),!o.visible&&o.requestVisiblePendingSearch&&(o.visible=!0,o.requestVisiblePendingSearch=!1)):o.hideMenu()}),o.$watch("isVisible()",function(t){if(t){var n=[];n.push(o.triggerChar),e.popUnderMention(o.parentMentio.context(),n,a,o.requireLeadingSpace)}}),o.parentMentio.$on("$destroy",function(){a.remove()}),o.hideMenu=function(){o.visible=!1,a.css("display","none")},o.adjustScroll=function(e){var t=a[0],n=t.querySelector("ul"),r=t.querySelector("[mentio-menu-item].active")||t.querySelector("[data-mentio-menu-item].active");return o.isFirstItemActive()?n.scrollTop=0:o.isLastItemActive()?n.scrollTop=n.scrollHeight:void(1===e?n.scrollTop+=r.offsetHeight:n.scrollTop-=r.offsetHeight)}}}}]).directive("mentioMenuItem",function(){return{restrict:"A",scope:{item:"=mentioMenuItem"},require:"^mentioMenu",link:function(e,t,n,r){e.$watch(function(){return r.isActive(e.item)},function(e){e?t.addClass("active"):t.removeClass("active")}),t.bind("mouseenter",function(){e.$apply(function(){r.activate(e.item)})}),t.bind("click",function(){return r.selectItem(e.item),!1})}}}).filter("unsafe",["$sce",function(e){return function(t){return e.trustAsHtml(t)}}]).filter("mentioHighlight",function(){function e(e){return e.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(t,n,r){if(n){var i=r?'$&':"$&";return(""+t).replace(new RegExp(e(n),"gi"),i)}return t}}),angular.module("mentio").factory("mentioUtil",["$window","$location","$anchorScroll","$timeout",function(e,t,n,r){function i(e,t,n,i){var c,l=h(e,t,i,!1);void 0!==l?(c=a(e)?b(e,v(e).activeElement,l.mentionPosition):S(e,l.mentionPosition),n.css({top:c.top+"px",left:c.left+"px",position:"absolute",zIndex:1e4,display:"block"}),r(function(){o(e,n)},0)):n.css({display:"none"})}function o(t,n){for(var r,i=20,o=100,a=n[0];void 0===r||0===r.height;)if(r=a.getBoundingClientRect(),0===r.height&&(a=a.childNodes[0],void 0===a||!a.getBoundingClientRect))return;var c=r.top,l=c+r.height;if(0>c)e.scrollTo(0,e.pageYOffset+r.top-i);else if(l>e.innerHeight){var s=e.pageYOffset+r.top-i;s-e.pageYOffset>o&&(s=e.pageYOffset+o);var m=e.pageYOffset-(e.innerHeight-l);m>s&&(m=s),e.scrollTo(0,m)}}function a(e){var t=v(e).activeElement;if(null!==t){var n=t.nodeName,r=t.getAttribute("type");return"INPUT"===n&&"text"===r||"TEXTAREA"===n}return!1}function c(e,t,n,r){var i,o=t;if(n)for(var a=0;a0&&(" "===c.charAt(c.length-1)||" "===c.charAt(c.length-1))&&(s=!0,c=c.substring(0,c.length-1)),angular.forEach(t,function(e,t){var o=c.toUpperCase().lastIndexOf(t.toUpperCase());if(o>=0&&t.length+o===c.length){var a=o-1;(0===o||" "===c.charAt(a)||" "===c.charAt(a))&&(l={macroPosition:o,macroText:t,macroSelectedElement:n,macroSelectedPath:i,macroSelectedOffset:r,macroHasTrailingSpace:s})}}),l)return l}}function f(e){var t,n=p(e),r=n.anchorNode,i=[];if(null!=r){for(var o,a=r.contentEditable;null!==r&&"true"!==a;)o=g(e,r),i.push(o),r=r.parentNode,null!==r&&(a=r.contentEditable);return i.reverse(),t=n.getRangeAt(0).startOffset,{selected:r,path:i,offset:t}}}function h(e,t,n,r,i){var o,c,l;if(a(e))o=v(e).activeElement;else{var s=f(e);s&&(o=s.selected,c=s.path,l=s.offset)}var m=T(e);if(void 0!==m&&null!==m){var u,g=-1;if(t.forEach(function(e){var t=m.lastIndexOf(e);t>g&&(g=t,u=e)}),g>=0&&(0===g||!n||/[\xA0\s]/g.test(m.substring(g-1,g)))){var d=m.substring(g+1,m.length);u=m.substring(g,g+1);var h=d.substring(0,1),p=d.length>0&&(" "===h||" "===h);if(i&&(d=d.trim()),!p&&(r||!/[\xA0\s]/g.test(d)))return{mentionPosition:g,mentionText:d,mentionSelectedElement:o,mentionSelectedPath:c,mentionSelectedOffset:l,mentionTriggerChar:u}}}}function p(e){return e?e.iframe.contentWindow.getSelection():window.getSelection()}function v(e){return e?e.iframe.contentWindow.document:document}function T(e){var t;if(a(e)){var n=v(e).activeElement,r=n.selectionStart;t=n.value.substring(0,r)}else{var i=p(e).anchorNode;if(null!=i){var o=i.textContent,c=p(e).getRangeAt(0).startOffset;c>=0&&(t=o.substring(0,c))}}return t}function S(e,t){var n,r,i="",o="sel_"+(new Date).getTime()+"_"+Math.random().toString().substr(2),a=p(e),c=a.getRangeAt(0);r=v(e).createRange(),r.setStart(a.anchorNode,t),r.setEnd(a.anchorNode,t),r.collapse(!1),n=v(e).createElement("span"),n.id=o,n.appendChild(v(e).createTextNode(i)),r.insertNode(n),a.removeAllRanges(),a.addRange(c);var l={left:0,top:n.offsetHeight};return E(e,n,l),n.parentNode.removeChild(n),l}function E(e,t,n){for(var r=t,i=e?e.iframe:null;r;)n.left+=r.offsetLeft+r.clientLeft,n.top+=r.offsetTop+r.clientTop,r=r.offsetParent,!r&&i&&(r=i,i=null);for(r=t,i=e?e.iframe:null;r!==v().body;)r.scrollTop&&r.scrollTop>0&&(n.top-=r.scrollTop),r.scrollLeft&&r.scrollLeft>0&&(n.left-=r.scrollLeft),r=r.parentNode,!r&&i&&(r=i,i=null)}function b(e,t,n){var r=["direction","boxSizing","width","height","overflowX","overflowY","borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth","paddingTop","paddingRight","paddingBottom","paddingLeft","fontStyle","fontVariant","fontWeight","fontStretch","fontSize","fontSizeAdjust","lineHeight","fontFamily","textAlign","textTransform","textIndent","textDecoration","letterSpacing","wordSpacing"],i=null!==window.mozInnerScreenX,o=v(e).createElement("div");o.id="input-textarea-caret-position-mirror-div",v(e).body.appendChild(o);var a=o.style,c=window.getComputedStyle?getComputedStyle(t):t.currentStyle;a.whiteSpace="pre-wrap","INPUT"!==t.nodeName&&(a.wordWrap="break-word"),a.position="absolute",a.visibility="hidden",r.forEach(function(e){a[e]=c[e]}),i?(a.width=parseInt(c.width)-2+"px",t.scrollHeight>parseInt(c.height)&&(a.overflowY="scroll")):a.overflow="hidden",o.textContent=t.value.substring(0,n),"INPUT"===t.nodeName&&(o.textContent=o.textContent.replace(/\s/g," "));var l=v(e).createElement("span");l.textContent=t.value.substring(n)||".",o.appendChild(l);var s={top:l.offsetTop+parseInt(c.borderTopWidth)+parseInt(c.fontSize),left:l.offsetLeft+parseInt(c.borderLeftWidth)};return E(e,t,s),v(e).body.removeChild(o),s}return{popUnderMention:i,replaceMacroText:m,replaceTriggerText:u,getMacroMatch:d,getTriggerInfo:h,selectElement:c,getTextAreaOrInputUnderlinePosition:b,getTextPrecedingCurrentSelection:T,getContentEditableSelectedPath:f,getNodePositionInParent:g,getContentEditableCaretPosition:S,pasteHtml:l,resetSelection:s,scrollIntoView:o}}]),angular.module("mentio").run(["$templateCache",function(e){e.put("mentio-menu.tpl.html",'\n')}]);
\ No newline at end of file
+"use strict";angular.module("mentio",[]).directive("mentio",["mentioUtil","$document","$compile","$log","$timeout",function(e,t,n,r,i){return{restrict:"A",scope:{macros:"=mentioMacros",search:"&mentioSearch",select:"&mentioSelect",items:"=mentioItems",typedTerm:"=mentioTypedTerm",altId:"=mentioId",iframeElement:"=mentioIframeElement",requireLeadingSpace:"=mentioRequireLeadingSpace",selectNotFound:"=mentioSelectNotFound",trimTerm:"=mentioTrimTerm",ngModel:"="},controller:["$scope","$timeout","$attrs",function(n,r,i){n.query=function(e,t){var r=n.triggerCharMap[e];(void 0===n.trimTerm||n.trimTerm)&&(t=t.trim()),r.showMenu(),r.search({term:t}),r.typedTerm=t},n.defaultSearch=function(e){var t=[];angular.forEach(n.items,function(n){n.label.toUpperCase().indexOf(e.term.toUpperCase())>=0&&t.push(n)}),n.localItems=t},n.bridgeSearch=function(e){var t=i.mentioSearch?n.search:n.defaultSearch;t({term:e})},n.defaultSelect=function(e){return n.defaultTriggerChar+e.item.label},n.bridgeSelect=function(e){var t=i.mentioSelect?n.select:n.defaultSelect;return t({item:e})},n.setTriggerText=function(e){n.syncTriggerText&&(n.typedTerm=void 0===n.trimTerm||n.trimTerm?e.trim():e)},n.context=function(){return n.iframeElement?{iframe:n.iframeElement}:void 0},n.replaceText=function(t,i){if(n.hideAll(),e.replaceTriggerText(n.context(),n.targetElement,n.targetElementPath,n.targetElementSelectedOffset,n.triggerCharSet,t,n.requireLeadingSpace,i),!i&&(n.setTriggerText(""),angular.element(n.targetElement).triggerHandler("change"),n.isContentEditable())){n.contentEditableMenuPasted=!0;var o=r(function(){n.contentEditableMenuPasted=!1},200);n.$on("$destroy",function(){r.cancel(o)})}},n.hideAll=function(){for(var e in n.triggerCharMap)n.triggerCharMap.hasOwnProperty(e)&&n.triggerCharMap[e].hideMenu()},n.getActiveMenuScope=function(){for(var e in n.triggerCharMap)if(n.triggerCharMap.hasOwnProperty(e)&&n.triggerCharMap[e].visible)return n.triggerCharMap[e];return null},n.selectActive=function(){for(var e in n.triggerCharMap)n.triggerCharMap.hasOwnProperty(e)&&n.triggerCharMap[e].visible&&n.triggerCharMap[e].selectActive()},n.isActive=function(){for(var e in n.triggerCharMap)if(n.triggerCharMap.hasOwnProperty(e)&&n.triggerCharMap[e].visible)return!0;return!1},n.isContentEditable=function(){return"INPUT"!==n.targetElement.nodeName&&"TEXTAREA"!==n.targetElement.nodeName},n.replaceMacro=function(t,i){i?e.replaceMacroText(n.context(),n.targetElement,n.targetElementPath,n.targetElementSelectedOffset,n.macros,n.macros[t]):(n.replacingMacro=!0,n.timer=r(function(){e.replaceMacroText(n.context(),n.targetElement,n.targetElementPath,n.targetElementSelectedOffset,n.macros,n.macros[t]),angular.element(n.targetElement).triggerHandler("change"),n.replacingMacro=!1},300),n.$on("$destroy",function(){r.cancel(n.timer)}))},n.addMenu=function(e){e.parentScope&&n.triggerCharMap.hasOwnProperty(e.triggerChar)||(n.triggerCharMap[e.triggerChar]=e,void 0===n.triggerCharSet&&(n.triggerCharSet=[]),n.triggerCharSet.push(e.triggerChar),e.setParent(n))},n.$on("menuCreated",function(e,t){(void 0!==i.id||void 0!==i.mentioId)&&(i.id===t.targetElement||void 0!==i.mentioId&&n.altId===t.targetElement)&&n.addMenu(t.scope)}),t.on("click",function(){n.isActive()&&n.$apply(function(){n.hideAll()})}),t.on("keydown keypress paste",function(e){var t=n.getActiveMenuScope();t&&((9===e.which||13===e.which)&&(e.preventDefault(),t.selectActive()),27===e.which&&(e.preventDefault(),t.$apply(function(){t.hideMenu()})),40===e.which&&(e.preventDefault(),t.$apply(function(){t.activateNextItem()}),t.adjustScroll(1)),38===e.which&&(e.preventDefault(),t.$apply(function(){t.activatePreviousItem()}),t.adjustScroll(-1)),(37===e.which||39===e.which)&&e.preventDefault())})}],link:function(t,o,a){function l(e){function n(e){e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation()}var r=t.getActiveMenuScope();if(r){if(9===e.which||13===e.which)return n(e),r.selectActive(),!1;if(27===e.which)return n(e),r.$apply(function(){r.hideMenu()}),!1;if(40===e.which)return n(e),r.$apply(function(){r.activateNextItem()}),r.adjustScroll(1),!1;if(38===e.which)return n(e),r.$apply(function(){r.activatePreviousItem()}),r.adjustScroll(-1),!1;if(37===e.which||39===e.which)return n(e),!1}}if(t.triggerCharMap={},t.targetElement=o,a.$set("autocomplete","off"),a.mentioItems){t.localItems=[],t.parentScope=t;var c=a.mentioSearch?' mentio-items="items"':' mentio-items="localItems"';t.defaultTriggerChar=a.mentioTriggerChar?t.$eval(a.mentioTriggerChar):"@";var s='';var m=n(s),u=m(t);o.parent().append(u),t.$on("$destroy",function(){u.remove()})}a.mentioTypedTerm&&(t.syncTriggerText=!0),t.$watch("iframeElement",function(e){if(e){var n=e.contentWindow.document;n.addEventListener("click",function(){t.isActive()&&t.$apply(function(){t.hideAll()})}),n.addEventListener("keydown",l,!0),t.$on("$destroy",function(){n.removeEventListener("keydown",l)})}}),t.$watch("ngModel",function(n){if(n&&""!==n||t.isActive()){if(void 0===t.triggerCharSet)return r.error("Error, no mentio-items attribute was provided, and no separate mentio-menus were specified. Nothing to do."),void 0;if(t.contentEditableMenuPasted)return t.contentEditableMenuPasted=!1,void 0;t.replacingMacro&&(i.cancel(t.timer),t.replacingMacro=!1);var o=t.isActive(),a=t.isContentEditable(),l=e.getTriggerInfo(t.context(),t.triggerCharSet,t.requireLeadingSpace,o);if(void 0!==l&&(!o||o&&(a&&l.mentionTriggerChar===t.currentMentionTriggerChar||!a&&l.mentionPosition===t.currentMentionPosition)))l.mentionSelectedElement&&(t.targetElement=l.mentionSelectedElement,t.targetElementPath=l.mentionSelectedPath,t.targetElementSelectedOffset=l.mentionSelectedOffset),t.setTriggerText(l.mentionText),t.currentMentionPosition=l.mentionPosition,t.currentMentionTriggerChar=l.mentionTriggerChar,t.query(l.mentionTriggerChar,l.mentionText);else{var c=t.typedTerm;t.setTriggerText(""),t.hideAll();var s=e.getMacroMatch(t.context(),t.macros);if(void 0!==s)t.targetElement=s.macroSelectedElement,t.targetElementPath=s.macroSelectedPath,t.targetElementSelectedOffset=s.macroSelectedOffset,t.replaceMacro(s.macroText,s.macroHasTrailingSpace);else if(t.selectNotFound&&c&&""!==c){var m=t.triggerCharMap[t.currentMentionTriggerChar];if(m){var u=m.select({item:{label:c}});"function"==typeof u.then?u.then(t.replaceText):t.replaceText(u,!0)}}}}})}}}]).directive("mentioMenu",["mentioUtil","$rootScope","$log","$window","$document",function(e,t,n,r,i){return{restrict:"E",scope:{search:"&mentioSearch",select:"&mentioSelect",items:"=mentioItems",triggerChar:"=mentioTriggerChar",forElem:"=mentioFor",parentScope:"=mentioParentScope"},templateUrl:function(e,t){return void 0!==t.mentioTemplateUrl?t.mentioTemplateUrl:"mentio-menu.tpl.html"},controller:["$scope",function(e){e.visible=!1,this.activate=e.activate=function(t){e.activeItem=t},this.isActive=e.isActive=function(t){return e.activeItem===t},this.selectItem=e.selectItem=function(t){var n=e.select({item:t});"function"==typeof n.then?n.then(e.parentMentio.replaceText):e.parentMentio.replaceText(n)},e.activateNextItem=function(){var t=e.items.indexOf(e.activeItem);this.activate(e.items[(t+1)%e.items.length])},e.activatePreviousItem=function(){var t=e.items.indexOf(e.activeItem);this.activate(e.items[0===t?e.items.length-1:t-1])},e.isFirstItemActive=function(){var t=e.items.indexOf(e.activeItem);return 0===t},e.isLastItemActive=function(){var t=e.items.indexOf(e.activeItem);return t===e.items.length-1},e.selectActive=function(){e.selectItem(e.activeItem)},e.isVisible=function(){return e.visible},e.showMenu=function(){e.visible||(e.requestVisiblePendingSearch=!0)},e.setParent=function(t){e.parentMentio=t,e.targetElement=t.targetElement}}],link:function(o,a,l){if(void 0===l.mentioApplyElement&&(a[0].parentNode.removeChild(a[0]),i[0].body.appendChild(a[0])),o.menuElement=a,o.parentScope)o.parentScope.addMenu(o);else{if(!o.forElem)return n.error("mentio-menu requires a target element in tbe mentio-for attribute"),void 0;if(!o.triggerChar)return n.error("mentio-menu requires a trigger char"),void 0;t.$broadcast("menuCreated",{targetElement:o.forElem,scope:o})}angular.element(r).bind("resize",function(){if(o.isVisible()){var t=[];t.push(o.triggerChar),e.popUnderMention(o.parentMentio.context(),t,a,o.requireLeadingSpace)}}),o.$watch("items",function(e){e&&e.length>0?(o.activate(e[0]),!o.visible&&o.requestVisiblePendingSearch&&(o.visible=!0,o.requestVisiblePendingSearch=!1)):o.hideMenu()}),o.$watch("isVisible()",function(t){if(t){var n=[];n.push(o.triggerChar),e.popUnderMention(o.parentMentio.context(),n,a,o.requireLeadingSpace)}}),o.parentMentio.$on("$destroy",function(){a.remove()}),o.hideMenu=function(){o.visible=!1,a.css("display","none")},o.adjustScroll=function(e){var t=a[0],n=t.querySelector("ul"),r=t.querySelector("[mentio-menu-item].active")||t.querySelector("[data-mentio-menu-item].active");return o.isFirstItemActive()?n.scrollTop=0:o.isLastItemActive()?n.scrollTop=n.scrollHeight:(1===e?n.scrollTop+=r.offsetHeight:n.scrollTop-=r.offsetHeight,void 0)}}}}]).directive("mentioMenuItem",function(){return{restrict:"A",scope:{item:"=mentioMenuItem"},require:"^mentioMenu",link:function(e,t,n,r){e.$watch(function(){return r.isActive(e.item)},function(e){e?t.addClass("active"):t.removeClass("active")}),t.bind("mouseenter",function(){e.$apply(function(){r.activate(e.item)})}),t.bind("click",function(){return r.selectItem(e.item),!1})}}}).filter("unsafe",["$sce",function(e){return function(t){return e.trustAsHtml(t)}}]).filter("mentioHighlight",function(){function e(e){return e.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(t,n,r){if(n){var i=r?'$&':"$&";return(""+t).replace(new RegExp(e(n),"gi"),i)}return t}}),angular.module("mentio").factory("mentioUtil",["$window","$location","$anchorScroll","$timeout",function(e,t,n,r){function i(e,t,n,i){var l,c=p(e,t,i,!1);void 0!==c?(l=a(e)?b(e,v(e).activeElement,c.mentionPosition,n):S(e,c.mentionPosition,n),n.css({top:l.top+"px",left:l.left+"px",position:"absolute",zIndex:1e4,display:"block"}),r(function(){o(e,n)},0)):n.css({display:"none"})}function o(t,n){for(var r,i=20,o=100,a=n[0];void 0===r||0===r.height;)if(r=a.getBoundingClientRect(),0===r.height&&(a=a.childNodes[0],void 0===a||!a.getBoundingClientRect))return;var l=r.top,c=l+r.height;if(0>l)e.scrollTo(0,e.pageYOffset+r.top-i);else if(c>e.innerHeight){var s=e.pageYOffset+r.top-i;s-e.pageYOffset>o&&(s=e.pageYOffset+o);var m=e.pageYOffset-(e.innerHeight-c);m>s&&(m=s),e.scrollTo(0,m)}}function a(e){var t=v(e).activeElement;if(null!==t){var n=t.nodeName,r=t.getAttribute("type");return"INPUT"===n&&"text"===r||"TEXTAREA"===n}return!1}function l(e,t,n,r){var i,o=t;if(n)for(var a=0;a0&&(" "===l.charAt(l.length-1)||" "===l.charAt(l.length-1))&&(s=!0,l=l.substring(0,l.length-1)),angular.forEach(t,function(e,t){var o=l.toUpperCase().lastIndexOf(t.toUpperCase());if(o>=0&&t.length+o===l.length){var a=o-1;(0===o||" "===l.charAt(a)||" "===l.charAt(a))&&(c={macroPosition:o,macroText:t,macroSelectedElement:n,macroSelectedPath:i,macroSelectedOffset:r,macroHasTrailingSpace:s})}}),c)return c}}function d(e){var t,n=h(e),r=n.anchorNode,i=[];if(null!=r){for(var o,a=r.contentEditable;null!==r&&"true"!==a;)o=g(e,r),i.push(o),r=r.parentNode,null!==r&&(a=r.contentEditable);return i.reverse(),t=n.getRangeAt(0).startOffset,{selected:r,path:i,offset:t}}}function p(e,t,n,r,i){var o,l,c;if(a(e))o=v(e).activeElement;else{var s=d(e);s&&(o=s.selected,l=s.path,c=s.offset)}var m=T(e);if(void 0!==m&&null!==m){var u,g=-1;if(t.forEach(function(e){var t=m.lastIndexOf(e);t>g&&(g=t,u=e)}),g>=0&&(0===g||!n||/[([\-\xA0\s]/g.test(m.substring(g-1,g)))){var f=m.substring(g+1,m.length);u=m.substring(g,g+1);var p=f.substring(0,1),h=f.length>0&&(" "===p||" "===p);if(i&&(f=f.trim()),!h)return{mentionPosition:g,mentionText:f,mentionSelectedElement:o,mentionSelectedPath:l,mentionSelectedOffset:c,mentionTriggerChar:u}}}}function h(e){return e?e.iframe.contentWindow.getSelection():window.getSelection()}function v(e){return e?e.iframe.contentWindow.document:document}function T(e){var t;if(a(e)){var n=v(e).activeElement,r=n.selectionStart;t=n.value.substring(0,r)}else{var i=h(e).anchorNode;if(null!=i){var o=i.textContent,l=h(e).getRangeAt(0).startOffset;l>=0&&(t=o.substring(0,l))}}return t}function S(e,t,n){var r,i,o="",a="sel_"+(new Date).getTime()+"_"+Math.random().toString().substr(2),l=h(e),c=l.getRangeAt(0);i=v(e).createRange(),i.setStart(l.anchorNode,t),i.setEnd(l.anchorNode,t),i.collapse(!1),r=v(e).createElement("span"),r.id=a,r.appendChild(v(e).createTextNode(o)),i.insertNode(r),l.removeAllRanges(),l.addRange(c);var s={left:0,top:r.offsetHeight};return n[0].parentNode===document.body?E(e,r,s):(s.left+=r.offsetLeft,s.top+=r.offsetTop),r.parentNode.removeChild(r),s}function E(e,t,n){for(var r=t,i=e?e.iframe:null;r;)n.left+=r.offsetLeft+r.clientLeft,n.top+=r.offsetTop+r.clientTop,r=r.offsetParent,!r&&i&&(r=i,i=null);for(r=t,i=e?e.iframe:null;r!==v().body;)r.scrollTop&&r.scrollTop>0&&(n.top-=r.scrollTop),r.scrollLeft&&r.scrollLeft>0&&(n.left-=r.scrollLeft),r=r.parentNode,!r&&i&&(r=i,i=null)}function b(e,t,n,r){var i=["direction","boxSizing","width","height","overflowX","overflowY","borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth","paddingTop","paddingRight","paddingBottom","paddingLeft","fontStyle","fontVariant","fontWeight","fontStretch","fontSize","fontSizeAdjust","lineHeight","fontFamily","textAlign","textTransform","textIndent","textDecoration","letterSpacing","wordSpacing"],o=null!==window.mozInnerScreenX,a=v(e).createElement("div");a.id="input-textarea-caret-position-mirror-div",v(e).body.appendChild(a);var l=a.style,c=window.getComputedStyle?getComputedStyle(t):t.currentStyle;l.whiteSpace="pre-wrap","INPUT"!==t.nodeName&&(l.wordWrap="break-word"),l.position="absolute",l.visibility="hidden",i.forEach(function(e){l[e]=c[e]}),o?(l.width=parseInt(c.width)-2+"px",t.scrollHeight>parseInt(c.height)&&(l.overflowY="scroll")):l.overflow="hidden",a.textContent=t.value.substring(0,n),"INPUT"===t.nodeName&&(a.textContent=a.textContent.replace(/\s/g," "));var s=v(e).createElement("span");s.textContent=t.value.substring(n)||".",a.appendChild(s);var m={top:s.offsetTop+parseInt(c.borderTopWidth)+parseInt(c.fontSize),left:s.offsetLeft+parseInt(c.borderLeftWidth)};return r[0].parentNode===document.body?E(e,t,m):(m.left+=t.offsetLeft,m.top+=t.offsetTop),v(e).body.removeChild(a),m}return{popUnderMention:i,replaceMacroText:m,replaceTriggerText:u,getMacroMatch:f,getTriggerInfo:p,selectElement:l,getTextAreaOrInputUnderlinePosition:b,getTextPrecedingCurrentSelection:T,getContentEditableSelectedPath:d,getNodePositionInParent:g,getContentEditableCaretPosition:S,pasteHtml:c,resetSelection:s,scrollIntoView:o}}]),angular.module("mentio").run(["$templateCache",function(e){e.put("mentio-menu.tpl.html",'\r\n')}]);
\ No newline at end of file
diff --git a/src/mentio.directive.js b/src/mentio.directive.js
index 455bff0..a461d06 100644
--- a/src/mentio.directive.js
+++ b/src/mentio.directive.js
@@ -536,9 +536,11 @@ angular.module('mentio', [])
};
},
- link: function (scope, element) {
- element[0].parentNode.removeChild(element[0]);
- $document[0].body.appendChild(element[0]);
+ link: function (scope, element, attrs) {
+ if (attrs.mentioApplyElement === undefined) {
+ element[0].parentNode.removeChild(element[0]);
+ $document[0].body.appendChild(element[0]);
+ }
scope.menuElement = element; // for testing
if (scope.parentScope) {
@@ -606,7 +608,7 @@ angular.module('mentio', [])
scope.adjustScroll = function (direction) {
var menuEl = element[0];
var menuItemsList = menuEl.querySelector('ul');
- var menuItem = (menuEl.querySelector('[mentio-menu-item].active') ||
+ var menuItem = (menuEl.querySelector('[mentio-menu-item].active') ||
menuEl.querySelector('[data-mentio-menu-item].active'));
if (scope.isFirstItemActive()) {
diff --git a/src/mentio.service.js b/src/mentio.service.js
index 0f0b85f..f7d0012 100644
--- a/src/mentio.service.js
+++ b/src/mentio.service.js
@@ -12,9 +12,9 @@ angular.module('mentio')
if (selectedElementIsTextAreaOrInput(ctx)) {
coordinates = getTextAreaOrInputUnderlinePosition(ctx, getDocument(ctx).activeElement,
- mentionInfo.mentionPosition);
+ mentionInfo.mentionPosition, selectionEl);
} else {
- coordinates = getContentEditableCaretPosition(ctx, mentionInfo.mentionPosition);
+ coordinates = getContentEditableCaretPosition(ctx, mentionInfo.mentionPosition, selectionEl);
}
// Move the button into place.
@@ -174,7 +174,7 @@ angular.module('mentio')
}
// public
- function replaceTriggerText (ctx, targetElement, path, offset, triggerCharSet,
+ function replaceTriggerText (ctx, targetElement, path, offset, triggerCharSet,
text, requireLeadingSpace, hasTrailingSpace) {
resetSelection(ctx, targetElement, path, offset);
@@ -297,7 +297,7 @@ angular.module('mentio')
// public
function getTriggerInfo (ctx, triggerCharSet, requireLeadingSpace, menuAlreadyActive, hasTrailingSpace) {
/*jshint maxcomplexity:11 */
- // yes this function needs refactoring
+ // yes this function needs refactoring
var selected, path, offset;
if (selectedElementIsTextAreaOrInput(ctx)) {
selected = getDocument(ctx).activeElement;
@@ -326,7 +326,7 @@ angular.module('mentio')
(
mostRecentTriggerCharPos === 0 ||
!requireLeadingSpace ||
- /[\xA0\s]/g.test
+ /[([\-\xA0\s]/g.test
(
effectiveRange.substring(
mostRecentTriggerCharPos - 1,
@@ -348,7 +348,7 @@ angular.module('mentio')
if (hasTrailingSpace) {
currentTriggerSnippet = currentTriggerSnippet.trim();
}
- if (!leadingSpace && (menuAlreadyActive || !(/[\xA0\s]/g.test(currentTriggerSnippet)))) {
+ if (!leadingSpace) {
return {
mentionPosition: mostRecentTriggerCharPos,
mentionText: currentTriggerSnippet,
@@ -398,7 +398,7 @@ angular.module('mentio')
return text;
}
- function getContentEditableCaretPosition (ctx, selectedNodePosition) {
+ function getContentEditableCaretPosition (ctx, selectedNodePosition, selectionEl) {
var markerTextChar = '\ufeff';
var markerEl, markerId = 'sel_' + new Date().getTime() + '_' + Math.random().toString().substr(2);
@@ -425,7 +425,12 @@ angular.module('mentio')
top: markerEl.offsetHeight
};
- localToGlobalCoordinates(ctx, markerEl, coordinates);
+ if (selectionEl[0].parentNode === document.body) {
+ localToGlobalCoordinates(ctx, markerEl, coordinates);
+ } else {
+ coordinates.left += markerEl.offsetLeft;
+ coordinates.top += markerEl.offsetTop;
+ }
markerEl.parentNode.removeChild(markerEl);
return coordinates;
@@ -442,7 +447,7 @@ angular.module('mentio')
obj = iframe;
iframe = null;
}
- }
+ }
obj = element;
iframe = ctx ? ctx.iframe : null;
while(obj !== getDocument().body) {
@@ -457,10 +462,10 @@ angular.module('mentio')
obj = iframe;
iframe = null;
}
- }
+ }
}
- function getTextAreaOrInputUnderlinePosition (ctx, element, position) {
+ function getTextAreaOrInputUnderlinePosition (ctx, element, position, selectionEl) {
var properties = [
'direction',
'boxSizing',
@@ -538,7 +543,12 @@ angular.module('mentio')
left: span.offsetLeft + parseInt(computed.borderLeftWidth)
};
- localToGlobalCoordinates(ctx, element, coordinates);
+ if (selectionEl[0].parentNode === document.body) {
+ localToGlobalCoordinates(ctx, element, coordinates);
+ } else {
+ coordinates.left += element.offsetLeft;
+ coordinates.top += element.offsetTop;
+ }
getDocument(ctx).body.removeChild(div);