* @return object
*/
_getDropdownMenuPosition: function() {
- var $range = this._redactor.getSelection().getRangeAt(0);
- var $startOffset = $range.startOffset;
+ var $orgRange = getSelection().getRangeAt(0).cloneRange();
+
+ // mark the entire text, starting from the '@' to the current cursor position
+ var $newRange = document.createRange();
+ $newRange.setStart($orgRange.startContainer, $orgRange.startOffset - (this._mentionStart.length + 1));
+ $newRange.setEnd($orgRange.startContainer, $orgRange.startOffset);
+
+ this._redactor.replaceRangesWith($newRange);
+
+ // get the offsets of the bounding box of current text selection
+ var $range = getSelection().getRangeAt(0);
+ var $rect = $range.getBoundingClientRect();
+ var $window = $(window);
+ var $offsets = {
+ top: Math.round($rect.bottom) + $window.scrollTop(),
+ left: Math.round($rect.left) + $window.scrollLeft()
+ };
- $range.setStart($range.startContainer, $range.startOffset - this._mentionStart.length);
- $range.collapse(true);
+ if (this._lineHeight === null) {
+ this._lineHeight = Math.round($rect.bottom - $rect.top);
+ }
- var $element = document.createElement('span');
- $range.insertNode($element);
+ // restore caret position
+ this._redactor.replaceRangesWith($orgRange);
- var $jElement = $($element);
- var $offsets = $jElement.offset();
- if (this._lineHeight === null) {
- this._lineHeight = $jElement.height();
+ return $offsets;
+ },
+
+ /**
+ * Replaces the started mentioning with a chosen username.
+ */
+ _setUsername: function(username) {
+ var $orgRange = getSelection().getRangeAt(0).cloneRange();
+
+ // allow redactor to undo this
+ this._redactor.bufferSet();
+
+ var $newRange = document.createRange();
+ $newRange.setStart($orgRange.startContainer, $orgRange.startOffset - (this._mentionStart.length + 1));
+ $newRange.setEnd($orgRange.startContainer, $orgRange.startOffset);
+
+ this._redactor.replaceRangesWith($newRange);
+
+ var $range = getSelection().getRangeAt(0);
+ $range.deleteContents();
+ $range.collapse(true);
+
+ // insert username
+ if (username.indexOf("'") !== -1) {
+ username = username.replace(/'/g, "''");
+ username = "'" + username + "'";
+ }
+ else if (username.indexOf(' ') !== -1) {
+ username = "'" + username + "'";
}
- $jElement.remove();
+ // use native API to prevent issues in Internet Explorer
+ var $text = document.createTextNode('@' + username);
+ $range.insertNode($text);
- // inserting the node caused the text node to be split, merge them again
- // using stupid DOM manipulation since .normalize() is broken in Internet Explorer 11
- $range.startContainer.nodeValue += $range.startContainer.nextSibling.textContent;
- $range.startContainer.parentNode.removeChild($range.startContainer.nextSibling);
+ var $newRange = document.createRange();
+ $newRange.setStart($text, username.length + 1);
+ $newRange.setEnd($text, username.length + 1);
- // move to end of node
- $range.setEnd($range.startContainer, $startOffset);
- $range.collapse(false);
+ this._redactor.replaceRangesWith($newRange);
- return $offsets;
+ this._hideList();
},
/**
}
},
- /**
- * Replaces the started mentioning with a chosen username.
- */
- _setUsername: function(username) {
- // allow redactor to undo this
- this._redactor.bufferSet();
-
- var $range = this._redactor.getSelection().getRangeAt(0);
- $range.setStart($range.startContainer, $range.startOffset - this._mentionStart.length);
- $range.deleteContents();
- $range.collapse(true);
-
- // insert username
- if (username.indexOf("'") !== -1) {
- username = username.replace(/'/g, "''");
- username = "'" + username + "'";
- }
- else if (username.indexOf(' ') !== -1) {
- username = "'" + username + "'";
- }
-
- // use native API to prevent issues in Internet Explorer
- var $text = document.createTextNode(username);
- $range.insertNode($text);
-
- this._hideList();
- },
-
/**
* Selects the suggestion with the given item index.
*
* Updates the position of the suggestion list.
*/
_updateSuggestionListPosition: function() {
- //try {
+ try {
var $dropdownMenuPosition = this._getDropdownMenuPosition();
- $dropdownMenuPosition.top += 5 + this._lineHeight; // add little vertical gap
- $dropdownMenuPosition.left -= 16;
+ $dropdownMenuPosition.top += 5; // add a little vertical gap
+
this._dropdownMenu.css($dropdownMenuPosition);
this._selectItem(0);
else {
this._dropdownMenu.removeClass('dropdownArrowBottom');
}
- /*}
+ }
catch (e) {
// ignore errors that are caused by pressing enter to
// often in a short period of time
- }*/
+ }
}
});