From 857ed85d5daa2fb4129470dc563a0956ee6514a7 Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Sat, 30 May 2015 21:21:11 +0200 Subject: [PATCH] Overhauled clipboard API (both PHP and JS) --- wcfsetup/install/files/js/WCF.js | 581 +----------------- .../js/WoltLab/WCF/Controller/Clipboard.js | 558 +++++++++++++++++ .../lib/action/ClipboardAction.class.php | 177 ------ .../ClipboardLoadMarkedItemsAction.class.php | 44 -- .../lib/action/ClipboardProxyAction.class.php | 143 ----- .../AbstractDatabaseObjectAction.class.php | 2 +- .../item/ClipboardItemAction.class.php | 190 ++++++ .../clipboard/ClipboardHandler.class.php | 16 +- .../action/AbstractClipboardAction.class.php | 7 - .../action/IClipboardAction.class.php | 10 - 10 files changed, 762 insertions(+), 966 deletions(-) create mode 100644 wcfsetup/install/files/js/WoltLab/WCF/Controller/Clipboard.js delete mode 100644 wcfsetup/install/files/lib/action/ClipboardAction.class.php delete mode 100644 wcfsetup/install/files/lib/action/ClipboardLoadMarkedItemsAction.class.php delete mode 100644 wcfsetup/install/files/lib/action/ClipboardProxyAction.class.php create mode 100644 wcfsetup/install/files/lib/data/clipboard/item/ClipboardItemAction.class.php diff --git a/wcfsetup/install/files/js/WCF.js b/wcfsetup/install/files/js/WCF.js index 57cd0022b4..68687d7b4f 100755 --- a/wcfsetup/install/files/js/WCF.js +++ b/wcfsetup/install/files/js/WCF.js @@ -1400,68 +1400,10 @@ WCF.Dropdown.Interactive.Instance = Class.extend({ /** * Clipboard API + * + * @deprecated 2.2 - please use `WoltLab/WCF/Controller/Clipboard` instead */ WCF.Clipboard = { - /** - * action proxy object - * @var WCF.Action.Proxy - */ - _actionProxy: null, - - /** - * action objects - * @var object - */ - _actionObjects: {}, - - /** - * list of clipboard containers - * @var jQuery - */ - _containers: null, - - /** - * container meta data - * @var object - */ - _containerData: { }, - - /** - * user has marked items - * @var boolean - */ - _hasMarkedItems: false, - - /** - * list of ids of marked objects grouped by object type - * @var object - */ - _markedObjectIDs: { }, - - /** - * current page - * @var string - */ - _page: '', - - /** - * current page's object id - * @var integer - */ - _pageObjectID: 0, - - /** - * proxy object - * @var WCF.Action.Proxy - */ - _proxy: null, - - /** - * list of elements already tracked for clipboard actions - * @var object - */ - _trackedElements: { }, - /** * Initializes the clipboard API. * @@ -1471,52 +1413,12 @@ WCF.Clipboard = { * @param integer pageObjectID */ init: function(page, hasMarkedItems, actionObjects, pageObjectID) { - this._page = page; - this._actionObjects = actionObjects || { }; - this._hasMarkedItems = (hasMarkedItems > 0); - this._pageObjectID = parseInt(pageObjectID) || 0; - - this._actionProxy = new WCF.Action.Proxy({ - success: $.proxy(this._actionSuccess, this), - url: 'index.php/ClipboardProxy/?t=' + SECURITY_TOKEN + SID_ARG_2ND - }); - - this._proxy = new WCF.Action.Proxy({ - success: $.proxy(this._success, this), - url: 'index.php/Clipboard/?t=' + SECURITY_TOKEN + SID_ARG_2ND - }); - - // init containers first - this._containers = $('.jsClipboardContainer').each($.proxy(function(index, container) { - this._initContainer(container); - }, this)); - - // loads marked items - if (this._hasMarkedItems && this._containers.length) { - this._loadMarkedItems(); - } - - var self = this; - WCF.DOMNodeInsertedHandler.addCallback('WCF.Clipboard', function() { - self._containers = $('.jsClipboardContainer').each($.proxy(function(index, container) { - self._initContainer(container); - }, self)); - }); - }, - - /** - * Loads marked items on init. - */ - _loadMarkedItems: function() { - new WCF.Action.Proxy({ - autoSend: true, - data: { - containerData: this._containerData, - pageClassName: this._page, - pageObjectID: this._pageObjectID - }, - success: $.proxy(this._loadMarkedItemsSuccess, this), - url: 'index.php/ClipboardLoadMarkedItems/?t=' + SECURITY_TOKEN + SID_ARG_2ND + require(['WoltLab/WCF/Controller/Clipboard'], function(ControllerClipboard) { + ControllerClipboard.setup({ + hasMarkedItems: (hasMarkedItems > 0), + pageClassName: page, + pageObjectId: pageObjectID + }); }); }, @@ -1524,472 +1426,9 @@ WCF.Clipboard = { * Reloads the list of marked items. */ reload: function() { - if (this._containers === null) { - return; - } - - this._loadMarkedItems(); - }, - - /** - * Marks all returned items as marked - * - * @param object data - * @param string textStatus - * @param jQuery jqXHR - */ - _loadMarkedItemsSuccess: function(data, textStatus, jqXHR) { - this._resetMarkings(); - - for (var $typeName in data.markedItems) { - if (!this._markedObjectIDs[$typeName]) { - this._markedObjectIDs[$typeName] = [ ]; - } - - var $objectData = data.markedItems[$typeName]; - for (var $i in $objectData) { - this._markedObjectIDs[$typeName].push($objectData[$i]); - } - - // loop through all containers - this._containers.each($.proxy(function(index, container) { - var $container = $(container); - - // typeName does not match, continue - if ($container.data('type') != $typeName) { - return true; - } - - // mark items as marked - $container.find('input.jsClipboardItem').each($.proxy(function(innerIndex, item) { - var $item = $(item); - if (WCF.inArray($item.data('objectID'), this._markedObjectIDs[$typeName])) { - $item.prop('checked', true); - - // add marked class for element container - $item.parents('.jsClipboardObject').addClass('jsMarked'); - } - }, this)); - - // check if there is a markAll-checkbox - $container.find('input.jsClipboardMarkAll').each(function(innerIndex, markAll) { - var $allItemsMarked = true; - - $container.find('input.jsClipboardItem').each(function(itemIndex, item) { - var $item = $(item); - if (!$item.prop('checked')) { - $allItemsMarked = false; - } - }); - - if ($allItemsMarked) { - $(markAll).prop('checked', true); - } - }); - }, this)); - } - - // call success method to build item list editors - this._success(data, textStatus, jqXHR); - }, - - /** - * Resets all checkboxes. - */ - _resetMarkings: function() { - this._containers.each($.proxy(function(index, container) { - var $container = $(container); - - this._markedObjectIDs[$container.data('type')] = [ ]; - $container.find('input.jsClipboardItem, input.jsClipboardMarkAll').prop('checked', false); - $container.find('.jsClipboardObject').removeClass('jsMarked'); - }, this)); - }, - - /** - * Initializes a clipboard container. - * - * @param object container - */ - _initContainer: function(container) { - var $container = $(container); - var $containerID = $container.wcfIdentify(); - - if (!this._trackedElements[$containerID]) { - $container.find('.jsClipboardMarkAll').data('hasContainer', $containerID).click($.proxy(this._markAll, this)); - - this._markedObjectIDs[$container.data('type')] = [ ]; - this._containerData[$container.data('type')] = {}; - $.each($container.data(), $.proxy(function(index, element) { - if (index.match(/^type(.+)/)) { - this._containerData[$container.data('type')][WCF.String.lcfirst(index.replace(/^type/, ''))] = element; - } - }, this)); - - this._trackedElements[$containerID] = [ ]; - } - - // track individual checkboxes - $container.find('input.jsClipboardItem').each($.proxy(function(index, input) { - var $input = $(input); - var $inputID = $input.wcfIdentify(); - - if (!WCF.inArray($inputID, this._trackedElements[$containerID])) { - this._trackedElements[$containerID].push($inputID); - - $input.data('hasContainer', $containerID).click($.proxy(this._click, this)); - } - }, this)); - }, - - /** - * Processes change checkbox state. - * - * @param object event - */ - _click: function(event) { - var $item = $(event.target); - var $objectID = $item.data('objectID'); - var $isMarked = ($item.prop('checked')) ? true : false; - var $objectIDs = [ $objectID ]; - - if ($item.data('hasContainer')) { - var $container = $('#' + $item.data('hasContainer')); - var $type = $container.data('type'); - } - else { - var $type = $item.data('type'); - } - - if ($isMarked) { - this._markedObjectIDs[$type].push($objectID); - $item.parents('.jsClipboardObject').addClass('jsMarked'); - } - else { - this._markedObjectIDs[$type] = $.removeArrayValue(this._markedObjectIDs[$type], $objectID); - $item.parents('.jsClipboardObject').removeClass('jsMarked'); - } - - // item is part of a container - if ($item.data('hasContainer')) { - // check if all items are marked - var $markedAll = true; - $container.find('input.jsClipboardItem').each(function(index, containerItem) { - var $containerItem = $(containerItem); - if (!$containerItem.prop('checked')) { - $markedAll = false; - } - }); - - // simulate a ticked 'markAll' checkbox - $container.find('.jsClipboardMarkAll').each(function(index, markAll) { - if ($markedAll) { - $(markAll).prop('checked', true); - } - else { - $(markAll).prop('checked', false); - } - }); - } - - this._saveState($type, $objectIDs, $isMarked); - }, - - /** - * Marks all associated clipboard items as checked. - * - * @param object event - */ - _markAll: function(event) { - var $item = $(event.target); - var $objectIDs = [ ]; - var $isMarked = true; - - // if markAll object is a checkbox, allow toggling - if ($item.is('input')) { - $isMarked = $item.prop('checked'); - } - - if ($item.data('hasContainer')) { - var $container = $('#' + $item.data('hasContainer')); - var $type = $container.data('type'); - } - else { - var $type = $item.data('type'); - } - - // handle item containers - if ($item.data('hasContainer')) { - // toggle state for all associated items - $container.find('input.jsClipboardItem').each($.proxy(function(index, containerItem) { - var $containerItem = $(containerItem); - var $objectID = $containerItem.data('objectID'); - if ($isMarked) { - if (!$containerItem.prop('checked')) { - $containerItem.prop('checked', true); - this._markedObjectIDs[$type].push($objectID); - $objectIDs.push($objectID); - } - } - else { - if ($containerItem.prop('checked')) { - $containerItem.prop('checked', false); - this._markedObjectIDs[$type] = $.removeArrayValue(this._markedObjectIDs[$type], $objectID); - $objectIDs.push($objectID); - } - } - }, this)); - - if ($isMarked) { - $container.find('.jsClipboardObject').addClass('jsMarked'); - } - else { - $container.find('.jsClipboardObject').removeClass('jsMarked'); - } - } - - // save new status - this._saveState($type, $objectIDs, $isMarked); - }, - - /** - * Saves clipboard item state. - * - * @param string type - * @param array objectIDs - * @param boolean isMarked - */ - _saveState: function(type, objectIDs, isMarked) { - this._proxy.setOption('data', { - action: (isMarked) ? 'mark' : 'unmark', - containerData: this._containerData, - objectIDs: objectIDs, - pageClassName: this._page, - pageObjectID: this._pageObjectID, - type: type - }); - this._proxy.sendRequest(); - }, - - /** - * Updates editor options. - * - * @param object data - * @param string textStatus - * @param jQuery jqXHR - */ - _success: function(data, textStatus, jqXHR) { - // clear all editors first - var $containers = {}; - $('.jsClipboardEditor').each(function(index, container) { - var $container = $(container); - var $types = eval($container.data('types')); - for (var $i = 0, $length = $types.length; $i < $length; $i++) { - var $typeName = $types[$i]; - $containers[$typeName] = $container; - } - - var $containerID = $container.wcfIdentify(); - WCF.CloseOverlayHandler.removeCallback($containerID); - - $container.empty(); - }); - - // do not build new editors - if (!data.items) return; - - // rebuild editors - for (var $typeName in data.items) { - if (!$containers[$typeName]) { - continue; - } - - // create container - var $container = $containers[$typeName]; - var $list = $container.children('ul'); - if ($list.length == 0) { - $list = $('