/** @module others/mediaViews */
import { findDeep, hooks } from '../util';
import { draggable } from '../util/dragdrop';
import wp from 'wp';
import { filter } from './filter';
import $ from 'jquery';
/**
* The attachments browser selectors.hooks
*/
export const BROWSER_SELECTOR = '.attachments-browser';
/**
* This deferred promise is resolved when the first attachments browser'
* toolbar is created with the RML filter.
*/
export const firstCreatedToolbar = $.Deferred();
/**
* Modify the media-views.js components (Backbone) in a way
* to make them compatible with the AIOT component.
*/
export default function() {
if (!findDeep(window, 'wp.media.view.Attachment.Library')) {
return false;
}
// Create filter
const RMLFilter = wp.media.view.AttachmentFilters.RML = wp.media.view.AttachmentFilters.extend(filter);
// Hold selectedId to select previously selected id
const Modal = wp.media.view.Modal;
wp.media.view.Modal = wp.media.view.Modal.extend({
close() {
Modal.prototype.close.apply(this, arguments);
const { $RmlAppTree } = this.controller;
this._rmlFolder = $RmlAppTree ? $RmlAppTree.props.store.selectedId : undefined;
},
open() {
const { $RmlAppTree } = this.controller;
if (this._rmlFolder !== undefined && $RmlAppTree) {
// Detect, if the folder is available, if yes, select it if not yet
const { store } = $RmlAppTree.props,
node = store.getTreeItemById(this._rmlFolder);
if (node && node.visible && store.selectedId !== this._rmlFolder) {
node.setter(node => { node.selected = true; });
}
// If the folder is no longer available, force 'All' files to be selected
if (!node || !node.visible) {
$RmlAppTree.handleSelect('all');
}
}
Modal.prototype.open.apply(this, arguments);
}
});
// Allow rml orderby
wp.media.model.Query.orderby.allowed.push('rml');
// Create rml orderby comparator
const Attachments = wp.media.view.Attachments;
wp.media.view.Attachments = wp.media.view.Attachments.extend({
initialize() {
Attachments.prototype.initialize.apply(this,arguments);
const that = this, { collection } = this,
{ comparator } = collection,
available = typeof comparator === 'function';
collection.comparator = function(a, b, c) {
let aO, bO;
if (collection.props.get('orderby') === 'rml' && (aO = a.attributes.rmlGalleryOrder)
&& (bO = b.attributes.rmlGalleryOrder) && aO !== -1 && bO !== -1) {
if (aO < bO) {
return -1;
}else if (aO > bO) {
return 1;
}
return 0;
}else if (available) {
return comparator.apply(this, arguments);
}
};
// Initially load a folder from the AppTree initialSelectedId state
const oldMore = collection.more;
let setted = false;
collection.more = function() {
const { $RmlAppTree } = that.controller,
toolbar = that.views.parent.toolbar;
let initialSelectedId;
if ($RmlAppTree && $RmlAppTree.props && (initialSelectedId = $RmlAppTree.initialSelectedId)) {
if (!setted) {
const model = toolbar.get('rml_folder').model;
model.set({ rml_folder: initialSelectedId === 'all' ? '' : initialSelectedId }, { silent: false });
setted = true;
}
return oldMore.apply(this, arguments);
}
return $.Deferred().resolveWith(that).promise();
};
}
});
// Call a grid render for all new generated items
const oldRender = wp.media.view.Attachment.Library.prototype.render;
wp.media.view.Attachment.Library.prototype.render = function() {
oldRender.apply(this, arguments);
const { $RmlAppTree } = this.controller;
/**
* Fired when an attachments browser item is rendered.
*
* @event module:util/hooks#attachmentsBrowser/item/rendered
* @param {jQuery} $el The element
* @param {object} model The backbone model
* @param {object} appTree The app tree instance
* @this wp.media.view.Attachment.Library
*/
hooks.call('attachmentsBrowser/item/rendered', [ this.$el, this.model, $RmlAppTree ], this);
};
// Modify attachments browser
const AttachmentsBrowser = wp.media.view.AttachmentsBrowser;
wp.media.view.AttachmentsBrowser = wp.media.view.AttachmentsBrowser.extend({
initialize() {
AttachmentsBrowser.prototype.initialize.apply(this, arguments);
// Events for attachments browsers collections
let timeout;
this.collection.on('change reset add remove', () => {
clearTimeout(timeout);
timeout = setTimeout(() => {
// Merged collection change
const { $RmlAppTree } = this.controller;
if ($RmlAppTree) {
draggable($RmlAppTree);
/**
* Fired when the collection of attachments browser changes.
*
* @event module:util/hooks#attachmentsBrowser/collection/change
* @param {object} appTree The app tree instance
* @this wp.media.view.AttachmentsBrowser
*/
hooks.call('attachmentsBrowser/collection/change', [ $RmlAppTree ], this);
}
}, 50);
});
this.collection.on('remove', (...args) => {
/**
* Fired when an attachments browser item gets removed.
*
* @event module:util/hooks#attachmentsBrowser/item/removed
* @param {mixed} args... The event arguments
* @this wp.media.view.AttachmentsBrowser
*/
hooks.call('attachmentsBrowser/item/removed', [this.controller.$RmlAppTree, ...args], this);
});
// Listen to the ajax complete to refresh the folder counts
$(document).ajaxComplete((e, xhs, req) => {
try {
if (req.data.indexOf('action=delete-post') > -1) {
const { $RmlAppTree } = this.controller;
$RmlAppTree && $RmlAppTree.fetchCounts();
}
}catch(e) {
// Silence is golden.
}
});
},
createToolbar() {
AttachmentsBrowser.prototype.createToolbar.call(this);
this.$el.data('backboneView', this);
// Add new toolbar
const obj = new RMLFilter({
controller: this.controller,
model: this.collection.props,
priority: -81 // see media-views.js#7295
}).render();
this.toolbar.set('rml_folder', obj);
obj.initialize();
const { modal } = this.controller.options;
if (modal) {
/**
* Fired, when a new modal window is created.
*
* @event module:util/hooks#attachmentsBrowser/modal
* @this wp.media.view.AttachmentsBrowser
*/
hooks.call('attachmentsBrowser/modal', [], this);
}else{
firstCreatedToolbar.resolve(this);
}
},
remove() {
this.controller.$RmlAppTree.handleDestroy();
AttachmentsBrowser.prototype.remove.apply(this, arguments);
}
});
return true;
}
/**
* Enhanced Media Library compatibility and layout adjustment.
*/
hooks.register('ready', () => {
if ($('body').hasClass('eml-grid')) {
const mediaGrid = $('#wp-media-grid'),
offsetTop = mediaGrid.offset().top,
fnResize = () => { mediaGrid.css('height', $(window).height() - $('#wpadminbar').height() - 10); },
fnScroll = () => {
const scrollTop = $(window).scrollTop();
mediaGrid[0].style.top = (scrollTop > offsetTop ? scrollTop : 0) + 'px';
//mediaGrid.css("top", scrollTop > offsetTop ? scrollTop - offsetTop : 0);
};
// Centerize container
$(window).on("resize", fnResize);
fnResize();
// Scroll container
$(window).on("scroll", fnScroll);
fnScroll();
}
});