From: Alexander Ebert Date: Fri, 4 Jul 2014 11:34:08 +0000 (+0200) Subject: Improved Redactor integration and resolved a few issues X-Git-Tag: 2.1.0_Alpha_1~627 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=c62197d6074592bfafd51f98e82e1157a38aa602;p=GitHub%2FWoltLab%2FWCF.git Improved Redactor integration and resolved a few issues --- diff --git a/wcfsetup/install/files/js/3rdParty/redactor/plugins/wbbcode.js b/wcfsetup/install/files/js/3rdParty/redactor/plugins/wbbcode.js index 6d8aa998b1..4745e72e20 100644 --- a/wcfsetup/install/files/js/3rdParty/redactor/plugins/wbbcode.js +++ b/wcfsetup/install/files/js/3rdParty/redactor/plugins/wbbcode.js @@ -36,6 +36,11 @@ RedactorPlugins.wbbcode = { html = html.replace(/

]+)?><\/p>/g, '

@@@wcf_empty_line@@@

'); return $mpSyncClean.call(self, html); }; + + if (this.getOption('wAutosaveOnce')) { + this._saveTextToStorage(); + delete this.opts.wAutosaveOnce; + } }, /** @@ -143,7 +148,7 @@ RedactorPlugins.wbbcode = { var $parts = html.split(/(<\/?p>)/); var $tmp = ''; var $buffer = ''; - for (var $i = 1; $i < $parts.length; $i++) { + for (var $i = 0; $i < $parts.length; $i++) { var $part = $parts[$i]; if ($part == '

