566 lines
25 KiB
JavaScript
566 lines
25 KiB
JavaScript
/**
|
|
* Cause gallery shortcode is hardcoded into WP core and has a lot of relations with Media Manager and other parts
|
|
* had to copy related code and adjust to the DG needs.
|
|
* Since WP core make use of shortcode tag to get (build) needed function name while handling shortcode (especially in visual editor),
|
|
* named all DG related variables and functions using prefix or suffix (depending on context) same as shortcode tag - dg
|
|
* As long as WP core has strange conditional statements for order and orderby attributes had to rename them by adding dg prefix.
|
|
*
|
|
*/
|
|
( function ($, _) {
|
|
// Check if environment is suitable for the code to be executed
|
|
if ( typeof wp.media.collection !== 'function' ) return;
|
|
|
|
var l10n,
|
|
media = wp.media;
|
|
|
|
// Link any localized strings.
|
|
l10n = media.view.l10n = typeof _wpMediaViewsL10n === 'undefined' ? {} : _wpMediaViewsL10n;
|
|
jQuery.extend(l10n, DGl10n);
|
|
|
|
// Based on code from /wp-includes/js/media-views.js WP 4.1
|
|
/**
|
|
* wp.media.controller.dgEdit
|
|
*
|
|
* A state for editing a dg's images and settings.
|
|
*
|
|
* @class
|
|
* @augments wp.media.controller.Library
|
|
* @augments wp.media.controller.State
|
|
* @augments Backbone.Model
|
|
*
|
|
* @param {object} [attributes] The attributes hash passed to the state.
|
|
* @param {string} [attributes.id=dg-edit] Unique identifier.
|
|
* @param {string} [attributes.title=Edit Document Gallery] Title for the state. Displays in the frame's title region.
|
|
* @param {wp.media.model.Attachments} [attributes.library] The collection of attachments in the dg.
|
|
* If one is not supplied, an empty media.model.Selection collection is created.
|
|
* @param {boolean} [attributes.multiple=false] Whether multi-select is enabled.
|
|
* @param {boolean} [attributes.searchable=false] Whether the library is searchable.
|
|
* @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.
|
|
* @param {string|false} [attributes.content=browse] Initial mode for the content region.
|
|
* @param {string|false} [attributes.toolbar=image-details] Initial mode for the toolbar region.
|
|
* @param {boolean} [attributes.describe=true] Whether to offer UI to describe attachments - e.g. captioning images in a dg.
|
|
* @param {boolean} [attributes.displaySettings=true] Whether to show the attachment display settings interface.
|
|
* @param {boolean} [attributes.dragInfo=true] Whether to show instructional text about the attachments being sortable.
|
|
* @param {int} [attributes.idealColumnWidth=170] The ideal column width in pixels for attachments.
|
|
* @param {boolean} [attributes.editing=false] Whether the dg is being created, or editing an existing instance.
|
|
* @param {int} [attributes.priority=60] The priority for the state link in the media menu.
|
|
* @param {boolean} [attributes.syncSelection=false] Whether the Attachments selection should be persisted from the last state.
|
|
* Defaults to false for this state, because the library passed in *is* the selection.
|
|
* @param {view} [attributes.AttachmentView] The single `Attachment` view to be used in the `Attachments`.
|
|
* If none supplied, defaults to wp.media.view.Attachment.EditLibrary.
|
|
*/
|
|
media.controller.dgEdit = media.controller.Library.extend({
|
|
defaults: {
|
|
id: 'dg-edit',
|
|
title: l10n.editdgTitle,
|
|
multiple: false,
|
|
searchable: false,
|
|
date: false,
|
|
sortable: true,
|
|
display: false,
|
|
content: 'browse',
|
|
toolbar: 'dg-edit',
|
|
describe: true,
|
|
displaySettings: true,
|
|
dragInfo: true,
|
|
idealColumnWidth: 170,
|
|
editing: false,
|
|
priority: 60,
|
|
syncSelection: false
|
|
},
|
|
|
|
/**
|
|
* @since 3.5.0
|
|
*/
|
|
initialize: function () {
|
|
// If we haven't been provided a `library`, create a `Selection`.
|
|
if (!this.get('library'))
|
|
this.set('library', new media.model.Selection());
|
|
|
|
// The single `Attachment` view to be used in the `Attachments` view.
|
|
if (!this.get('AttachmentView'))
|
|
this.set('AttachmentView', media.view.Attachment.EditLibrary);
|
|
media.controller.Library.prototype.initialize.apply(this, arguments);
|
|
},
|
|
|
|
/**
|
|
* @since 3.5.0
|
|
*/
|
|
activate: function () {
|
|
var library = this.get('library');
|
|
|
|
// Limit the library to images only.
|
|
//library.props.set( 'type', 'image' );
|
|
|
|
// Watch for uploaded attachments.
|
|
this.get('library').observe(wp.Uploader.queue);
|
|
|
|
this.frame.on('content:render:browse', this.dgSettings, this);
|
|
|
|
media.controller.Library.prototype.activate.apply(this, arguments);
|
|
},
|
|
|
|
/**
|
|
* @since 3.5.0
|
|
*/
|
|
deactivate: function () {
|
|
// Stop watching for uploaded attachments.
|
|
this.get('library').unobserve(wp.Uploader.queue);
|
|
|
|
this.frame.off('content:render:browse', this.dgSettings, this);
|
|
|
|
media.controller.Library.prototype.deactivate.apply(this, arguments);
|
|
},
|
|
|
|
/**
|
|
* @since 3.5.0
|
|
*
|
|
* @param browser
|
|
*/
|
|
dgSettings: function (browser) {
|
|
if (!this.get('displaySettings')) {
|
|
return;
|
|
}
|
|
|
|
var library = this.get('library');
|
|
|
|
if (!library || !browser) {
|
|
return;
|
|
}
|
|
|
|
library.dg = library.dg || new Backbone.Model();
|
|
|
|
browser.sidebar.set({
|
|
dg: new media.view.Settings.dg({
|
|
controller: this,
|
|
model: library.dg,
|
|
priority: 40
|
|
})
|
|
});
|
|
|
|
browser.toolbar.set('reverse', {
|
|
text: l10n.reverseOrder,
|
|
priority: 80,
|
|
|
|
click: function () {
|
|
library.reset(library.toArray().reverse());
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
/**
|
|
* A state for selecting more images to add to a dg.
|
|
*
|
|
* @class
|
|
* @augments wp.media.controller.Library
|
|
* @augments wp.media.controller.State
|
|
* @augments Backbone.Model
|
|
*
|
|
* @param {object} [attributes] The attributes hash passed to the state.
|
|
* @param {string} [attributes.id=dg-library] Unique identifier.
|
|
* @param {string} [attributes.title=Add to Document Gallery] Title for the state. Displays in the frame's title region.
|
|
* @param {boolean} [attributes.multiple=add] Whether multi-select is enabled. @todo 'add' doesn't seem do anything special, and gets used as a boolean.
|
|
* @param {wp.media.model.Attachments} [attributes.library] The attachments collection to browse.
|
|
* If one is not supplied, a collection of all images will be created.
|
|
* @param {boolean|string} [attributes.filterable=uploaded] Whether the library is filterable, and if so what filters should be shown.
|
|
* Accepts 'all', 'uploaded', or 'unattached'.
|
|
* @param {string} [attributes.menu=dg] Initial mode for the menu region.
|
|
* @param {string} [attributes.content=upload] Initial mode for the content region.
|
|
* Overridden by persistent user setting if 'contentUserSetting' is true.
|
|
* @param {string} [attributes.router=browse] Initial mode for the router region.
|
|
* @param {string} [attributes.toolbar=dg-add] Initial mode for the toolbar region.
|
|
* @param {boolean} [attributes.searchable=true] Whether the library is searchable.
|
|
* @param {boolean} [attributes.sortable=true] Whether the Attachments should be sortable. Depends on the orderby property being set to menuOrder on the attachments collection.
|
|
* @param {boolean} [attributes.autoSelect=true] Whether an uploaded attachment should be automatically added to the selection.
|
|
* @param {boolean} [attributes.contentUserSetting=true] Whether the content region's mode should be set and persisted per user.
|
|
* @param {int} [attributes.priority=100] The priority for the state link in the media menu.
|
|
* @param {boolean} [attributes.syncSelection=false] Whether the Attachments selection should be persisted from the last state.
|
|
* Defaults to false because for this state, because the library of the Edit Document Gallery state is the selection.
|
|
*/
|
|
media.controller.dgAdd = media.controller.Library.extend({
|
|
defaults: _.defaults({
|
|
id: 'dg-library',
|
|
title: l10n.addTodgTitle,
|
|
multiple: 'add',
|
|
filterable: 'uploaded',
|
|
menu: 'dg',
|
|
toolbar: 'dg-add',
|
|
priority: 100,
|
|
syncSelection: false
|
|
}, media.controller.Library.prototype.defaults),
|
|
|
|
/**
|
|
* @since 3.5.0
|
|
*/
|
|
initialize: function () {
|
|
// If a library wasn't supplied, create a library of images.
|
|
if (!this.get('library'))
|
|
this.set('library', media.query());
|
|
|
|
media.controller.Library.prototype.initialize.apply(this, arguments);
|
|
},
|
|
|
|
/**
|
|
* @since 3.5.0
|
|
*/
|
|
activate: function () {
|
|
var library = this.get('library'),
|
|
edit = this.frame.state('dg-edit').get('library');
|
|
|
|
if (this.editLibrary && this.editLibrary !== edit)
|
|
library.unobserve(this.editLibrary);
|
|
|
|
// Accepts attachments that exist in the original library and
|
|
// that do not exist in dg's library.
|
|
library.validator = function (attachment) {
|
|
return !!this.mirroring.get(attachment.cid) && !edit.get(attachment.cid) && media.model.Selection.prototype.validator.apply(this, arguments);
|
|
};
|
|
|
|
// Reset the library to ensure that all attachments are re-added
|
|
// to the collection. Do so silently, as calling `observe` will
|
|
// trigger the `reset` event.
|
|
library.reset(library.mirroring.models, {silent: true});
|
|
library.observe(edit);
|
|
this.editLibrary = edit;
|
|
|
|
media.controller.Library.prototype.activate.apply(this, arguments);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* wp.media.view.Settings.dg
|
|
*
|
|
* @class
|
|
* @augments wp.media.view.Settings
|
|
* @augments wp.media.View
|
|
* @augments wp.Backbone.View
|
|
* @augments Backbone.View
|
|
*/
|
|
media.view.Settings.dg = media.view.Settings.extend({
|
|
update: function( key ) {
|
|
var value = this.model.get( key ),
|
|
$setting = this.$('[data-setting="' + key + '"]'),
|
|
$buttons, $value;
|
|
|
|
// Bail if we didn't find a matching setting.
|
|
if ( ! $setting.length ) {
|
|
return;
|
|
}
|
|
|
|
// Attempt to determine how the setting is rendered and update
|
|
// the selected value.
|
|
|
|
// Handle dropdowns.
|
|
if ( $setting.is('select') ) {
|
|
$value = $setting.find('[value="' + value + '"]');
|
|
|
|
if ( $value.length ) {
|
|
$setting.find('option').prop( 'selected', false );
|
|
$value.prop( 'selected', true );
|
|
} else {
|
|
// If we can't find the desired value, record what *is* selected.
|
|
this.model.set( key, $setting.find(':selected').val() );
|
|
}
|
|
|
|
// Handle button groups.
|
|
} else if ( $setting.hasClass('button-group') ) {
|
|
$buttons = $setting.find('button').removeClass('active');
|
|
$buttons.filter( '[value="' + value + '"]' ).addClass('active');
|
|
|
|
// Handle text inputs and textareas.
|
|
} else if ( $setting.is('input[type="text"], input[type="number"], textarea') ) {
|
|
if ( ! $setting.is(':focus') ) {
|
|
$setting.val( value );
|
|
}
|
|
// Handle checkboxes.
|
|
} else if ( $setting.is('input[type="checkbox"]') ) {
|
|
$setting.prop( 'checked', !! value && 'false' !== value );
|
|
}
|
|
},
|
|
className: 'collection-settings dg-settings',
|
|
template: media.template('dg-settings')
|
|
});
|
|
|
|
// supersede the default MediaFrame.Post view
|
|
// hint from https://gist.github.com/Fab1en/4586865
|
|
var wpMediaFramePost = wp.media.view.MediaFrame.Post;
|
|
wp.media.view.MediaFrame.Post = wpMediaFramePost.extend(
|
|
{
|
|
initialize: function () {
|
|
wpMediaFramePost.prototype.initialize.apply(this, arguments);
|
|
this.states.add([
|
|
new media.controller.Library({
|
|
id: 'dg',
|
|
title: l10n.dgMenuTitle,
|
|
priority: 50,
|
|
toolbar: 'main-dg',
|
|
filterable: 'all',
|
|
multiple: 'add',
|
|
editable: false,
|
|
|
|
library: media.query(this.options.library)
|
|
}),
|
|
|
|
// Document Gallery states.
|
|
new media.controller.dgEdit({
|
|
library: this.options.selection,
|
|
editing: this.options.editing,
|
|
menu: 'dg'
|
|
}),
|
|
|
|
new media.controller.dgAdd()
|
|
]);
|
|
|
|
this.on('menu:create:dg', this.createMenu, this);
|
|
this.on('toolbar:create:main-dg', this.createToolbar, this);
|
|
|
|
this.on('menu:render:dg', this.dgMenu, this);
|
|
this.on('toolbar:render:main-dg', this.maindgToolbar, this);
|
|
this.on('toolbar:render:dg-edit', this.dgEditToolbar, this);
|
|
this.on('toolbar:render:dg-add', this.dgAddToolbar, this);
|
|
},
|
|
|
|
/**
|
|
* @param {wp.Backbone.View} view
|
|
*/
|
|
dgMenu: function (view) {
|
|
var lastState = this.lastState(),
|
|
previous = lastState && lastState.id,
|
|
frame = this;
|
|
|
|
view.set({
|
|
cancel: {
|
|
text: l10n.canceldgTitle,
|
|
priority: 20,
|
|
click: function () {
|
|
if (previous) {
|
|
frame.setState(previous);
|
|
} else {
|
|
frame.close();
|
|
}
|
|
|
|
// Keep focus inside media modal
|
|
// after canceling a dg
|
|
this.controller.modal.focusManager.focus();
|
|
}
|
|
},
|
|
separateCancel: new media.View({
|
|
className: 'separator',
|
|
priority: 40
|
|
})
|
|
});
|
|
},
|
|
|
|
/**
|
|
* @param {wp.Backbone.View} view
|
|
*/
|
|
maindgToolbar: function (view) {
|
|
var controller = this;
|
|
|
|
this.selectionStatusToolbar(view);
|
|
|
|
view.set('dg', {
|
|
style: 'primary',
|
|
text: l10n.dgButton,
|
|
priority: 60,
|
|
requires: {selection: true},
|
|
|
|
click: function () {
|
|
var selection = controller.state().get('selection'),
|
|
edit = controller.state('dg-edit'),
|
|
models = selection.models;
|
|
|
|
edit.set('library', new media.model.Selection(models, {
|
|
props: selection.props.toJSON(),
|
|
multiple: true
|
|
}));
|
|
|
|
this.controller.setState('dg-edit');
|
|
|
|
// Keep focus inside media modal
|
|
// after jumping to dg view
|
|
this.controller.modal.focusManager.focus();
|
|
}
|
|
});
|
|
},
|
|
|
|
dgEditToolbar: function () {
|
|
var editing = this.state().get('editing');
|
|
this.toolbar.set(new media.view.Toolbar({
|
|
controller: this,
|
|
items: {
|
|
insert: {
|
|
style: 'primary',
|
|
text: editing ? l10n.updatedg : l10n.insertdg,
|
|
priority: 80,
|
|
requires: {library: true},
|
|
|
|
/**
|
|
* @fires wp.media.controller.State#update
|
|
*/
|
|
click: function () {
|
|
var controller = this.controller,
|
|
state = controller.state();
|
|
|
|
controller.close();
|
|
if ( editing ) {
|
|
state.trigger('update', state.get('library')); // calling for workflow.state update, so just execute its contents
|
|
} else {
|
|
wp.media.editor.insert(wp.media.dg.shortcode(state.get('library')).string().replace(/\sdgorder=/ig, ' order=').replace(/\sdgorderby=/ig, ' orderby='));
|
|
}
|
|
|
|
// Restore and reset the default state.
|
|
controller.setState(controller.options.state);
|
|
controller.reset();
|
|
if (typeof tinyMCE != 'undefined' && tinyMCE.activeEditor !== null) {
|
|
tinyMCE.activeEditor.fire('update.dg');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}));
|
|
},
|
|
|
|
dgAddToolbar: function () {
|
|
this.toolbar.set(new media.view.Toolbar({
|
|
controller: this,
|
|
items: {
|
|
insert: {
|
|
style: 'primary',
|
|
text: l10n.addTodg,
|
|
priority: 80,
|
|
requires: {selection: true},
|
|
|
|
/**
|
|
* @fires wp.media.controller.State#reset
|
|
*/
|
|
click: function () {
|
|
var controller = this.controller,
|
|
state = controller.state(),
|
|
edit = controller.state('dg-edit');
|
|
|
|
edit.get('library').add(state.get('selection').models);
|
|
state.trigger('reset');
|
|
controller.setState('dg-edit');
|
|
}
|
|
}
|
|
}
|
|
}));
|
|
}
|
|
});
|
|
|
|
// Based on code from /wp-includes/js/media-editor.js WP 4.1
|
|
|
|
wp.media._dgDefaults = {
|
|
id: wp.media.view.settings.post && wp.media.view.settings.post.id,
|
|
columns: dgDefaults.columns,
|
|
fancy: dgDefaults.fancy,
|
|
relation: dgDefaults.relation,
|
|
limit: dgDefaults.limit,
|
|
mime_types: dgDefaults.mime_types,
|
|
post_status: dgDefaults.post_status,
|
|
post_type: dgDefaults.post_type,
|
|
attachment_pg: dgDefaults.attachment_pg,
|
|
descriptions: dgDefaults.descriptions,
|
|
new_window: dgDefaults.new_window,
|
|
paginate: dgDefaults.paginate,
|
|
dgorder: dgDefaults.order,
|
|
dgorderby: dgDefaults.orderby
|
|
};
|
|
|
|
if (wp.media.view.settings.dgDefaults) {
|
|
wp.media.dgDefaults = _.extend({}, wp.media._dgDefaults, wp.media.view.settings.dgDefaults);
|
|
} else {
|
|
wp.media.dgDefaults = wp.media._dgDefaults;
|
|
}
|
|
|
|
wp.media.dg = new wp.media.collection({
|
|
tag: 'dg',
|
|
//type : 'image',
|
|
editTitle: wp.media.view.l10n.editdgTitle,
|
|
defaults: wp.media.dgDefaults,
|
|
|
|
setDefaults: function (attrs) {
|
|
var self = this, changed = !_.isEqual(wp.media.dgDefaults, wp.media._dgDefaults);
|
|
_.each(this.defaults, function (value, key) {
|
|
attrs[key] = self.coerce(attrs, key);
|
|
if (value === attrs[key] && ( !changed || value === wp.media._dgDefaults[key] )) {
|
|
delete attrs[key];
|
|
}
|
|
});
|
|
return attrs;
|
|
}
|
|
});
|
|
}(jQuery, _));
|
|
|
|
// Check if environment is suitable for the code to be executed
|
|
if ( typeof window.wp.mce !== 'undefined' && typeof window.wp.mce.views !== 'undefined' ) {
|
|
// Based on code from /wp-includes/js/mce-view.js WP 4.2
|
|
/*
|
|
* The WordPress core TinyMCE views.
|
|
* View for the dg shortcode.
|
|
*/
|
|
(function (window, views, media, $) {
|
|
var dg;
|
|
|
|
base = {
|
|
state: [],
|
|
|
|
edit: function (text, update) {
|
|
// currently the shortcode *must* include ids attribute and may include any of the listed attributes to be editable
|
|
if (text.search(/\sids\s*=/gi) == -1 || text.search(/\s(?!(?:ids|attachment_pg|columns|new_window|descriptions|fancy|orderby|order|paginate|limit)\s*=)[\w\-]+\s*=/gi) > -1) {
|
|
tinyMCE.activeEditor.windowManager.alert(DGl10n.unfitSCalert);
|
|
} else {
|
|
var type = this.type,
|
|
frame = media[type].edit(text.replace(/\sorder\s*=/ig, ' dgorder=').replace(/\sorderby\s*=/ig, ' dgorderby='));
|
|
|
|
this.pausePlayers && this.pausePlayers();
|
|
|
|
_.each(this.state, function (state) {
|
|
frame.state(state).on('update', function (selection) {
|
|
update(media[type].shortcode(selection).string().replace(/\sdgorder=/ig, ' order=').replace(/\sdgorderby=/ig, ' orderby='), type === 'dg');
|
|
});
|
|
});
|
|
|
|
frame.on('close', function () {
|
|
frame.detach();
|
|
});
|
|
|
|
frame.open();
|
|
}
|
|
}
|
|
};
|
|
|
|
dg = _.extend({}, base, {
|
|
state: ['dg-edit'],
|
|
template: media.template('editor-dg'),
|
|
|
|
initialize: function () {
|
|
var attachments = media.dg.attachments(this.shortcode, media.view.settings.post.id),
|
|
attrs = this.shortcode.attrs.named,
|
|
sc = this.text,
|
|
atts = {},
|
|
self = this;
|
|
|
|
for (prop in attrs) {
|
|
if (sc.indexOf(' ' + prop + '=') > -1) {
|
|
atts[prop] = attrs[prop];
|
|
}
|
|
}
|
|
if (sc.indexOf(' dgorderby=') > -1) {
|
|
atts['orderby'] = attrs['dgorderby'];
|
|
}
|
|
if (sc.indexOf(' dgorder=') > -1) {
|
|
atts['order'] = attrs['dgorder'];
|
|
}
|
|
self.render('<div data-shortcode="' +
|
|
encodeURIComponent(JSON.stringify(atts)) +
|
|
'"><div class="loading-placeholder"><div class="dashicons dashicons-admin-media"></div><div class="wpview-loading"><ins></ins></div></div></div>');
|
|
}
|
|
});
|
|
|
|
views.register('dg', _.extend({}, dg));
|
|
|
|
})(window, window.wp.mce.views, window.wp.media, window.jQuery);
|
|
} |