Some cleanup
authorAlexander Ebert <ebert@woltlab.com>
Sun, 29 May 2016 17:48:49 +0000 (19:48 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Sun, 29 May 2016 17:48:56 +0000 (19:48 +0200)
wcfsetup/install/files/js/WCF.Message.js
wcfsetup/install/files/js/WoltLab/WCF/Ui/Message/InlineEditor.js

index 900fd94df7431d4153434abf2faf64552e1424cd..aea6dce9f16c708899ee9a2d1a82c0a64c0fac63 100644 (file)
@@ -764,9 +764,7 @@ WCF.Message.InlineEditor = Class.extend({
         */
        init: function(containerID, supportExtendedForm, quoteManager) {
                require(['WoltLab/WCF/Ui/Message/InlineEditor'], (function(UiMessageInlineEditor) {
-                       UiMessageInlineEditor.init({
-                               extendedForm: (supportExtendedForm === true),
-                               
+                       new UiMessageInlineEditor({
                                className: this._getClassName(),
                                containerId: containerID,
                                editorPrefix: this._messageEditorIDPrefix,
@@ -2516,477 +2514,11 @@ WCF.Message.Share.Page = Class.extend({
 });
 
 /**
- * Handles user mention suggestions in Redactor instances.
- * 
- * Important: Objects of this class have to be created before Redactor
- * is initialized!
+ * @deprecated 2.2
  */
 WCF.Message.UserMention = Class.extend({
-       /**
-        * current caret position
-        * @var DOMRange
-        */
-       _caretPosition: null,
-       
-       /**
-        * name of the class used to get the user suggestions
-        * @var string
-        */
-       _className: 'wcf\\data\\user\\UserAction',
-       
-       /**
-        * dropdown object
-        * @var jQuery
-        */
-       _dropdown: null,
-       
-       /**
-        * dropdown menu object
-        * @var jQuery
-        */
-       _dropdownMenu: null,
-       
-       /**
-        * suggestion item index, -1 if none is selected
-        * @var integer
-        */
-       _itemIndex: -1,
-       
-       /**
-        * line height
-        * @var integer
-        */
-       _lineHeight: null,
-       
-       /**
-        * current beginning of the mentioning
-        * @var string
-        */
-       _mentionStart: '',
-       
-       /**
-        * redactor instance object
-        * @var $.Redactor
-        */
-       _redactor: null,
-       
-       /**
-        * delay timer to only send requests after user paused typing
-        * @var WCF.PeriodicalExecuter
-        */
-       _timer: null,
-       
-       /**
-        * Initalizes user suggestions for Redactor with the given textarea id.
-        * 
-        * @param       string          wysiwygSelector
-        */
-       init: function(wysiwygSelector) {
-               if ($.browser.mobile && $.browser.mozilla) {
-                       // the desktop Firefox work-arounds do not work on Firefox for Android, in fact they crash it
-                       return;
-               }
-               
-               this._textarea = $('#' + wysiwygSelector);
-               this._redactor = this._textarea.redactor('core.getObject');
-               
-               this._dropdown = this._textarea.redactor('core.getEditor');
-               this._dropdownMenu = $('<ul class="dropdownMenu userSuggestionList" />').appendTo(this._textarea.parent());
-               WCF.Dropdown.initDropdownFragment(this._dropdown, this._dropdownMenu);
-               
-               this._proxy = new WCF.Action.Proxy({
-                       autoAbortPrevious: true,
-                       success: $.proxy(this._success, this)
-               });
-               
-               WCF.System.Event.addListener('com.woltlab.wcf.redactor', 'keydown_' + wysiwygSelector, $.proxy(this._keydown, this));
-               WCF.System.Event.addListener('com.woltlab.wcf.redactor', 'keyup_' + wysiwygSelector, $.proxy(this._keyup, this));
-       },
-       
-       /**
-        * Clears the suggestion list.
-        */
-       _clearList: function() {
-               this._hideList();
-               
-               this._dropdownMenu.empty();
-       },
-       
-       /**
-        * Handles a click on a list item suggesting a username.
-        * 
-        * This function is also called when seleting a suggested username by clicking
-        * enter.
-        * 
-        * @param       object          event
-        */
-       _click: function(event) {
-               // in Firefox, this._caretPosition does not have the text node as
-               // startContainer anymore when confirming a username suggestion by
-               // clicking enter, thus we need to manually adjust it
-               if ($.browser.mozilla && this._caretPosition.startContainer.nodeName == 'P') {
-                       var $textNode = this._caretPosition.startContainer.childNodes[this._caretPosition.startOffset - 1];
-                       
-                       this._caretPosition = document.createRange();
-                       this._caretPosition.selectNodeContents($textNode);
-                       this._caretPosition.collapse();
-               }
-               
-               // restore caret position
-               this._redactor.wutil.replaceRangesWith(this._caretPosition);
-               
-               this._setUsername($(event.currentTarget).data('username'));
-       },
-       
-       /**
-        * Creates an item in the suggestion list with the given data.
-        * 
-        * @return      object
-        */
-       _createListItem: function(listItemData) {
-               var $listItem = $('<li />').data('username', listItemData.label).click($.proxy(this._click, this)).appendTo(this._dropdownMenu);
-               
-               var $box16 = $('<div />').addClass('box16').appendTo($listItem);
-               $box16.append($(listItemData.icon));
-               $box16.append($('<div />').append($('<span />').text(listItemData.label)));
-       },
-       
-       /**
-        * Returns the offsets used to set the position of the user suggestion
-        * dropdown.
-        * 
-        * @return      object
-        */
-       _getDropdownMenuPosition: function() {
-               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.wutil.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()
-               };
-               
-               if (this._lineHeight === null) {
-                       this._lineHeight = Math.round($rect.bottom - $rect.top);
-               }
-               
-               // restore caret position
-               this._redactor.wutil.replaceRangesWith($orgRange);
-               this._caretPosition = $orgRange;
-               
-               return $offsets;
-       },
-       
-       /**
-        * Replaces the started mentioning with a chosen username.
-        */
-       _setUsername: function(username) {
-               if (this._timer !== null) {
-                       this._timer.stop();
-                       this._timer = null;
-               }
-               this._proxy.abortPrevious();
-               
-               var $orgRange = getSelection().getRangeAt(0).cloneRange();
-               
-               // allow redactor to undo this
-               this._redactor.buffer.set();
-               
-               var $startContainer = $orgRange.startContainer;
-               var $startOffset = $orgRange.startOffset - (this._mentionStart.length + 1);
-               
-               // navigating with the keyboard before hitting enter will cause the text node to be split
-               if ($startOffset < 0) {
-                       $startContainer = $startContainer.previousSibling;
-                       $startOffset = $startContainer.length - (this._mentionStart.length + 1) - ($orgRange.startOffset - 1);
-               }
-               
-               var $newRange = document.createRange();
-               $newRange.setStart($startContainer, $startOffset);
-               $newRange.setEnd($orgRange.startContainer, $orgRange.startOffset);
-               
-               this._redactor.wutil.replaceRangesWith($newRange);
-               
-               var $range = getSelection().getRangeAt(0);
-               $range.deleteContents();
-               $range.collapse(true);
-               
-               // insert username
-               if (username.indexOf("'") !== -1) {
-                       username = username.replace(/'/g, "''");
-               }
-               username = "'" + username + "'";
-               
-               // use native API to prevent issues in Internet Explorer
-               var $text = document.createTextNode('@' + username);
-               $range.insertNode($text);
-               
-               var $newRange = document.createRange();
-               $newRange.setStart($text, username.length + 1);
-               $newRange.setEnd($text, username.length + 1);
-               
-               this._redactor.wutil.replaceRangesWith($newRange);
-               
-               this._hideList();
-       },
-       
-       /**
-        * Returns the parameters for the AJAX request.
-        * 
-        * @return      object
-        */
-       _getParameters: function() {
-               return {
-                       data: {
-                               includeUserGroups: false,
-                               searchString: this._mentionStart
-                       }
-               };
-       },
-       
-       /**
-        * Returns the relevant text in front of the caret in the current line.
-        * 
-        * @return      string
-        */
-       _getTextLineInFrontOfCaret: function() {
-               // if text is marked, user suggestions are disabled
-               if (this._redactor.selection.getHtml().length) {
-                       return '';
-               }
-               
-               var $range = getSelection().getRangeAt(0);
-               
-               // in Firefox, blurring and refocusing the browser creates separate
-               // text nodes
-               if ($.browser.mozilla && $range.startContainer.nodeType == 3) {
-                       $range.startContainer.parentNode.normalize();
-               }
-               
-               var $text = $range.startContainer.textContent.substr(0, $range.startOffset);
-               
-               // remove unicode zero width space and non-breaking space
-               var $textBackup = $text;
-               $text = '';
-               var $hadSpace = false;
-               for (var $i = 0; $i < $textBackup.length; $i++) {
-                       var $byte = $textBackup.charCodeAt($i).toString(16);
-                       if ($byte != '200b' && (!/\s/.test($textBackup[$i]) || (($byte == 'a0' || $byte == '20') && !$hadSpace))) {
-                               if ($byte == 'a0' || $byte == '20') {
-                                       $hadSpace = true;
-                               }
-                               
-                               if ($textBackup[$i] === '@' && $i && /\s/.test($textBackup[$i - 1])) {
-                                       $hadSpace = false;
-                                       $text = '';
-                               }
-                               
-                               $text += $textBackup[$i];
-                       }
-                       else {
-                               $hadSpace = false;
-                               $text = '';
-                       }
-               }
-               
-               return $text;
-       },
-       
-       /**
-        * Hides the suggestion list.
-        */
-       _hideList: function() {
-               this._dropdown.removeClass('dropdownOpen');
-               this._dropdownMenu.removeClass('dropdownOpen');
-               
-               this._itemIndex = -1;
-       },
-       
-       /**
-        * Handles the keydown event to check if the user starts mentioning someone.
-        * 
-        * @param       object          data
-        */
-       _keydown: function(data) {
-               if (this._redactor.wutil.inPlainMode()) {
-                       return;
-               }
-               
-               if (this._dropdownMenu.is(':visible')) {
-                       switch (data.event.which) {
-                               case $.ui.keyCode.ENTER:
-                                       data.event.preventDefault();
-                                       data.cancel = true;
-                                       
-                                       this._dropdownMenu.children('li').eq(this._itemIndex).trigger('click');
-                               break;
-                               
-                               case $.ui.keyCode.UP:
-                                       data.cancel = true;
-                                       data.event.preventDefault();
-                                       
-                                       this._selectItem(this._itemIndex - 1);
-                               break;
-                               
-                               case $.ui.keyCode.DOWN:
-                                       data.cancel = true;
-                                       data.event.preventDefault();
-                                       
-                                       this._selectItem(this._itemIndex + 1);
-                               break;
-                       }
-               }
-       },
-       
-       /**
-        * Handles the keyup event to check if the user starts mentioning someone.
-        * 
-        * @param       object          data
-        */
-       _keyup: function(data) {
-               if (this._redactor.wutil.inPlainMode()) {
-                       return true;
-               }
-               
-               // abort previous search requests
-               if (this._timer !== null) {
-                       this._timer.stop();
-                       this._timer = null;
-               }
-               this._proxy.abortPrevious();
-               
-               // ignore enter key up event
-               if (data.event.which === $.ui.keyCode.ENTER) {
-                       return;
-               }
-               
-               // ignore event if suggestion list and user pressed enter, arrow up or arrow down
-               if (this._dropdownMenu.is(':visible') && data.event.which in { 13:1, 38:1, 40:1 }) {
-                       return;
-               }
-               
-               var $currentText = this._getTextLineInFrontOfCaret();
-               if ($currentText) {
-                       var $match = $currentText.match(/@([^,]{3,})$/);
-                       if ($match) {
-                               // if mentioning is at text begin or there's a whitespace character
-                               // before the '@', everything is fine
-                               if (!$match.index || $currentText[$match.index - 1].match(/\s/)) {
-                                       this._mentionStart = $match[1];
-                                       
-                                       if (this._timer !== null) {
-                                               this._timer.stop();
-                                       }
-                                       
-                                       this._timer = new WCF.PeriodicalExecuter($.proxy(function() {
-                                               this._proxy.setOption('data', {
-                                                       actionName: 'getSearchResultList',
-                                                       className: this._className,
-                                                       interfaceName: 'wcf\\data\\ISearchAction',
-                                                       parameters: this._getParameters()
-                                               });
-                                               this._proxy.sendRequest();
-                                               
-                                               this._timer.stop();
-                                               this._timer = null;
-                                       }, this), 500);
-                               }
-                       }
-                       else {
-                               this._hideList();
-                       }
-               }
-               else {
-                       this._hideList();
-               }
-       },
-       
-       /**
-        * Selects the suggestion with the given item index.
-        * 
-        * @param       integer         itemIndex
-        */
-       _selectItem: function(itemIndex) {
-               var $li = this._dropdownMenu.children('li');
-               
-               if (itemIndex < 0) {
-                       itemIndex = $li.length - 1;
-               }
-               else if (itemIndex + 1 > $li.length) {
-                       itemIndex = 0;
-               }
-               
-               $li.removeClass('dropdownNavigationItem');
-               $li.eq(itemIndex).addClass('dropdownNavigationItem');
-               
-               this._itemIndex = itemIndex;
-       },
-       
-       /**
-        * Shows the suggestion list.
-        */
-       _showList: function() {
-               this._dropdown.addClass('dropdownOpen');
-               this._dropdownMenu.addClass('dropdownOpen');
-       },
-       
-       /**
-        * Evalutes user suggestion-AJAX request results.
-        * 
-        * @param       object          data
-        * @param       string          textStatus
-        * @param       jQuery          jqXHR
-        */
-       _success: function(data, textStatus, jqXHR) {
-               this._clearList(false);
-               
-               if ($.getLength(data.returnValues)) {
-                       for (var $i in data.returnValues) {
-                               var $item = data.returnValues[$i];
-                               this._createListItem($item);
-                       }
-                       
-                       this._updateSuggestionListPosition();
-                       this._showList();
-               }
-       },
-       
-       /**
-        * Updates the position of the suggestion list.
-        */
-       _updateSuggestionListPosition: function() {
-               try {
-                       var $dropdownMenuPosition = this._getDropdownMenuPosition();
-                       $dropdownMenuPosition.top += 5; // add a little vertical gap
-                       
-                       this._dropdownMenu.css($dropdownMenuPosition);
-                       this._selectItem(0);
-                       
-                       if ($dropdownMenuPosition.top + this._dropdownMenu.outerHeight() + 10 > $(window).height() + $(document).scrollTop()) {
-                               this._dropdownMenu.addClass('dropdownArrowBottom');
-                               
-                               this._dropdownMenu.css({
-                                       top: $dropdownMenuPosition.top - this._dropdownMenu.outerHeight() - 2 * this._lineHeight + 5
-                               });
-                       }
-                       else {
-                               this._dropdownMenu.removeClass('dropdownArrowBottom');
-                       }
-               }
-               catch (e) {
-                       // ignore errors that are caused by pressing enter to
-                       // often in a short period of time
-               }
+       init: function() {
+               throw new Error("Support for mentions in Redactor are now enabled by adding the attribute 'data-support-mention=\"true\"' to the textarea element.");
        }
 });
 
index 3774e80188d6f9c01e6a0d0f939567c8ed05074f..c25c0b5627acd3e1bb91cb2755c482634fd2923c 100644 (file)
@@ -2,7 +2,7 @@
  * Flexible message inline editor.
  * 
  * @author     Alexander Ebert
- * @copyright  2001-2015 WoltLab GmbH
+ * @copyright  2001-2016 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @module     WoltLab/WCF/Ui/Message/InlineEditor
  */
@@ -37,7 +37,6 @@ define(
                        this._elements = new ObjectMap();
                        this._options = Core.extend({
                                canEditInline: false,
-                               extendedForm: true,
                                
                                className: '',
                                containerId: 0,
@@ -341,11 +340,6 @@ define(
                        var buttonSave = elBySel('button[data-type="save"]', formSubmit);
                        buttonSave.addEventListener('click', this._save.bind(this));
                        
-                       if (this._options.extendedForm) {
-                               var buttonExtended = elBySel('button[data-type="extended"]', formSubmit);
-                               buttonExtended.addEventListener('click', this._prepareExtended.bind(this));
-                       }
-                       
                        var buttonCancel = elBySel('button[data-type="cancel"]', formSubmit);
                        buttonCancel.addEventListener('click', this._restoreMessage.bind(this));
                        
@@ -470,27 +464,6 @@ define(
                        }
                },
                
-               /**
-                * Initiates the jump to the extended edit form.
-                * 
-                * @protected
-                */
-               _prepareExtended: function() {
-                       var data = {
-                               actionName: 'jumpToExtended',
-                               parameters: {
-                                       containerID: this._options.containerId,
-                                       message: '',
-                                       messageID: this._getObjectId(this._activeElement)
-                               }
-                       };
-                       
-                       var id = this._getEditorId();
-                       EventHandler.fire('com.woltlab.wcf.redactor', 'getText_' + id, data.parameters);
-                       
-                       Ajax.api(this, data);
-               },
-               
                /**
                 * Hides the editor from view.
                 * 
@@ -608,10 +581,6 @@ define(
                                        this._showEditor(data);
                                        break;
                                        
-                               case 'jumpToExtended':
-                                       window.location = data.returnValues.url;
-                                       break;
-                               
                                case 'save':
                                        this._showMessage(data);
                                        break;