') { continue; @@ -158,7 +163,12 @@ RedactorPlugins.wbbcode = { $buffer = ''; } else { - $buffer += $part; + if ($i == 0) { + $tmp += $part; + } + else { + $buffer += $part; + } } } html = $tmp; @@ -306,8 +316,8 @@ RedactorPlugins.wbbcode = { html = html.replace(/<\/(ul|ol)>/gi, '[/list]'); // [table] - html = html.replace(/]*>/gi, '[table]'); - html = html.replace(/<\/table>/gi, '[/table]'); + html = html.replace(/]*>/gi, '[table]\n'); + html = html.replace(/<\/table>/gi, '[/table]\n'); // remove html = html.replace(/([\s\S]*?)<\/tbody>/, function(match, p1) { @@ -317,15 +327,15 @@ RedactorPlugins.wbbcode = { // remove empty s html = html.replace(/<\/tr>/gi, ''); // [tr] - html = html.replace(//gi, '[tr]'); - html = html.replace(/<\/tr>/gi, '[/tr]'); + html = html.replace(//gi, '[tr]\n'); + html = html.replace(/<\/tr>/gi, '[/tr]\n'); // [td]+[align] html = html.replace(/([\s\S]*?)<\/td>/gi, "[td][align=$1]$2[/align][/td]"); // [td] - html = html.replace(//gi, '[td]'); - html = html.replace(/<\/td>/gi, '[/td]'); + html = html.replace(/(\t)*/gi, '[td]'); + html = html.replace(/(\t)*<\/td>/gi, '[/td]\n'); // cache redactor's selection markers var $cachedMarkers = { }; diff --git a/wcfsetup/install/files/js/3rdParty/redactor/plugins/wmonkeypatch.js b/wcfsetup/install/files/js/3rdParty/redactor/plugins/wmonkeypatch.js index b77f4782db..a0dc282063 100644 --- a/wcfsetup/install/files/js/3rdParty/redactor/plugins/wmonkeypatch.js +++ b/wcfsetup/install/files/js/3rdParty/redactor/plugins/wmonkeypatch.js @@ -249,6 +249,82 @@ RedactorPlugins.wmonkeypatch = { this.$modal.children('.dialogContent').removeClass('dialogForm'); }, + tableInsert: function() + { + this.bufferSet(false); + + var rows = $('#redactor_table_rows').val(), + columns = $('#redactor_table_columns').val(), + $table_box = $('

'), + tableId = Math.floor(Math.random() * 99999), + $table = $('
'), + i, $row, z, $column; + + for (i = 0; i < rows; i++) + { + $row = $(''); + + for (z = 0; z < columns; z++) + { + $column = $('' + this.opts.invisibleSpace + ''); + + // set the focus to the first td + if (i === 0 && z === 0) + { + $column.append('' + this.opts.invisibleSpace + ''); + } + + $($row).append($column); + } + + $table.append($row); + } + + $table_box.append($table); + var html = $table_box.html(); + + if (this.opts.linebreaks === false && this.browser('mozilla')) + { + html += '

' + this.opts.invisibleSpace + '

'; + } + + this.modalClose(); + this.selectionRestore(); + + var current = this.getBlock() || this.getCurrent(); + + if (current && current.tagName != 'BODY') + { + // WoltLab fix for nested tables + if (current.tagName == 'TD') { + $(current).append(html); + } + else { + if (current.tagName == 'LI') + { + var current = $(current).closest('ul, ol'); + } + + $(current).after(html); + } + // WoltLab fix for nested tables + } + else + { + this.insertHtmlAdvanced(html, false); + } + + this.selectionRestore(); + + var table = this.$editor.find('#table' + tableId); + this.buttonActiveObserver(); + + table.find('span#selection-marker-1, inline#selection-marker-1').remove(); + table.removeAttr('id'); + + this.sync(); + }, + modalOpenedCallback: function() { // handle positioning of form submit controls var $heightDifference = 0; diff --git a/wcfsetup/install/files/js/3rdParty/redactor/plugins/woptions.js b/wcfsetup/install/files/js/3rdParty/redactor/plugins/woptions.js new file mode 100644 index 0000000000..6dc75715a4 --- /dev/null +++ b/wcfsetup/install/files/js/3rdParty/redactor/plugins/woptions.js @@ -0,0 +1,117 @@ +if (!RedactorPlugins) var RedactorPlugins = {}; + +/** + * Provides message option tabs for Redactor. + * + * @author Alexander Ebert + * @copyright 2001-2014 WoltLab GmbH + * @license GNU Lesser General Public License + */ +RedactorPlugins.woptions = { + /** + * list of message option elements + * @var object + */ + _messageOptions: { }, + + /** + * message option container + * @var jQuery + */ + _messageOptionContainer: null, + + /** + * navigation container + * @var jQuery + */ + _messageOptionNavigation: null, + + /** + * Initializes the RedactorPlugins.woptions plugin. + */ + init: function() { + var $options = this.getOption('wMessageOptions'); + if (!$options.length) { + return; + } + + this._messageOptionContainer = $('
').appendTo(this.$box); + this._messageOptionNavigation = $('').appendTo(this._messageOptionContainer).children('ul'); + + for (var $i = 0; $i < $options.length; $i++) { + var $container = $options[$i]; + + var $listItem = $('
  • ' + $container.title + '
  • ').appendTo(this._messageOptionNavigation); + $listItem.data('containerID', $container.containerID).click($.proxy(this._showMessageOptionContainer, this)); + + var $tabContainer = $('
    ').hide().appendTo(this._messageOptionContainer); + + for (var $j = 0; $j < $container.items.length; $j++) { + $($container.items[$j]).appendTo($tabContainer); + } + + this._messageOptions[$container.containerID] = { + container: $tabContainer, + listItem: $listItem + }; + } + + WCF.System.Event.fireEvent('com.woltlab.wcf.redactor', 'updateMessageOptions', this._messageOptions); + + WCF.System.Event.addListener('com.woltlab.wcf.redactor', 'reset', $.proxy(this._wOptionsListener, this)); + }, + + /** + * Toggles the specified message option container. + * + * @param object event + * @param string containerID + */ + _showMessageOptionContainer: function(event, containerID) { + var $containerID = (event === null) ? containerID : $(event.currentTarget).data('containerID'); + if (this._messageOptions[$containerID].listItem.hasClass('active')) { + this._messageOptions[$containerID].listItem.removeClass('active'); + this._messageOptions[$containerID].container.hide(); + + return; + } + + $.each(this._messageOptions, function(containerID, elements) { + if (containerID == $containerID) { + elements.listItem.addClass('active'); + elements.container.show(); + } + else { + elements.listItem.removeClass('active'); + elements.container.hide(); + } + }); + }, + + /** + * Collapses all message option containers. + * + * @param object data + */ + _wOptionsListener: function(data) { + $.each(this._messageOptions, function(containerID, elements) { + elements.listItem.removeClass('active'); + elements.container.hide(); + + elements.container.find('input, select, textarea').each(function(index, element) { + var $element = $(element); + switch ($element.getTagName()) { + case 'input': + $element.prop('checked', false); + break; + + default: + $element.val(''); + break; + } + }); + }); + + WCF.System.Event.fireEvent('com.woltlab.wcf.redactor', 'updateMessageOptions', this._messageOptions); + } +}; diff --git a/wcfsetup/install/files/js/3rdParty/redactor/plugins/wupload.js b/wcfsetup/install/files/js/3rdParty/redactor/plugins/wupload.js index efb570b1e1..c4b0c88d64 100644 --- a/wcfsetup/install/files/js/3rdParty/redactor/plugins/wupload.js +++ b/wcfsetup/install/files/js/3rdParty/redactor/plugins/wupload.js @@ -23,13 +23,15 @@ RedactorPlugins.wupload = { this.buttonAwesome('upload', 'fa-upload'); this._initAttachments(); + + WCF.System.Event.addListener('com.woltlab.wcf.redactor', 'reset', $.proxy(this._wUploadListener, this)); }, /** * Initializes the attachments user interface. */ _initAttachments: function() { - this._attachmentsContainer = $('
    ').hide().appendTo(this.$box); + this._attachmentsContainer = $('#redactorMessageOptions_attachments'); var $attachmentList = $('
      ').hide().appendTo(this._attachmentsContainer); $('
      ' + WCF.String.unescapeHTML(WCF.Language.get('wcf.attachment.upload.limits')) + '
      ').appendTo(this._attachmentsContainer); @@ -53,12 +55,18 @@ RedactorPlugins.wupload = { $listItem.appendTo($attachmentList); - this._attachmentsContainer.show(); $attachmentList.show(); } + + this._showMessageOptionContainer(null, 'attachments'); } new WCF.Attachment.Upload(this._attachmentsContainer.find('> dl > dd > div'), this._attachmentsContainer.children('ul'), $options.objectType, $options.objectID, $options.tmpHash, $options.parentObjectID, $options.maxCount, this.$source.wcfIdentify()); new WCF.Action.Delete('wcf\\data\\attachment\\AttachmentAction', '.formAttachmentList > li'); + }, + + _wUploadListener: function(data) { + this._attachmentsContainer.children('.formAttachmentList').hide().empty(); + this._attachmentsContainer.find('.jsButtonAttachmentInsertAll').hide(); } }; diff --git a/wcfsetup/install/files/js/3rdParty/redactor/plugins/wutil.js b/wcfsetup/install/files/js/3rdParty/redactor/plugins/wutil.js index 8e8b9f5d28..a480aa7dd5 100644 --- a/wcfsetup/install/files/js/3rdParty/redactor/plugins/wutil.js +++ b/wcfsetup/install/files/js/3rdParty/redactor/plugins/wutil.js @@ -25,7 +25,7 @@ RedactorPlugins.wutil = { this.autosaveEnable(); if (this.getOption('wautosave').saveOnInit || this.$source.data('saveOnInit')) { - this._saveTextToStorage(); + this.setOption('wAutosaveOnce', true); } else { this.autosaveRestore(); @@ -176,6 +176,8 @@ RedactorPlugins.wutil = { else { this.$source.val(''); } + + WCF.System.Event.fireEvent('com.woltlab.wcf.redactor', 'reset'); }, /** diff --git a/wcfsetup/install/files/js/WCF.Attachment.js b/wcfsetup/install/files/js/WCF.Attachment.js index 5c4c5f68f6..526c420bca 100644 --- a/wcfsetup/install/files/js/WCF.Attachment.js +++ b/wcfsetup/install/files/js/WCF.Attachment.js @@ -64,7 +64,7 @@ WCF.Attachment.Upload = WCF.Upload.extend({ this._makeSortable(); - this._insertAllButton = $('

      ' + WCF.Language.get('wcf.attachment.insertAll') + '

      ').hide().appendTo(this._buttonSelector); + this._insertAllButton = $('

      ' + WCF.Language.get('wcf.attachment.insertAll') + '

      ').hide().appendTo(this._buttonSelector); this._insertAllButton.click($.proxy(this._insertAll, this)); if (this._fileListSelector.children('li:not(.uploadFailed)').length) { diff --git a/wcfsetup/install/files/js/WCF.Message.js b/wcfsetup/install/files/js/WCF.Message.js index e9817577eb..d4de8dd23b 100644 --- a/wcfsetup/install/files/js/WCF.Message.js +++ b/wcfsetup/install/files/js/WCF.Message.js @@ -787,6 +787,38 @@ WCF.Message.QuickReply = Class.extend({ $parameters.anchor = this._container.data('anchor'); } + // check for additional settings + var $container = $('#redactorMessageOptions_settings'); + if ($container.length) { + $parameters.settings = { }; + $container.find('input, textarea, select').each(function(index, element) { + var $element = $(element); + switch ($element.getTagName()) { + case 'input': + switch ($element.prop('type')) { + case 'checkbox': + case 'radio': + if ($element.is(':checked')) { + $parameters.settings[$element.prop('name')] = $element.val(); + } + else if ($element.data('submitEmpty')) { + $parameters.settings[$element.prop('name')] = 0; + } + break; + + default: + $parameters.settings[$element.prop('name')] = $element.val(); + break; + } + break; + + default: + $parameters.settings[$element.prop('name')] = $element.val(); + break; + } + }); + } + return $parameters; }, diff --git a/wcfsetup/install/files/js/WCF.User.js b/wcfsetup/install/files/js/WCF.User.js index b5b13467a0..b0fc3ad9b6 100644 --- a/wcfsetup/install/files/js/WCF.User.js +++ b/wcfsetup/install/files/js/WCF.User.js @@ -2694,6 +2694,8 @@ WCF.User.ObjectWatch.Subscribe = Class.extend({ var $objectID = $button.data('objectID'); this._buttons[$objectID] = $button.click($.proxy(this._click, this)); }, this)); + + WCF.System.Event.addListener('com.woltlab.wcf.objectWatch', 'update', $.proxy(this._updateSubscriptionStatus, this)); }, /** @@ -2759,14 +2761,11 @@ WCF.User.ObjectWatch.Subscribe = Class.extend({ else if (data.actionName === 'saveSubscription' && this._dialog.is(':visible')) { this._dialog.wcfDialog('close'); - // update icon - var $icon = $(this._buttonSelector + '[data-object-id=' + data.returnValues.objectID + '] > .icon'); - if (data.returnValues.subscribe) { - $icon.removeClass('icon-bookmark-empty').addClass('icon-bookmark'); - } - else { - $icon.removeClass('icon-bookmark').addClass('icon-bookmark-empty'); - } + this._updateSubscriptionStatus({ + isSubscribed: data.returnValues.subscribe, + objectID: data.returnValues.objectID + }); + // show notification if (this._notification === null) { @@ -2798,6 +2797,26 @@ WCF.User.ObjectWatch.Subscribe = Class.extend({ } }); this._proxy.sendRequest(); + }, + + /** + * Updates subscription status and icon. + * + * @param object data + */ + _updateSubscriptionStatus: function(data) { + var $button = $(this._buttonSelector + '[data-object-id=' + data.objectID + ']'); + var $icon = $button.children('.icon'); + if (data.isSubscribed) { + $icon.removeClass('icon-bookmark-empty').addClass('icon-bookmark'); + $button.data('isSubscribed', true); + } + else { + $icon.removeClass('icon-bookmark').addClass('icon-bookmark-empty'); + $button.data('isSubscribed', false); + } + + WCF.System.Event.fireEvent('com.woltlab.wcf.objectWatch', 'updatedSubscription', data); } }); diff --git a/wcfsetup/install/files/js/WCF.js b/wcfsetup/install/files/js/WCF.js index 1cfb4203a4..a3f55a1e06 100755 --- a/wcfsetup/install/files/js/WCF.js +++ b/wcfsetup/install/files/js/WCF.js @@ -7650,7 +7650,54 @@ WCF.System.PushNotification = { } } } -} +}; + +/** + * System-wide event system. + */ +WCF.System.Event = { + /** + * list of event listeners grouped by identifier and action. + * @var object + */ + _listeners: { }, + + /** + * Registers a new event listener. + * + * @param string identifier + * @param string action + * @param object listener + */ + addListener: function(identifier, action, listener) { + if (typeof this._listeners[identifier] === 'undefined') { + this._listeners[identifier] = { }; + } + + if (typeof this._listeners[identifier][action] === 'undefined') { + this._listeners[identifier][action] = [ ]; + } + + this._listeners[identifier][action].push(listener); + }, + + /** + * Fires a new event and notifies all registered event listeners. + * + * @param string identifier + * @param string action + * @param object data + */ + fireEvent: function(identifier, action, data) { + data = data || { }; + + if (this._listeners[identifier] && this._listeners[identifier][action]) { + for (var $i = 0; $i < this._listeners[identifier][action].length; $i++) { + this._listeners[identifier][action][$i](data); + } + } + } +}; /** * Worker support for frontend based upon DatabaseObjectActions.