/**
* Provides the media manager dialog.
*
- * @author Matthias Schmidt
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module WoltLabSuite/Core/Media/Manager/Base
+ * @author Matthias Schmidt
+ * @copyright 2001-2020 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module WoltLabSuite/Core/Media/Manager/Base
*/
-define([
- 'Core', 'Dictionary', 'Dom/ChangeListener', 'Dom/Traverse',
- 'Dom/Util', 'EventHandler', 'Language', 'List',
- 'Permission', 'Ui/Dialog', 'Ui/Notification', 'WoltLabSuite/Core/Controller/Clipboard',
- 'WoltLabSuite/Core/Media/Editor', 'WoltLabSuite/Core/Media/Upload', 'WoltLabSuite/Core/Media/Manager/Search', 'StringUtil',
- 'WoltLabSuite/Core/Ui/Pagination',
- 'WoltLabSuite/Core/Media/Clipboard'
-], function (Core, Dictionary, DomChangeListener, DomTraverse, DomUtil, EventHandler, Language, List, Permission, UiDialog, UiNotification, Clipboard, MediaEditor, MediaUpload, MediaManagerSearch, StringUtil, UiPagination, MediaClipboard) {
+define(["require", "exports", "tslib", "../../Core", "../../Language", "../../Permission", "../../Dom/Change/Listener", "../../Event/Handler", "../../Dom/Traverse", "../../Dom/Util", "../../Ui/Dialog", "../../Controller/Clipboard", "../../Ui/Pagination", "../../Ui/Notification", "../../StringUtil", "./Search", "../Upload", "../Editor", "../Clipboard"], function (require, exports, tslib_1, Core, Language, Permission, DomChangeListener, EventHandler, DomTraverse, DomUtil, UiDialog, Clipboard, Pagination_1, UiNotification, StringUtil, Search_1, Upload_1, Editor_1, MediaClipboard) {
"use strict";
- if (!COMPILER_TARGET_DEFAULT) {
- var Fake = function () { };
- Fake.prototype = {
- _addButtonEventListeners: function () { },
- _click: function () { },
- _dialogClose: function () { },
- _dialogInit: function () { },
- _dialogSetup: function () { },
- _dialogShow: function () { },
- _editMedia: function () { },
- _editorClose: function () { },
- _editorSuccess: function () { },
- _removeClipboardCheckboxes: function () { },
- _setMedia: function () { },
- addMedia: function () { },
- clipboardDeleteMedia: function () { },
- getDialog: function () { },
- getMode: function () { },
- getOption: function () { },
- removeMedia: function () { },
- resetMedia: function () { },
- setMedia: function () { },
- setupMediaElement: function () { }
- };
- return Fake;
- }
- var _mediaManagerCounter = 0;
- /**
- * @constructor
- */
- function MediaManagerBase(options) {
- this._options = Core.extend({
- dialogTitle: Language.get('wcf.media.manager'),
- imagesOnly: false,
- minSearchLength: 3
- }, options);
- this._id = 'mediaManager' + _mediaManagerCounter++;
- this._listItems = new Dictionary();
- this._media = new Dictionary();
- this._mediaManagerMediaList = null;
- this._search = null;
- this._upload = null;
- this._forceClipboard = false;
- this._hadInitiallyMarkedItems = false;
- this._pagination = null;
- if (Permission.get('admin.content.cms.canManageMedia')) {
- this._mediaEditor = new MediaEditor(this);
+ Core = tslib_1.__importStar(Core);
+ Language = tslib_1.__importStar(Language);
+ Permission = tslib_1.__importStar(Permission);
+ DomChangeListener = tslib_1.__importStar(DomChangeListener);
+ EventHandler = tslib_1.__importStar(EventHandler);
+ DomTraverse = tslib_1.__importStar(DomTraverse);
+ DomUtil = tslib_1.__importStar(DomUtil);
+ UiDialog = tslib_1.__importStar(UiDialog);
+ Clipboard = tslib_1.__importStar(Clipboard);
+ Pagination_1 = tslib_1.__importDefault(Pagination_1);
+ UiNotification = tslib_1.__importStar(UiNotification);
+ StringUtil = tslib_1.__importStar(StringUtil);
+ Search_1 = tslib_1.__importDefault(Search_1);
+ Upload_1 = tslib_1.__importDefault(Upload_1);
+ Editor_1 = tslib_1.__importDefault(Editor_1);
+ MediaClipboard = tslib_1.__importStar(MediaClipboard);
+ let mediaManagerCounter = 0;
+ class MediaManager {
+ constructor(options) {
+ this._forceClipboard = false;
+ this._hadInitiallyMarkedItems = false;
+ this._id = `mediaManager${mediaManagerCounter++}`;
+ this._listItems = new Map();
+ this._media = new Map();
+ this._mediaEditor = null;
+ this._mediaManagerMediaList = null;
+ this._pagination = null;
+ this._search = null;
+ this._upload = null;
+ this._options = Core.extend({
+ dialogTitle: Language.get("wcf.media.manager"),
+ imagesOnly: false,
+ minSearchLength: 3,
+ }, options);
+ if (Permission.get("admin.content.cms.canManageMedia")) {
+ this._mediaEditor = new Editor_1.default(this);
+ }
+ DomChangeListener.add("WoltLabSuite/Core/Media/Manager", () => this._addButtonEventListeners());
+ EventHandler.add("com.woltlab.wcf.media.upload", "success", (data) => this._openEditorAfterUpload(data));
}
- DomChangeListener.add('WoltLabSuite/Core/Media/Manager', this._addButtonEventListeners.bind(this));
- EventHandler.add('com.woltlab.wcf.media.upload', 'success', this._openEditorAfterUpload.bind(this));
- }
- MediaManagerBase.prototype = {
/**
* Adds click event listeners to media buttons.
*/
- _addButtonEventListeners: function () {
- if (!this._mediaManagerMediaList)
+ _addButtonEventListeners() {
+ if (!this._mediaManagerMediaList || !Permission.get("admin.content.cms.canManageMedia"))
return;
- var listItems = DomTraverse.childrenByTag(this._mediaManagerMediaList, 'LI');
- for (var i = 0, length = listItems.length; i < length; i++) {
- var listItem = listItems[i];
- if (Permission.get('admin.content.cms.canManageMedia')) {
- var editIcon = elByClass('jsMediaEditButton', listItem)[0];
- if (editIcon) {
- editIcon.classList.remove('jsMediaEditButton');
- editIcon.addEventListener('click', this._editMedia.bind(this));
- }
+ DomTraverse.childrenByTag(this._mediaManagerMediaList, "LI").forEach((listItem) => {
+ const editIcon = listItem.querySelector(".jsMediaEditButton");
+ if (editIcon) {
+ editIcon.classList.remove("jsMediaEditButton");
+ editIcon.addEventListener("click", (ev) => this._editMedia(ev));
}
- }
- },
+ });
+ }
/**
* Is called when a new category is selected.
*/
- _categoryChange: function () {
+ _categoryChange() {
this._search.search();
- },
+ }
/**
* Handles clicks on the media manager button.
- *
- * @param {object} event event object
*/
- _click: function (event) {
+ _click(event) {
event.preventDefault();
UiDialog.open(this);
- },
+ }
/**
* Is called if the media manager dialog is closed.
*/
- _dialogClose: function () {
+ _dialogClose() {
// only show media clipboard if editor is open
- if (Permission.get('admin.content.cms.canManageMedia') || this._forceClipboard) {
- Clipboard.hideEditor('com.woltlab.wcf.media');
+ if (Permission.get("admin.content.cms.canManageMedia") || this._forceClipboard) {
+ Clipboard.hideEditor("com.woltlab.wcf.media");
}
- },
+ }
/**
* Initializes the dialog when first loaded.
- *
- * @param {string} content dialog content
- * @param {object} data AJAX request's response data
*/
- _dialogInit: function (content, data) {
+ _dialogInit(content, data) {
// store media data locally
- var media = data.returnValues.media || {};
- for (var mediaId in media) {
- if (objOwns(media, mediaId)) {
- this._media.set(~~mediaId, media[mediaId]);
- }
- }
+ Object.entries(data.returnValues.media || {}).forEach(([mediaId, media]) => {
+ this._media.set(~~mediaId, media);
+ });
this._initPagination(~~data.returnValues.pageCount);
- this._hadInitiallyMarkedItems = data.returnValues.hasMarkedItems;
- },
+ this._hadInitiallyMarkedItems = data.returnValues.hasMarkedItems > 0;
+ }
/**
* Returns all data to setup the media manager dialog.
- *
- * @return {object} dialog setup data
*/
- _dialogSetup: function () {
+ _dialogSetup() {
return {
id: this._id,
options: {
- onClose: this._dialogClose.bind(this),
- onShow: this._dialogShow.bind(this),
- title: this._options.dialogTitle
+ onClose: () => this._dialogClose(),
+ onShow: () => this._dialogShow(),
+ title: this._options.dialogTitle,
},
source: {
- after: this._dialogInit.bind(this),
+ after: (content, data) => this._dialogInit(content, data),
data: {
- actionName: 'getManagementDialog',
- className: 'wcf\\data\\media\\MediaAction',
+ actionName: "getManagementDialog",
+ className: "wcf\\data\\media\\MediaAction",
parameters: {
mode: this.getMode(),
- imagesOnly: this._options.imagesOnly
- }
- }
- }
+ imagesOnly: this._options.imagesOnly,
+ },
+ },
+ },
};
- },
+ }
/**
* Is called if the media manager dialog is shown.
*/
- _dialogShow: function () {
+ _dialogShow() {
if (!this._mediaManagerMediaList) {
- var dialog = this.getDialog();
- this._mediaManagerMediaList = elByClass('mediaManagerMediaList', dialog)[0];
- this._mediaCategorySelect = elBySel('.mediaManagerCategoryList > select', dialog);
+ const dialog = this.getDialog();
+ this._mediaManagerMediaList = dialog.querySelector(".mediaManagerMediaList");
+ this._mediaCategorySelect = dialog.querySelector(".mediaManagerCategoryList > select");
if (this._mediaCategorySelect) {
- this._mediaCategorySelect.addEventListener('change', this._categoryChange.bind(this));
+ this._mediaCategorySelect.addEventListener("change", this._categoryChange.bind(this));
}
// store list items locally
- var listItems = DomTraverse.childrenByTag(this._mediaManagerMediaList, 'LI');
- for (var i = 0, length = listItems.length; i < length; i++) {
- var listItem = listItems[i];
- this._listItems.set(~~elData(listItem, 'object-id'), listItem);
- }
- if (Permission.get('admin.content.cms.canManageMedia')) {
- var uploadButton = elByClass('mediaManagerMediaUploadButton', UiDialog.getDialog(this).dialog)[0];
- this._upload = new MediaUpload(DomUtil.identify(uploadButton), DomUtil.identify(this._mediaManagerMediaList), {
- mediaManager: this
+ const listItems = DomTraverse.childrenByTag(this._mediaManagerMediaList, "LI");
+ listItems.forEach((listItem) => {
+ this._listItems.set(~~listItem.dataset.objectId, listItem);
+ });
+ if (Permission.get("admin.content.cms.canManageMedia")) {
+ const uploadButton = UiDialog.getDialog(this).dialog.querySelector(".mediaManagerMediaUploadButton");
+ this._upload = new Upload_1.default(DomUtil.identify(uploadButton), DomUtil.identify(this._mediaManagerMediaList), {
+ mediaManager: this,
});
- var deleteAction = new WCF.Action.Delete('wcf\\data\\media\\MediaAction', '.mediaFile');
- deleteAction._didTriggerEffect = function (element) {
- this.removeMedia(elData(element[0], 'object-id'));
- }.bind(this);
+ // eslint-disable-next-line
+ //@ts-ignore
+ const deleteAction = new WCF.Action.Delete("wcf\\data\\media\\MediaAction", ".mediaFile");
+ deleteAction._didTriggerEffect = (element) => this.removeMedia(element[0].dataset.objectId);
}
- if (Permission.get('admin.content.cms.canManageMedia') || this._forceClipboard) {
- MediaClipboard.init('menuManagerDialog-' + this.getMode(), this._hadInitiallyMarkedItems ? true : false, this);
+ if (Permission.get("admin.content.cms.canManageMedia") || this._forceClipboard) {
+ MediaClipboard.init("menuManagerDialog-" + this.getMode(), this._hadInitiallyMarkedItems ? true : false, this);
}
else {
this._removeClipboardCheckboxes();
}
- this._search = new MediaManagerSearch(this);
+ this._search = new Search_1.default(this);
if (!listItems.length) {
this._search.hideSearch();
}
}
// only show media clipboard if editor is open
- if (Permission.get('admin.content.cms.canManageMedia') || this._forceClipboard) {
- Clipboard.showEditor('com.woltlab.wcf.media');
+ if (Permission.get("admin.content.cms.canManageMedia") || this._forceClipboard) {
+ Clipboard.showEditor();
}
- },
+ }
/**
* Opens the media editor for a media file.
- *
- * @param {Event} event event object for clicks on edit icons
*/
- _editMedia: function (event) {
- if (!Permission.get('admin.content.cms.canManageMedia')) {
+ _editMedia(event) {
+ if (!Permission.get("admin.content.cms.canManageMedia")) {
throw new Error("You are not allowed to edit media files.");
}
UiDialog.close(this);
- this._mediaEditor.edit(this._media.get(~~elData(event.currentTarget, 'object-id')));
- },
+ const target = event.currentTarget;
+ this._mediaEditor.edit(this._media.get(~~target.dataset.objectId));
+ }
/**
* Re-opens the manager dialog after closing the editor dialog.
*/
- _editorClose: function () {
+ _editorClose() {
UiDialog.open(this);
- },
+ }
/**
- * Re-opens the manager dialog and updates the media data after
- * successfully editing a media file.
- *
- * @param {object} media updated media file data
- * @param {integer} oldCategoryId old category id
+ * Re-opens the manager dialog and updates the media data after successfully editing a media file.
*/
- _editorSuccess: function (media, oldCategoryId) {
+ _editorSuccess(media, oldCategoryId) {
// if the category changed of media changed and category
// is selected, check if media list needs to be refreshed
if (this._mediaCategorySelect) {
- var selectedCategoryId = ~~this._mediaCategorySelect.value;
+ const selectedCategoryId = ~~this._mediaCategorySelect.value;
if (selectedCategoryId) {
- var newCategoryId = ~~media.categoryID;
- if (oldCategoryId != newCategoryId && (oldCategoryId == selectedCategoryId || newCategoryId == selectedCategoryId)) {
+ const newCategoryId = ~~media.categoryID;
+ if (oldCategoryId != newCategoryId &&
+ (oldCategoryId == selectedCategoryId || newCategoryId == selectedCategoryId)) {
this._search.search();
}
}
}
UiDialog.open(this);
this._media.set(~~media.mediaID, media);
- var listItem = this._listItems.get(~~media.mediaID);
- var p = elByClass('mediaTitle', listItem)[0];
+ const listItem = this._listItems.get(~~media.mediaID);
+ const p = listItem.querySelector(".mediaTitle");
if (media.isMultilingual) {
- if (media.title && media.title[LANGUAGE_ID]) {
- p.textContent = media.title[LANGUAGE_ID];
+ if (media.title && media.title[window.LANGUAGE_ID]) {
+ p.textContent = media.title[window.LANGUAGE_ID];
}
else {
p.textContent = media.filename;
p.textContent = media.filename;
}
}
- var thumbnail = elByClass('mediaThumbnail', listItem)[0];
+ const thumbnail = listItem.querySelector(".mediaThumbnail");
thumbnail.innerHTML = media.elementTag;
// Bust browser cache by adding additional parameter.
- var imgs = elByTag('img', thumbnail);
- if (imgs.length) {
- imgs[0].src += '&refresh=' + Date.now();
+ const img = thumbnail.querySelector("img");
+ if (img) {
+ img.src += `&refresh=${Date.now()}`;
}
- },
+ }
/**
* Initializes the dialog pagination.
- *
- * @param {integer} pageCount
- * @param {integer} pageNo
*/
- _initPagination: function (pageCount, pageNo) {
+ _initPagination(pageCount, pageNo) {
if (pageNo === undefined)
pageNo = 1;
if (pageCount > 1) {
- var newPagination = elCreate('div');
- newPagination.className = 'paginationBottom jsPagination';
- DomUtil.replaceElement(elBySel('.jsPagination', UiDialog.getDialog(this).content), newPagination);
- this._pagination = new UiPagination(newPagination, {
+ const newPagination = document.createElement("div");
+ newPagination.className = "paginationBottom jsPagination";
+ DomUtil.replaceElement(UiDialog.getDialog(this).content.querySelector(".jsPagination"), newPagination);
+ this._pagination = new Pagination_1.default(newPagination, {
activePage: pageNo,
callbackSwitch: this._search.search.bind(this._search),
- maxPage: pageCount
+ maxPage: pageCount,
});
}
else if (this._pagination) {
- elHide(this._pagination.getElement());
+ this._pagination.getElement().style.display = "none";
}
- },
+ }
/**
* Removes all media clipboard checkboxes.
*/
- _removeClipboardCheckboxes: function () {
- var checkboxes = elByClass('mediaCheckbox', this._mediaManagerMediaList);
- while (checkboxes.length) {
- elRemove(checkboxes[0]);
- }
- },
+ _removeClipboardCheckboxes() {
+ this._mediaManagerMediaList.querySelectorAll(".mediaCheckbox").forEach((el) => el.remove());
+ }
/**
* Opens the media editor after uploading a single file.
*
- * @param {object} data upload event data
- * @since 5.2
+ * @since 5.2
*/
- _openEditorAfterUpload: function (data) {
+ _openEditorAfterUpload(data) {
if (data.upload === this._upload && !data.isMultiFileUpload && !this._upload.hasPendingUploads()) {
- var keys = Object.keys(data.media);
+ const keys = Object.keys(data.media);
if (keys.length) {
UiDialog.close(this);
this._mediaEditor.edit(this._media.get(~~data.media[keys[0]].mediaID));
}
}
- },
+ }
/**
* Sets the displayed media (after a search).
- *
- * @param {Dictionary} media media to be set as active
*/
- _setMedia: function (media) {
- if (Core.isPlainObject(media)) {
- this._media = Dictionary.fromObject(media);
- }
- else {
- this._media = media;
- }
- var info = DomTraverse.nextByClass(this._mediaManagerMediaList, 'info');
+ _setMedia(media) {
+ this._media = new Map();
+ Object.entries(media).forEach(([mediaId, media]) => {
+ this._media.set(~~mediaId, media);
+ });
+ let info = DomTraverse.nextByClass(this._mediaManagerMediaList, "info");
if (this._media.size) {
if (info) {
- elHide(info);
+ info.style.display = "none";
}
}
else {
if (info === null) {
- info = elCreate('p');
- info.className = 'info';
- info.textContent = Language.get('wcf.media.search.noResults');
+ info = document.createElement("p");
+ info.className = "info";
+ info.textContent = Language.get("wcf.media.search.noResults");
}
- elShow(info);
+ info.style.display = "block";
DomUtil.insertAfter(info, this._mediaManagerMediaList);
}
- var mediaListItems = DomTraverse.childrenByTag(this._mediaManagerMediaList, 'LI');
- for (var i = 0, length = mediaListItems.length; i < length; i++) {
- var listItem = mediaListItems[i];
- if (!this._media.has(elData(listItem, 'object-id'))) {
- elHide(listItem);
+ DomTraverse.childrenByTag(this._mediaManagerMediaList, "LI").forEach((listItem) => {
+ if (!this._media.has(~~listItem.dataset.objectId)) {
+ listItem.style.display = "none";
}
else {
- elShow(listItem);
+ listItem.style.display = "block";
}
- }
+ });
DomChangeListener.trigger();
- if (Permission.get('admin.content.cms.canManageMedia') || this._forceClipboard) {
+ if (Permission.get("admin.content.cms.canManageMedia") || this._forceClipboard) {
Clipboard.reload();
}
else {
this._removeClipboardCheckboxes();
}
- },
+ }
/**
* Adds a media file to the manager.
- *
- * @param {object} media data of the media file
- * @param {Element} listItem list item representing the file
*/
- addMedia: function (media, listItem) {
+ addMedia(media, listItem) {
if (!media.languageID)
media.isMultilingual = 1;
this._media.set(~~media.mediaID, media);
if (this._listItems.size === 1) {
this._search.showSearch();
}
- },
+ }
/**
* Is called after the media files with the given ids have been deleted via clipboard.
- *
- * @param {int[]} mediaIds ids of deleted media files
*/
- clipboardDeleteMedia: function (mediaIds) {
- for (var i = 0, length = mediaIds.length; i < length; i++) {
- this.removeMedia(~~mediaIds[i], true);
- }
+ clipboardDeleteMedia(mediaIds) {
+ mediaIds.forEach((mediaId) => {
+ this.removeMedia(~~mediaId);
+ });
UiNotification.show();
- },
+ }
/**
* Returns the id of the currently selected category or `0` if no category is selected.
- *
- * @return {integer}
*/
- getCategoryId: function () {
+ getCategoryId() {
if (this._mediaCategorySelect) {
- return this._mediaCategorySelect.value;
+ return ~~this._mediaCategorySelect.value;
}
return 0;
- },
+ }
/**
* Returns the media manager dialog element.
- *
- * @return {Element} media manager dialog
*/
- getDialog: function () {
+ getDialog() {
return UiDialog.getDialog(this).dialog;
- },
+ }
/**
* Returns the mode of the media manager.
- *
- * @return {string}
*/
- getMode: function () {
- return '';
- },
+ getMode() {
+ return "";
+ }
/**
* Returns the media manager option with the given name.
- *
- * @param {string} name option name
- * @return {mixed} option value or null
*/
- getOption: function (name) {
+ getOption(name) {
if (this._options[name]) {
return this._options[name];
}
return null;
- },
+ }
/**
* Removes a media file.
- *
- * @param {int} mediaId id of the removed media file
*/
- removeMedia: function (mediaId) {
+ removeMedia(mediaId) {
if (this._listItems.has(mediaId)) {
// remove list item
try {
- elRemove(this._listItems.get(mediaId));
+ this._listItems.get(mediaId).remove();
}
catch (e) {
// ignore errors if item has already been removed like by WCF.Action.Delete
this._listItems.delete(mediaId);
this._media.delete(mediaId);
}
- },
+ }
/**
* Changes the displayed media to the previously displayed media.
*/
- resetMedia: function () {
+ resetMedia() {
// calling WoltLabSuite/Core/Media/Manager/Search.search() reloads the first page of the dialog
this._search.search();
- },
+ }
/**
* Sets the media files currently displayed.
- *
- * @param {object} media media data
- * @param {string} template
- * @param {object} additionalData
*/
- setMedia: function (media, template, additionalData) {
- var hasMedia = false;
- for (var mediaId in media) {
- if (objOwns(media, mediaId)) {
- hasMedia = true;
- }
- }
- var newListItems = [];
+ setMedia(media, template, additionalData) {
+ const hasMedia = Object.entries(media).length > 0;
if (hasMedia) {
- var ul = elCreate('ul');
+ const ul = document.createElement("ul");
ul.innerHTML = template;
- var listItems = DomTraverse.childrenByTag(ul, 'LI');
- for (var i = 0, length = listItems.length; i < length; i++) {
- var listItem = listItems[i];
- if (!this._listItems.has(~~elData(listItem, 'object-id'))) {
- this._listItems.set(elData(listItem, 'object-id'), listItem);
+ DomTraverse.childrenByTag(ul, "LI").forEach((listItem) => {
+ if (!this._listItems.has(~~listItem.dataset.objectId)) {
+ this._listItems.set(~~listItem.dataset.objectId, listItem);
this._mediaManagerMediaList.appendChild(listItem);
}
- }
+ });
}
this._initPagination(additionalData.pageCount, additionalData.pageNo);
this._setMedia(media);
- },
+ }
/**
* Sets up a new media element.
- *
- * @param {object} media data of the media file
- * @param {HTMLElement} mediaElement element representing the media file
*/
- setupMediaElement: function (media, mediaElement) {
- var mediaInformation = DomTraverse.childByClass(mediaElement, 'mediaInformation');
- var buttonGroupNavigation = elCreate('nav');
- buttonGroupNavigation.className = 'jsMobileNavigation buttonGroupNavigation';
+ setupMediaElement(media, mediaElement) {
+ const mediaInformation = DomTraverse.childByClass(mediaElement, "mediaInformation");
+ const buttonGroupNavigation = document.createElement("nav");
+ buttonGroupNavigation.className = "jsMobileNavigation buttonGroupNavigation";
mediaInformation.parentNode.appendChild(buttonGroupNavigation);
- var buttons = elCreate('ul');
- buttons.className = 'buttonList iconList';
+ const buttons = document.createElement("ul");
+ buttons.className = "buttonList iconList";
buttonGroupNavigation.appendChild(buttons);
- var listItem = elCreate('li');
- listItem.className = 'mediaCheckbox';
+ const listItem = document.createElement("li");
+ listItem.className = "mediaCheckbox";
buttons.appendChild(listItem);
- var a = elCreate('a');
+ const a = document.createElement("a");
listItem.appendChild(a);
- var label = elCreate('label');
+ const label = document.createElement("label");
a.appendChild(label);
- var checkbox = elCreate('input');
- checkbox.className = 'jsClipboardItem';
- elAttr(checkbox, 'type', 'checkbox');
- elData(checkbox, 'object-id', media.mediaID);
+ const checkbox = document.createElement("input");
+ checkbox.className = "jsClipboardItem";
+ checkbox.type = "checkbox";
+ checkbox.dataset.objectId = media.mediaID;
label.appendChild(checkbox);
- if (Permission.get('admin.content.cms.canManageMedia')) {
- listItem = elCreate('li');
- listItem.className = 'jsMediaEditButton';
- elData(listItem, 'object-id', media.mediaID);
- buttons.appendChild(listItem);
- listItem.innerHTML = '<a><span class="icon icon16 fa-pencil jsTooltip" title="' + Language.get('wcf.global.button.edit') + '"></span> <span class="invisible">' + Language.get('wcf.global.button.edit') + '</span></a>';
- listItem = elCreate('li');
- listItem.className = 'jsDeleteButton';
- elData(listItem, 'object-id', media.mediaID);
+ if (Permission.get("admin.content.cms.canManageMedia")) {
+ const editButton = document.createElement("li");
+ editButton.className = "jsMediaEditButton";
+ editButton.dataset.objectId = media.mediaID;
+ buttons.appendChild(editButton);
+ editButton.innerHTML = `
+ <a>
+ <span class="icon icon16 fa-pencil jsTooltip" title="${Language.get("wcf.global.button.edit")}"></span>
+ <span class="invisible">${Language.get("wcf.global.button.edit")}</span>
+ </a>`;
+ const deleteButton = document.createElement("li");
+ deleteButton.className = "jsDeleteButton";
+ deleteButton.dataset.objectId = media.mediaID;
// use temporary title to not unescape html in filename
- var uuid = Core.getUuid();
- elData(listItem, 'confirm-message-html', StringUtil.unescapeHTML(Language.get('wcf.media.delete.confirmMessage', {
- title: uuid
- })).replace(uuid, StringUtil.escapeHTML(media.filename)));
- buttons.appendChild(listItem);
- listItem.innerHTML = '<a><span class="icon icon16 fa-times jsTooltip" title="' + Language.get('wcf.global.button.delete') + '"></span> <span class="invisible">' + Language.get('wcf.global.button.delete') + '</span></a>';
+ const uuid = Core.getUuid();
+ deleteButton.dataset.confirmMessageHtml = StringUtil.unescapeHTML(Language.get("wcf.media.delete.confirmMessage", {
+ title: uuid,
+ })).replace(uuid, StringUtil.escapeHTML(media.filename));
+ buttons.appendChild(deleteButton);
+ deleteButton.innerHTML = `
+ <a>
+ <span class="icon icon16 fa-times jsTooltip" title="${Language.get("wcf.global.button.delete")}"></span>
+ <span class="invisible">${Language.get("wcf.global.button.delete")}</span>
+ </a>`;
}
}
- };
- return MediaManagerBase;
+ }
+ Core.enableLegacyInheritance(MediaManager);
+ return MediaManager;
});
+++ /dev/null
-/**
- * Provides the media manager dialog.
- *
- * @author Matthias Schmidt
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module WoltLabSuite/Core/Media/Manager/Base
- */
-define(
- [
- 'Core', 'Dictionary', 'Dom/ChangeListener', 'Dom/Traverse',
- 'Dom/Util', 'EventHandler', 'Language', 'List',
- 'Permission', 'Ui/Dialog', 'Ui/Notification', 'WoltLabSuite/Core/Controller/Clipboard',
- 'WoltLabSuite/Core/Media/Editor', 'WoltLabSuite/Core/Media/Upload', 'WoltLabSuite/Core/Media/Manager/Search', 'StringUtil',
- 'WoltLabSuite/Core/Ui/Pagination',
- 'WoltLabSuite/Core/Media/Clipboard'
- ],
- function(
- Core, Dictionary, DomChangeListener, DomTraverse,
- DomUtil, EventHandler, Language, List,
- Permission, UiDialog, UiNotification, Clipboard,
- MediaEditor, MediaUpload, MediaManagerSearch, StringUtil,
- UiPagination,
- MediaClipboard
- )
-{
- "use strict";
-
- if (!COMPILER_TARGET_DEFAULT) {
- var Fake = function() {};
- Fake.prototype = {
- _addButtonEventListeners: function() {},
- _click: function() {},
- _dialogClose: function() {},
- _dialogInit: function() {},
- _dialogSetup: function() {},
- _dialogShow: function() {},
- _editMedia: function() {},
- _editorClose: function() {},
- _editorSuccess: function() {},
- _removeClipboardCheckboxes: function() {},
- _setMedia: function() {},
- addMedia: function() {},
- clipboardDeleteMedia: function() {},
- getDialog: function() {},
- getMode: function() {},
- getOption: function() {},
- removeMedia: function() {},
- resetMedia: function() {},
- setMedia: function() {},
- setupMediaElement: function() {}
- };
- return Fake;
- }
-
- var _mediaManagerCounter = 0;
-
- /**
- * @constructor
- */
- function MediaManagerBase(options) {
- this._options = Core.extend({
- dialogTitle: Language.get('wcf.media.manager'),
- imagesOnly: false,
- minSearchLength: 3
- }, options);
-
- this._id = 'mediaManager' + _mediaManagerCounter++;
- this._listItems = new Dictionary();
- this._media = new Dictionary();
- this._mediaManagerMediaList = null;
- this._search = null;
- this._upload = null;
- this._forceClipboard = false;
- this._hadInitiallyMarkedItems = false;
- this._pagination = null;
-
- if (Permission.get('admin.content.cms.canManageMedia')) {
- this._mediaEditor = new MediaEditor(this);
- }
-
- DomChangeListener.add('WoltLabSuite/Core/Media/Manager', this._addButtonEventListeners.bind(this));
-
- EventHandler.add('com.woltlab.wcf.media.upload', 'success', this._openEditorAfterUpload.bind(this));
- }
- MediaManagerBase.prototype = {
- /**
- * Adds click event listeners to media buttons.
- */
- _addButtonEventListeners: function() {
- if (!this._mediaManagerMediaList) return;
-
- var listItems = DomTraverse.childrenByTag(this._mediaManagerMediaList, 'LI');
- for (var i = 0, length = listItems.length; i < length; i++) {
- var listItem = listItems[i];
-
- if (Permission.get('admin.content.cms.canManageMedia')) {
- var editIcon = elByClass('jsMediaEditButton', listItem)[0];
- if (editIcon) {
- editIcon.classList.remove('jsMediaEditButton');
- editIcon.addEventListener('click', this._editMedia.bind(this));
- }
- }
- }
- },
-
- /**
- * Is called when a new category is selected.
- */
- _categoryChange: function() {
- this._search.search();
- },
-
- /**
- * Handles clicks on the media manager button.
- *
- * @param {object} event event object
- */
- _click: function(event) {
- event.preventDefault();
-
- UiDialog.open(this);
- },
-
- /**
- * Is called if the media manager dialog is closed.
- */
- _dialogClose: function() {
- // only show media clipboard if editor is open
- if (Permission.get('admin.content.cms.canManageMedia') || this._forceClipboard) {
- Clipboard.hideEditor('com.woltlab.wcf.media');
- }
- },
-
- /**
- * Initializes the dialog when first loaded.
- *
- * @param {string} content dialog content
- * @param {object} data AJAX request's response data
- */
- _dialogInit: function(content, data) {
- // store media data locally
- var media = data.returnValues.media || { };
- for (var mediaId in media) {
- if (objOwns(media, mediaId)) {
- this._media.set(~~mediaId, media[mediaId]);
- }
- }
-
- this._initPagination(~~data.returnValues.pageCount);
-
- this._hadInitiallyMarkedItems = data.returnValues.hasMarkedItems;
- },
-
- /**
- * Returns all data to setup the media manager dialog.
- *
- * @return {object} dialog setup data
- */
- _dialogSetup: function() {
- return {
- id: this._id,
- options: {
- onClose: this._dialogClose.bind(this),
- onShow: this._dialogShow.bind(this),
- title: this._options.dialogTitle
- },
- source: {
- after: this._dialogInit.bind(this),
- data: {
- actionName: 'getManagementDialog',
- className: 'wcf\\data\\media\\MediaAction',
- parameters: {
- mode: this.getMode(),
- imagesOnly: this._options.imagesOnly
- }
- }
- }
- };
- },
-
- /**
- * Is called if the media manager dialog is shown.
- */
- _dialogShow: function() {
- if (!this._mediaManagerMediaList) {
- var dialog = this.getDialog();
-
- this._mediaManagerMediaList = elByClass('mediaManagerMediaList', dialog)[0];
-
- this._mediaCategorySelect = elBySel('.mediaManagerCategoryList > select', dialog);
- if (this._mediaCategorySelect) {
- this._mediaCategorySelect.addEventListener('change', this._categoryChange.bind(this));
- }
-
- // store list items locally
- var listItems = DomTraverse.childrenByTag(this._mediaManagerMediaList, 'LI');
- for (var i = 0, length = listItems.length; i < length; i++) {
- var listItem = listItems[i];
-
- this._listItems.set(~~elData(listItem, 'object-id'), listItem);
- }
-
- if (Permission.get('admin.content.cms.canManageMedia')) {
- var uploadButton = elByClass('mediaManagerMediaUploadButton', UiDialog.getDialog(this).dialog)[0];
- this._upload = new MediaUpload(DomUtil.identify(uploadButton), DomUtil.identify(this._mediaManagerMediaList), {
- mediaManager: this
- });
-
- var deleteAction = new WCF.Action.Delete('wcf\\data\\media\\MediaAction', '.mediaFile');
- deleteAction._didTriggerEffect = function(element) {
- this.removeMedia(elData(element[0], 'object-id'));
- }.bind(this);
- }
-
- if (Permission.get('admin.content.cms.canManageMedia') || this._forceClipboard) {
- MediaClipboard.init(
- 'menuManagerDialog-' + this.getMode(),
- this._hadInitiallyMarkedItems ? true : false,
- this
- );
- }
- else {
- this._removeClipboardCheckboxes();
- }
-
- this._search = new MediaManagerSearch(this);
-
- if (!listItems.length) {
- this._search.hideSearch();
- }
- }
-
- // only show media clipboard if editor is open
- if (Permission.get('admin.content.cms.canManageMedia') || this._forceClipboard) {
- Clipboard.showEditor('com.woltlab.wcf.media');
- }
- },
-
- /**
- * Opens the media editor for a media file.
- *
- * @param {Event} event event object for clicks on edit icons
- */
- _editMedia: function(event) {
- if (!Permission.get('admin.content.cms.canManageMedia')) {
- throw new Error("You are not allowed to edit media files.");
- }
-
- UiDialog.close(this);
-
- this._mediaEditor.edit(this._media.get(~~elData(event.currentTarget, 'object-id')));
- },
-
- /**
- * Re-opens the manager dialog after closing the editor dialog.
- */
- _editorClose: function() {
- UiDialog.open(this);
- },
-
- /**
- * Re-opens the manager dialog and updates the media data after
- * successfully editing a media file.
- *
- * @param {object} media updated media file data
- * @param {integer} oldCategoryId old category id
- */
- _editorSuccess: function(media, oldCategoryId) {
- // if the category changed of media changed and category
- // is selected, check if media list needs to be refreshed
- if (this._mediaCategorySelect) {
- var selectedCategoryId = ~~this._mediaCategorySelect.value;
-
- if (selectedCategoryId) {
- var newCategoryId = ~~media.categoryID;
-
- if (oldCategoryId != newCategoryId && (oldCategoryId == selectedCategoryId || newCategoryId == selectedCategoryId)) {
- this._search.search();
- }
- }
- }
-
- UiDialog.open(this);
-
- this._media.set(~~media.mediaID, media);
-
- var listItem = this._listItems.get(~~media.mediaID);
- var p = elByClass('mediaTitle', listItem)[0];
- if (media.isMultilingual) {
- if (media.title && media.title[LANGUAGE_ID]) {
- p.textContent = media.title[LANGUAGE_ID];
- }
- else {
- p.textContent = media.filename;
- }
- }
- else {
- if (media.title && media.title[media.languageID]) {
- p.textContent = media.title[media.languageID];
- }
- else {
- p.textContent = media.filename;
- }
- }
-
- var thumbnail = elByClass('mediaThumbnail', listItem)[0];
- thumbnail.innerHTML = media.elementTag;
- // Bust browser cache by adding additional parameter.
- var imgs = elByTag('img', thumbnail);
- if (imgs.length) {
- imgs[0].src += '&refresh=' + Date.now();
- }
- },
-
- /**
- * Initializes the dialog pagination.
- *
- * @param {integer} pageCount
- * @param {integer} pageNo
- */
- _initPagination: function(pageCount, pageNo) {
- if (pageNo === undefined) pageNo = 1;
-
- if (pageCount > 1) {
- var newPagination = elCreate('div');
- newPagination.className = 'paginationBottom jsPagination';
- DomUtil.replaceElement(elBySel('.jsPagination', UiDialog.getDialog(this).content), newPagination);
-
- this._pagination = new UiPagination(newPagination, {
- activePage: pageNo,
- callbackSwitch: this._search.search.bind(this._search),
- maxPage: pageCount
- });
- }
- else if (this._pagination) {
- elHide(this._pagination.getElement());
- }
- },
-
- /**
- * Removes all media clipboard checkboxes.
- */
- _removeClipboardCheckboxes: function() {
- var checkboxes = elByClass('mediaCheckbox', this._mediaManagerMediaList);
- while (checkboxes.length) {
- elRemove(checkboxes[0]);
- }
- },
-
- /**
- * Opens the media editor after uploading a single file.
- *
- * @param {object} data upload event data
- * @since 5.2
- */
- _openEditorAfterUpload: function(data) {
- if (data.upload === this._upload && !data.isMultiFileUpload && !this._upload.hasPendingUploads()) {
- var keys = Object.keys(data.media);
-
- if (keys.length) {
- UiDialog.close(this);
-
- this._mediaEditor.edit(this._media.get(~~data.media[keys[0]].mediaID));
- }
- }
- },
-
- /**
- * Sets the displayed media (after a search).
- *
- * @param {Dictionary} media media to be set as active
- */
- _setMedia: function(media) {
- if (Core.isPlainObject(media)) {
- this._media = Dictionary.fromObject(media);
- }
- else {
- this._media = media;
- }
-
- var info = DomTraverse.nextByClass(this._mediaManagerMediaList, 'info');
-
- if (this._media.size) {
- if (info) {
- elHide(info);
- }
- }
- else {
- if (info === null) {
- info = elCreate('p');
- info.className = 'info';
- info.textContent = Language.get('wcf.media.search.noResults');
- }
-
- elShow(info);
- DomUtil.insertAfter(info, this._mediaManagerMediaList);
- }
-
- var mediaListItems = DomTraverse.childrenByTag(this._mediaManagerMediaList, 'LI');
- for (var i = 0, length = mediaListItems.length; i < length; i++) {
- var listItem = mediaListItems[i];
-
- if (!this._media.has(elData(listItem, 'object-id'))) {
- elHide(listItem);
- }
- else {
- elShow(listItem);
- }
- }
-
- DomChangeListener.trigger();
-
- if (Permission.get('admin.content.cms.canManageMedia') || this._forceClipboard) {
- Clipboard.reload();
- }
- else {
- this._removeClipboardCheckboxes();
- }
- },
-
- /**
- * Adds a media file to the manager.
- *
- * @param {object} media data of the media file
- * @param {Element} listItem list item representing the file
- */
- addMedia: function(media, listItem) {
- if (!media.languageID) media.isMultilingual = 1;
-
- this._media.set(~~media.mediaID, media);
- this._listItems.set(~~media.mediaID, listItem);
-
- if (this._listItems.size === 1) {
- this._search.showSearch();
- }
- },
-
- /**
- * Is called after the media files with the given ids have been deleted via clipboard.
- *
- * @param {int[]} mediaIds ids of deleted media files
- */
- clipboardDeleteMedia: function(mediaIds) {
- for (var i = 0, length = mediaIds.length; i < length; i++) {
- this.removeMedia(~~mediaIds[i], true);
- }
-
- UiNotification.show();
- },
-
- /**
- * Returns the id of the currently selected category or `0` if no category is selected.
- *
- * @return {integer}
- */
- getCategoryId: function() {
- if (this._mediaCategorySelect) {
- return this._mediaCategorySelect.value;
- }
-
- return 0;
- },
-
- /**
- * Returns the media manager dialog element.
- *
- * @return {Element} media manager dialog
- */
- getDialog: function() {
- return UiDialog.getDialog(this).dialog;
- },
-
- /**
- * Returns the mode of the media manager.
- *
- * @return {string}
- */
- getMode: function() {
- return '';
- },
-
- /**
- * Returns the media manager option with the given name.
- *
- * @param {string} name option name
- * @return {mixed} option value or null
- */
- getOption: function(name) {
- if (this._options[name]) {
- return this._options[name];
- }
-
- return null;
- },
-
- /**
- * Removes a media file.
- *
- * @param {int} mediaId id of the removed media file
- */
- removeMedia: function(mediaId) {
- if (this._listItems.has(mediaId)) {
- // remove list item
- try {
- elRemove(this._listItems.get(mediaId));
- }
- catch (e) {
- // ignore errors if item has already been removed like by WCF.Action.Delete
- }
-
- this._listItems.delete(mediaId);
- this._media.delete(mediaId);
- }
- },
-
- /**
- * Changes the displayed media to the previously displayed media.
- */
- resetMedia: function() {
- // calling WoltLabSuite/Core/Media/Manager/Search.search() reloads the first page of the dialog
- this._search.search();
- },
-
- /**
- * Sets the media files currently displayed.
- *
- * @param {object} media media data
- * @param {string} template
- * @param {object} additionalData
- */
- setMedia: function(media, template, additionalData) {
- var hasMedia = false;
- for (var mediaId in media) {
- if (objOwns(media, mediaId)) {
- hasMedia = true;
- }
- }
-
- var newListItems = [];
- if (hasMedia) {
- var ul = elCreate('ul');
- ul.innerHTML = template;
-
- var listItems = DomTraverse.childrenByTag(ul, 'LI');
- for (var i = 0, length = listItems.length; i < length; i++) {
- var listItem = listItems[i];
- if (!this._listItems.has(~~elData(listItem, 'object-id'))) {
- this._listItems.set(elData(listItem, 'object-id'), listItem);
-
- this._mediaManagerMediaList.appendChild(listItem);
- }
- }
- }
-
- this._initPagination(additionalData.pageCount, additionalData.pageNo);
-
- this._setMedia(media);
- },
-
- /**
- * Sets up a new media element.
- *
- * @param {object} media data of the media file
- * @param {HTMLElement} mediaElement element representing the media file
- */
- setupMediaElement: function(media, mediaElement) {
- var mediaInformation = DomTraverse.childByClass(mediaElement, 'mediaInformation');
-
- var buttonGroupNavigation = elCreate('nav');
- buttonGroupNavigation.className = 'jsMobileNavigation buttonGroupNavigation';
- mediaInformation.parentNode.appendChild(buttonGroupNavigation);
-
- var buttons = elCreate('ul');
- buttons.className = 'buttonList iconList';
- buttonGroupNavigation.appendChild(buttons);
-
- var listItem = elCreate('li');
- listItem.className = 'mediaCheckbox';
- buttons.appendChild(listItem);
-
- var a = elCreate('a');
- listItem.appendChild(a);
-
- var label = elCreate('label');
- a.appendChild(label);
-
- var checkbox = elCreate('input');
- checkbox.className = 'jsClipboardItem';
- elAttr(checkbox, 'type', 'checkbox');
- elData(checkbox, 'object-id', media.mediaID);
- label.appendChild(checkbox);
-
- if (Permission.get('admin.content.cms.canManageMedia')) {
- listItem = elCreate('li');
- listItem.className = 'jsMediaEditButton';
- elData(listItem, 'object-id', media.mediaID);
- buttons.appendChild(listItem);
-
- listItem.innerHTML = '<a><span class="icon icon16 fa-pencil jsTooltip" title="' + Language.get('wcf.global.button.edit') + '"></span> <span class="invisible">' + Language.get('wcf.global.button.edit') + '</span></a>';
-
- listItem = elCreate('li');
- listItem.className = 'jsDeleteButton';
- elData(listItem, 'object-id', media.mediaID);
-
- // use temporary title to not unescape html in filename
- var uuid = Core.getUuid();
- elData(listItem, 'confirm-message-html', StringUtil.unescapeHTML(Language.get('wcf.media.delete.confirmMessage', {
- title: uuid
- })).replace(uuid, StringUtil.escapeHTML(media.filename)));
- buttons.appendChild(listItem);
-
- listItem.innerHTML = '<a><span class="icon icon16 fa-times jsTooltip" title="' + Language.get('wcf.global.button.delete') + '"></span> <span class="invisible">' + Language.get('wcf.global.button.delete') + '</span></a>';
- }
- }
- };
-
- return MediaManagerBase;
-});
--- /dev/null
+/**
+ * Provides the media manager dialog.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2020 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module WoltLabSuite/Core/Media/Manager/Base
+ */
+
+import * as Core from "../../Core";
+import { Media, MediaManagerOptions, MediaEditorCallbackObject, MediaUploadSuccessEventData } from "../Data";
+import * as Language from "../../Language";
+import * as Permission from "../../Permission";
+import * as DomChangeListener from "../../Dom/Change/Listener";
+import * as EventHandler from "../../Event/Handler";
+import * as DomTraverse from "../../Dom/Traverse";
+import * as DomUtil from "../../Dom/Util";
+import * as UiDialog from "../../Ui/Dialog";
+import { DialogCallbackSetup, DialogCallbackObject } from "../../Ui/Dialog/Data";
+import * as Clipboard from "../../Controller/Clipboard";
+import UiPagination from "../../Ui/Pagination";
+import * as UiNotification from "../../Ui/Notification";
+import * as StringUtil from "../../StringUtil";
+import MediaManagerSearch from "./Search";
+import MediaUpload from "../Upload";
+import MediaEditor from "../Editor";
+import * as MediaClipboard from "../Clipboard";
+
+let mediaManagerCounter = 0;
+
+type DialogInitAjaxResponseData = {
+ returnValues: {
+ hasMarkedItems: number;
+ media: object;
+ pageCount: number;
+ };
+};
+
+type SetMediaAdditionalData = {
+ pageCount: number;
+ pageNo: number;
+};
+
+abstract class MediaManager<TOptions extends MediaManagerOptions = MediaManagerOptions>
+ implements DialogCallbackObject, MediaEditorCallbackObject {
+ protected _forceClipboard = false;
+ protected _hadInitiallyMarkedItems = false;
+ protected readonly _id = `mediaManager${mediaManagerCounter++}`;
+ protected readonly _listItems = new Map<number, HTMLLIElement>();
+ protected _media = new Map<number, Media>();
+ protected _mediaCategorySelect: HTMLSelectElement | null;
+ protected readonly _mediaEditor: MediaEditor | null = null;
+ protected _mediaManagerMediaList: HTMLElement | null = null;
+ protected _pagination: UiPagination | null = null;
+ protected _search: MediaManagerSearch | null = null;
+ protected _upload: any = null;
+ protected readonly _options: TOptions;
+
+ constructor(options: Partial<TOptions>) {
+ this._options = Core.extend(
+ {
+ dialogTitle: Language.get("wcf.media.manager"),
+ imagesOnly: false,
+ minSearchLength: 3,
+ },
+ options,
+ ) as TOptions;
+
+ if (Permission.get("admin.content.cms.canManageMedia")) {
+ this._mediaEditor = new MediaEditor(this);
+ }
+
+ DomChangeListener.add("WoltLabSuite/Core/Media/Manager", () => this._addButtonEventListeners());
+
+ EventHandler.add("com.woltlab.wcf.media.upload", "success", (data: MediaUploadSuccessEventData) =>
+ this._openEditorAfterUpload(data),
+ );
+ }
+
+ /**
+ * Adds click event listeners to media buttons.
+ */
+ protected _addButtonEventListeners(): void {
+ if (!this._mediaManagerMediaList || !Permission.get("admin.content.cms.canManageMedia")) return;
+
+ DomTraverse.childrenByTag(this._mediaManagerMediaList, "LI").forEach((listItem) => {
+ const editIcon = listItem.querySelector(".jsMediaEditButton");
+ if (editIcon) {
+ editIcon.classList.remove("jsMediaEditButton");
+ editIcon.addEventListener("click", (ev: MouseEvent) => this._editMedia(ev));
+ }
+ });
+ }
+
+ /**
+ * Is called when a new category is selected.
+ */
+ protected _categoryChange(): void {
+ this._search!.search();
+ }
+
+ /**
+ * Handles clicks on the media manager button.
+ */
+ protected _click(event: MouseEvent): void {
+ event.preventDefault();
+
+ UiDialog.open(this);
+ }
+
+ /**
+ * Is called if the media manager dialog is closed.
+ */
+ protected _dialogClose(): void {
+ // only show media clipboard if editor is open
+ if (Permission.get("admin.content.cms.canManageMedia") || this._forceClipboard) {
+ Clipboard.hideEditor("com.woltlab.wcf.media");
+ }
+ }
+
+ /**
+ * Initializes the dialog when first loaded.
+ */
+ protected _dialogInit(content: HTMLElement, data: DialogInitAjaxResponseData): void {
+ // store media data locally
+ Object.entries(data.returnValues.media || {}).forEach(([mediaId, media]) => {
+ this._media.set(~~mediaId, media);
+ });
+
+ this._initPagination(~~data.returnValues.pageCount);
+
+ this._hadInitiallyMarkedItems = data.returnValues.hasMarkedItems > 0;
+ }
+
+ /**
+ * Returns all data to setup the media manager dialog.
+ */
+ public _dialogSetup(): ReturnType<DialogCallbackSetup> {
+ return {
+ id: this._id,
+ options: {
+ onClose: () => this._dialogClose(),
+ onShow: () => this._dialogShow(),
+ title: this._options.dialogTitle,
+ },
+ source: {
+ after: (content: HTMLElement, data: DialogInitAjaxResponseData) => this._dialogInit(content, data),
+ data: {
+ actionName: "getManagementDialog",
+ className: "wcf\\data\\media\\MediaAction",
+ parameters: {
+ mode: this.getMode(),
+ imagesOnly: this._options.imagesOnly,
+ },
+ },
+ },
+ };
+ }
+
+ /**
+ * Is called if the media manager dialog is shown.
+ */
+ protected _dialogShow(): void {
+ if (!this._mediaManagerMediaList) {
+ const dialog = this.getDialog();
+
+ this._mediaManagerMediaList = dialog.querySelector(".mediaManagerMediaList");
+
+ this._mediaCategorySelect = dialog.querySelector(".mediaManagerCategoryList > select");
+ if (this._mediaCategorySelect) {
+ this._mediaCategorySelect.addEventListener("change", this._categoryChange.bind(this));
+ }
+
+ // store list items locally
+ const listItems = DomTraverse.childrenByTag(this._mediaManagerMediaList!, "LI");
+ listItems.forEach((listItem: HTMLLIElement) => {
+ this._listItems.set(~~listItem.dataset.objectId!, listItem);
+ });
+
+ if (Permission.get("admin.content.cms.canManageMedia")) {
+ const uploadButton = UiDialog.getDialog(this)!.dialog.querySelector(".mediaManagerMediaUploadButton")!;
+ this._upload = new MediaUpload(DomUtil.identify(uploadButton), DomUtil.identify(this._mediaManagerMediaList!), {
+ mediaManager: this,
+ });
+
+ // eslint-disable-next-line
+ //@ts-ignore
+ const deleteAction = new WCF.Action.Delete("wcf\\data\\media\\MediaAction", ".mediaFile");
+ deleteAction._didTriggerEffect = (element) => this.removeMedia(element[0].dataset.objectId);
+ }
+
+ if (Permission.get("admin.content.cms.canManageMedia") || this._forceClipboard) {
+ MediaClipboard.init("menuManagerDialog-" + this.getMode(), this._hadInitiallyMarkedItems ? true : false, this);
+ } else {
+ this._removeClipboardCheckboxes();
+ }
+
+ this._search = new MediaManagerSearch(this);
+
+ if (!listItems.length) {
+ this._search.hideSearch();
+ }
+ }
+
+ // only show media clipboard if editor is open
+ if (Permission.get("admin.content.cms.canManageMedia") || this._forceClipboard) {
+ Clipboard.showEditor();
+ }
+ }
+
+ /**
+ * Opens the media editor for a media file.
+ */
+ protected _editMedia(event: MouseEvent): void {
+ if (!Permission.get("admin.content.cms.canManageMedia")) {
+ throw new Error("You are not allowed to edit media files.");
+ }
+
+ UiDialog.close(this);
+
+ const target = event.currentTarget as HTMLElement;
+
+ this._mediaEditor!.edit(this._media.get(~~target.dataset.objectId!)!);
+ }
+
+ /**
+ * Re-opens the manager dialog after closing the editor dialog.
+ */
+ _editorClose(): void {
+ UiDialog.open(this);
+ }
+
+ /**
+ * Re-opens the manager dialog and updates the media data after successfully editing a media file.
+ */
+ _editorSuccess(media: Media, oldCategoryId?: number): void {
+ // if the category changed of media changed and category
+ // is selected, check if media list needs to be refreshed
+ if (this._mediaCategorySelect) {
+ const selectedCategoryId = ~~this._mediaCategorySelect.value;
+
+ if (selectedCategoryId) {
+ const newCategoryId = ~~media.categoryID;
+
+ if (
+ oldCategoryId != newCategoryId &&
+ (oldCategoryId == selectedCategoryId || newCategoryId == selectedCategoryId)
+ ) {
+ this._search!.search();
+ }
+ }
+ }
+
+ UiDialog.open(this);
+
+ this._media.set(~~media.mediaID, media);
+
+ const listItem = this._listItems.get(~~media.mediaID)!;
+ const p = listItem.querySelector(".mediaTitle")!;
+ if (media.isMultilingual) {
+ if (media.title && media.title[window.LANGUAGE_ID]) {
+ p.textContent = media.title[window.LANGUAGE_ID];
+ } else {
+ p.textContent = media.filename;
+ }
+ } else {
+ if (media.title && media.title[media.languageID!]) {
+ p.textContent = media.title[media.languageID!];
+ } else {
+ p.textContent = media.filename;
+ }
+ }
+
+ const thumbnail = listItem.querySelector(".mediaThumbnail")!;
+ thumbnail.innerHTML = media.elementTag;
+ // Bust browser cache by adding additional parameter.
+ const img = thumbnail.querySelector("img");
+ if (img) {
+ img.src += `&refresh=${Date.now()}`;
+ }
+ }
+
+ /**
+ * Initializes the dialog pagination.
+ */
+ protected _initPagination(pageCount: number, pageNo?: number): void {
+ if (pageNo === undefined) pageNo = 1;
+
+ if (pageCount > 1) {
+ const newPagination = document.createElement("div");
+ newPagination.className = "paginationBottom jsPagination";
+ DomUtil.replaceElement(
+ UiDialog.getDialog(this)!.content.querySelector(".jsPagination") as HTMLElement,
+ newPagination,
+ );
+
+ this._pagination = new UiPagination(newPagination, {
+ activePage: pageNo,
+ callbackSwitch: this._search!.search.bind(this._search),
+ maxPage: pageCount,
+ });
+ } else if (this._pagination) {
+ this._pagination.getElement().style.display = "none";
+ }
+ }
+
+ /**
+ * Removes all media clipboard checkboxes.
+ */
+ _removeClipboardCheckboxes(): void {
+ this._mediaManagerMediaList!.querySelectorAll(".mediaCheckbox").forEach((el) => el.remove());
+ }
+
+ /**
+ * Opens the media editor after uploading a single file.
+ *
+ * @since 5.2
+ */
+ _openEditorAfterUpload(data: MediaUploadSuccessEventData): void {
+ if (data.upload === this._upload && !data.isMultiFileUpload && !this._upload.hasPendingUploads()) {
+ const keys = Object.keys(data.media);
+
+ if (keys.length) {
+ UiDialog.close(this);
+
+ this._mediaEditor!.edit(this._media.get(~~data.media[keys[0]].mediaID)!);
+ }
+ }
+ }
+
+ /**
+ * Sets the displayed media (after a search).
+ */
+ _setMedia(media: object): void {
+ this._media = new Map<number, Media>();
+ Object.entries(media).forEach(([mediaId, media]) => {
+ this._media.set(~~mediaId, media);
+ });
+
+ let info = DomTraverse.nextByClass(this._mediaManagerMediaList!, "info") as HTMLElement;
+
+ if (this._media.size) {
+ if (info) {
+ info.style.display = "none";
+ }
+ } else {
+ if (info === null) {
+ info = document.createElement("p");
+ info.className = "info";
+ info.textContent = Language.get("wcf.media.search.noResults");
+ }
+
+ info.style.display = "block";
+ DomUtil.insertAfter(info, this._mediaManagerMediaList!);
+ }
+
+ DomTraverse.childrenByTag(this._mediaManagerMediaList!, "LI").forEach((listItem) => {
+ if (!this._media.has(~~listItem.dataset.objectId!)) {
+ listItem.style.display = "none";
+ } else {
+ listItem.style.display = "block";
+ }
+ });
+
+ DomChangeListener.trigger();
+
+ if (Permission.get("admin.content.cms.canManageMedia") || this._forceClipboard) {
+ Clipboard.reload();
+ } else {
+ this._removeClipboardCheckboxes();
+ }
+ }
+
+ /**
+ * Adds a media file to the manager.
+ */
+ public addMedia(media: Media, listItem: HTMLLIElement): void {
+ if (!media.languageID) media.isMultilingual = 1;
+
+ this._media.set(~~media.mediaID, media);
+ this._listItems.set(~~media.mediaID, listItem);
+
+ if (this._listItems.size === 1) {
+ this._search!.showSearch();
+ }
+ }
+
+ /**
+ * Is called after the media files with the given ids have been deleted via clipboard.
+ */
+ public clipboardDeleteMedia(mediaIds: number[]): void {
+ mediaIds.forEach((mediaId) => {
+ this.removeMedia(~~mediaId);
+ });
+
+ UiNotification.show();
+ }
+
+ /**
+ * Returns the id of the currently selected category or `0` if no category is selected.
+ */
+ public getCategoryId(): number {
+ if (this._mediaCategorySelect) {
+ return ~~this._mediaCategorySelect.value;
+ }
+
+ return 0;
+ }
+
+ /**
+ * Returns the media manager dialog element.
+ */
+ getDialog(): HTMLElement {
+ return UiDialog.getDialog(this)!.dialog;
+ }
+
+ /**
+ * Returns the mode of the media manager.
+ */
+ public getMode(): string {
+ return "";
+ }
+
+ /**
+ * Returns the media manager option with the given name.
+ */
+ public getOption(name: string): any {
+ if (this._options[name]) {
+ return this._options[name];
+ }
+
+ return null;
+ }
+
+ /**
+ * Removes a media file.
+ */
+ public removeMedia(mediaId: number): void {
+ if (this._listItems.has(mediaId)) {
+ // remove list item
+ try {
+ this._listItems.get(mediaId)!.remove();
+ } catch (e) {
+ // ignore errors if item has already been removed like by WCF.Action.Delete
+ }
+
+ this._listItems.delete(mediaId);
+ this._media.delete(mediaId);
+ }
+ }
+
+ /**
+ * Changes the displayed media to the previously displayed media.
+ */
+ public resetMedia(): void {
+ // calling WoltLabSuite/Core/Media/Manager/Search.search() reloads the first page of the dialog
+ this._search!.search();
+ }
+
+ /**
+ * Sets the media files currently displayed.
+ */
+ setMedia(media: object, template: string, additionalData: SetMediaAdditionalData): void {
+ const hasMedia = Object.entries(media).length > 0;
+
+ if (hasMedia) {
+ const ul = document.createElement("ul");
+ ul.innerHTML = template;
+
+ DomTraverse.childrenByTag(ul, "LI").forEach((listItem) => {
+ if (!this._listItems.has(~~listItem.dataset.objectId!)) {
+ this._listItems.set(~~listItem.dataset.objectId!, listItem);
+
+ this._mediaManagerMediaList!.appendChild(listItem);
+ }
+ });
+ }
+
+ this._initPagination(additionalData.pageCount, additionalData.pageNo);
+
+ this._setMedia(media);
+ }
+
+ /**
+ * Sets up a new media element.
+ */
+ public setupMediaElement(media: Media, mediaElement: HTMLElement): void {
+ const mediaInformation = DomTraverse.childByClass(mediaElement, "mediaInformation")!;
+
+ const buttonGroupNavigation = document.createElement("nav");
+ buttonGroupNavigation.className = "jsMobileNavigation buttonGroupNavigation";
+ mediaInformation.parentNode!.appendChild(buttonGroupNavigation);
+
+ const buttons = document.createElement("ul");
+ buttons.className = "buttonList iconList";
+ buttonGroupNavigation.appendChild(buttons);
+
+ const listItem = document.createElement("li");
+ listItem.className = "mediaCheckbox";
+ buttons.appendChild(listItem);
+
+ const a = document.createElement("a");
+ listItem.appendChild(a);
+
+ const label = document.createElement("label");
+ a.appendChild(label);
+
+ const checkbox = document.createElement("input");
+ checkbox.className = "jsClipboardItem";
+ checkbox.type = "checkbox";
+ checkbox.dataset.objectId = (media.mediaID as unknown) as string;
+ label.appendChild(checkbox);
+
+ if (Permission.get("admin.content.cms.canManageMedia")) {
+ const editButton = document.createElement("li");
+ editButton.className = "jsMediaEditButton";
+ editButton.dataset.objectId = (media.mediaID as unknown) as string;
+ buttons.appendChild(editButton);
+
+ editButton.innerHTML = `
+ <a>
+ <span class="icon icon16 fa-pencil jsTooltip" title="${Language.get("wcf.global.button.edit")}"></span>
+ <span class="invisible">${Language.get("wcf.global.button.edit")}</span>
+ </a>`;
+
+ const deleteButton = document.createElement("li");
+ deleteButton.className = "jsDeleteButton";
+ deleteButton.dataset.objectId = (media.mediaID as unknown) as string;
+
+ // use temporary title to not unescape html in filename
+ const uuid = Core.getUuid();
+ deleteButton.dataset.confirmMessageHtml = StringUtil.unescapeHTML(
+ Language.get("wcf.media.delete.confirmMessage", {
+ title: uuid,
+ }),
+ ).replace(uuid, StringUtil.escapeHTML(media.filename));
+ buttons.appendChild(deleteButton);
+
+ deleteButton.innerHTML = `
+ <a>
+ <span class="icon icon16 fa-times jsTooltip" title="${Language.get("wcf.global.button.delete")}"></span>
+ <span class="invisible">${Language.get("wcf.global.button.delete")}</span>
+ </a>`;
+ }
+ }
+}
+
+Core.enableLegacyInheritance(MediaManager);
+
+export = MediaManager;