diff options
| author | Charles Cabergs <me@cacharle.xyz> | 2020-07-27 10:05:23 +0200 |
|---|---|---|
| committer | Charles Cabergs <me@cacharle.xyz> | 2020-07-27 10:05:23 +0200 |
| commit | 5bf66662a9bdd62c5bccab15e607cd95cfb8fcab (patch) | |
| tree | 39a1a4629749056191c05dfd899f931701b7acf3 /srcs/wordpress/wp-admin/js | |
| parent | 5afd237bbd22028b85532b8c0b3fcead49a00764 (diff) | |
| download | ft_server-5bf66662a9bdd62c5bccab15e607cd95cfb8fcab.tar.gz ft_server-5bf66662a9bdd62c5bccab15e607cd95cfb8fcab.tar.bz2 ft_server-5bf66662a9bdd62c5bccab15e607cd95cfb8fcab.zip | |
Removed wordpress and phpmyadmin, my server doesn't handle it well and it brings shame on my famillyHEADmaster
Diffstat (limited to 'srcs/wordpress/wp-admin/js')
105 files changed, 0 insertions, 42420 deletions
diff --git a/srcs/wordpress/wp-admin/js/accordion.js b/srcs/wordpress/wp-admin/js/accordion.js deleted file mode 100644 index 0bec1ce..0000000 --- a/srcs/wordpress/wp-admin/js/accordion.js +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Accordion-folding functionality. - * - * Markup with the appropriate classes will be automatically hidden, - * with one section opening at a time when its title is clicked. - * Use the following markup structure for accordion behavior: - * - * <div class="accordion-container"> - * <div class="accordion-section open"> - * <h3 class="accordion-section-title"></h3> - * <div class="accordion-section-content"> - * </div> - * </div> - * <div class="accordion-section"> - * <h3 class="accordion-section-title"></h3> - * <div class="accordion-section-content"> - * </div> - * </div> - * <div class="accordion-section"> - * <h3 class="accordion-section-title"></h3> - * <div class="accordion-section-content"> - * </div> - * </div> - * </div> - * - * Note that any appropriate tags may be used, as long as the above classes are present. - * - * @since 3.6.0 - * @output wp-admin/js/accordion.js - */ - -( function( $ ){ - - $( document ).ready( function () { - - // Expand/Collapse accordion sections on click. - $( '.accordion-container' ).on( 'click keydown', '.accordion-section-title', function( e ) { - if ( e.type === 'keydown' && 13 !== e.which ) { // "return" key - return; - } - - e.preventDefault(); // Keep this AFTER the key filter above - - accordionSwitch( $( this ) ); - }); - - }); - - /** - * Close the current accordion section and open a new one. - * - * @param {Object} el Title element of the accordion section to toggle. - * @since 3.6.0 - */ - function accordionSwitch ( el ) { - var section = el.closest( '.accordion-section' ), - sectionToggleControl = section.find( '[aria-expanded]' ).first(), - container = section.closest( '.accordion-container' ), - siblings = container.find( '.open' ), - siblingsToggleControl = siblings.find( '[aria-expanded]' ).first(), - content = section.find( '.accordion-section-content' ); - - // This section has no content and cannot be expanded. - if ( section.hasClass( 'cannot-expand' ) ) { - return; - } - - // Add a class to the container to let us know something is happening inside. - // This helps in cases such as hiding a scrollbar while animations are executing. - container.addClass( 'opening' ); - - if ( section.hasClass( 'open' ) ) { - section.toggleClass( 'open' ); - content.toggle( true ).slideToggle( 150 ); - } else { - siblingsToggleControl.attr( 'aria-expanded', 'false' ); - siblings.removeClass( 'open' ); - siblings.find( '.accordion-section-content' ).show().slideUp( 150 ); - content.toggle( false ).slideToggle( 150 ); - section.toggleClass( 'open' ); - } - - // We have to wait for the animations to finish - setTimeout(function(){ - container.removeClass( 'opening' ); - }, 150); - - // If there's an element with an aria-expanded attribute, assume it's a toggle control and toggle the aria-expanded value. - if ( sectionToggleControl ) { - sectionToggleControl.attr( 'aria-expanded', String( sectionToggleControl.attr( 'aria-expanded' ) === 'false' ) ); - } - } - -})(jQuery); diff --git a/srcs/wordpress/wp-admin/js/accordion.min.js b/srcs/wordpress/wp-admin/js/accordion.min.js deleted file mode 100644 index 1f5d422..0000000 --- a/srcs/wordpress/wp-admin/js/accordion.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(e){e(document).ready(function(){e(".accordion-container").on("click keydown",".accordion-section-title",function(n){"keydown"===n.type&&13!==n.which||(n.preventDefault(),function(n){var e=n.closest(".accordion-section"),o=e.find("[aria-expanded]").first(),a=e.closest(".accordion-container"),i=a.find(".open"),t=i.find("[aria-expanded]").first(),s=e.find(".accordion-section-content");if(e.hasClass("cannot-expand"))return;a.addClass("opening"),e.hasClass("open")?(e.toggleClass("open"),s.toggle(!0).slideToggle(150)):(t.attr("aria-expanded","false"),i.removeClass("open"),i.find(".accordion-section-content").show().slideUp(150),s.toggle(!1).slideToggle(150),e.toggleClass("open"));setTimeout(function(){a.removeClass("opening")},150),o&&o.attr("aria-expanded",String("false"===o.attr("aria-expanded")))}(e(this)))})})}(jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/code-editor.js b/srcs/wordpress/wp-admin/js/code-editor.js deleted file mode 100644 index 25a21a5..0000000 --- a/srcs/wordpress/wp-admin/js/code-editor.js +++ /dev/null @@ -1,342 +0,0 @@ -/** - * @output wp-admin/js/code-editor.js - */ - -if ( 'undefined' === typeof window.wp ) { - /** - * @namespace wp - */ - window.wp = {}; -} -if ( 'undefined' === typeof window.wp.codeEditor ) { - /** - * @namespace wp.codeEditor - */ - window.wp.codeEditor = {}; -} - -( function( $, wp ) { - 'use strict'; - - /** - * Default settings for code editor. - * - * @since 4.9.0 - * @type {object} - */ - wp.codeEditor.defaultSettings = { - codemirror: {}, - csslint: {}, - htmlhint: {}, - jshint: {}, - onTabNext: function() {}, - onTabPrevious: function() {}, - onChangeLintingErrors: function() {}, - onUpdateErrorNotice: function() {} - }; - - /** - * Configure linting. - * - * @param {CodeMirror} editor - Editor. - * @param {object} settings - Code editor settings. - * @param {object} settings.codeMirror - Settings for CodeMirror. - * @param {Function} settings.onChangeLintingErrors - Callback for when there are changes to linting errors. - * @param {Function} settings.onUpdateErrorNotice - Callback to update error notice. - * - * @returns {void} - */ - function configureLinting( editor, settings ) { // eslint-disable-line complexity - var currentErrorAnnotations = [], previouslyShownErrorAnnotations = []; - - /** - * Call the onUpdateErrorNotice if there are new errors to show. - * - * @returns {void} - */ - function updateErrorNotice() { - if ( settings.onUpdateErrorNotice && ! _.isEqual( currentErrorAnnotations, previouslyShownErrorAnnotations ) ) { - settings.onUpdateErrorNotice( currentErrorAnnotations, editor ); - previouslyShownErrorAnnotations = currentErrorAnnotations; - } - } - - /** - * Get lint options. - * - * @returns {object} Lint options. - */ - function getLintOptions() { // eslint-disable-line complexity - var options = editor.getOption( 'lint' ); - - if ( ! options ) { - return false; - } - - if ( true === options ) { - options = {}; - } else if ( _.isObject( options ) ) { - options = $.extend( {}, options ); - } - - // Note that rules must be sent in the "deprecated" lint.options property to prevent linter from complaining about unrecognized options. See <https://github.com/codemirror/CodeMirror/pull/4944>. - if ( ! options.options ) { - options.options = {}; - } - - // Configure JSHint. - if ( 'javascript' === settings.codemirror.mode && settings.jshint ) { - $.extend( options.options, settings.jshint ); - } - - // Configure CSSLint. - if ( 'css' === settings.codemirror.mode && settings.csslint ) { - $.extend( options.options, settings.csslint ); - } - - // Configure HTMLHint. - if ( 'htmlmixed' === settings.codemirror.mode && settings.htmlhint ) { - options.options.rules = $.extend( {}, settings.htmlhint ); - - if ( settings.jshint ) { - options.options.rules.jshint = settings.jshint; - } - if ( settings.csslint ) { - options.options.rules.csslint = settings.csslint; - } - } - - // Wrap the onUpdateLinting CodeMirror event to route to onChangeLintingErrors and onUpdateErrorNotice. - options.onUpdateLinting = (function( onUpdateLintingOverridden ) { - return function( annotations, annotationsSorted, cm ) { - var errorAnnotations = _.filter( annotations, function( annotation ) { - return 'error' === annotation.severity; - } ); - - if ( onUpdateLintingOverridden ) { - onUpdateLintingOverridden.apply( annotations, annotationsSorted, cm ); - } - - // Skip if there are no changes to the errors. - if ( _.isEqual( errorAnnotations, currentErrorAnnotations ) ) { - return; - } - - currentErrorAnnotations = errorAnnotations; - - if ( settings.onChangeLintingErrors ) { - settings.onChangeLintingErrors( errorAnnotations, annotations, annotationsSorted, cm ); - } - - /* - * Update notifications when the editor is not focused to prevent error message - * from overwhelming the user during input, unless there are now no errors or there - * were previously errors shown. In these cases, update immediately so they can know - * that they fixed the errors. - */ - if ( ! editor.state.focused || 0 === currentErrorAnnotations.length || previouslyShownErrorAnnotations.length > 0 ) { - updateErrorNotice(); - } - }; - })( options.onUpdateLinting ); - - return options; - } - - editor.setOption( 'lint', getLintOptions() ); - - // Keep lint options populated. - editor.on( 'optionChange', function( cm, option ) { - var options, gutters, gutterName = 'CodeMirror-lint-markers'; - if ( 'lint' !== option ) { - return; - } - gutters = editor.getOption( 'gutters' ) || []; - options = editor.getOption( 'lint' ); - if ( true === options ) { - if ( ! _.contains( gutters, gutterName ) ) { - editor.setOption( 'gutters', [ gutterName ].concat( gutters ) ); - } - editor.setOption( 'lint', getLintOptions() ); // Expand to include linting options. - } else if ( ! options ) { - editor.setOption( 'gutters', _.without( gutters, gutterName ) ); - } - - // Force update on error notice to show or hide. - if ( editor.getOption( 'lint' ) ) { - editor.performLint(); - } else { - currentErrorAnnotations = []; - updateErrorNotice(); - } - } ); - - // Update error notice when leaving the editor. - editor.on( 'blur', updateErrorNotice ); - - // Work around hint selection with mouse causing focus to leave editor. - editor.on( 'startCompletion', function() { - editor.off( 'blur', updateErrorNotice ); - } ); - editor.on( 'endCompletion', function() { - var editorRefocusWait = 500; - editor.on( 'blur', updateErrorNotice ); - - // Wait for editor to possibly get re-focused after selection. - _.delay( function() { - if ( ! editor.state.focused ) { - updateErrorNotice(); - } - }, editorRefocusWait ); - }); - - /* - * Make sure setting validities are set if the user tries to click Publish - * while an autocomplete dropdown is still open. The Customizer will block - * saving when a setting has an error notifications on it. This is only - * necessary for mouse interactions because keyboards will have already - * blurred the field and cause onUpdateErrorNotice to have already been - * called. - */ - $( document.body ).on( 'mousedown', function( event ) { - if ( editor.state.focused && ! $.contains( editor.display.wrapper, event.target ) && ! $( event.target ).hasClass( 'CodeMirror-hint' ) ) { - updateErrorNotice(); - } - }); - } - - /** - * Configure tabbing. - * - * @param {CodeMirror} codemirror - Editor. - * @param {object} settings - Code editor settings. - * @param {object} settings.codeMirror - Settings for CodeMirror. - * @param {Function} settings.onTabNext - Callback to handle tabbing to the next tabbable element. - * @param {Function} settings.onTabPrevious - Callback to handle tabbing to the previous tabbable element. - * - * @returns {void} - */ - function configureTabbing( codemirror, settings ) { - var $textarea = $( codemirror.getTextArea() ); - - codemirror.on( 'blur', function() { - $textarea.data( 'next-tab-blurs', false ); - }); - codemirror.on( 'keydown', function onKeydown( editor, event ) { - var tabKeyCode = 9, escKeyCode = 27; - - // Take note of the ESC keypress so that the next TAB can focus outside the editor. - if ( escKeyCode === event.keyCode ) { - $textarea.data( 'next-tab-blurs', true ); - return; - } - - // Short-circuit if tab key is not being pressed or the tab key press should move focus. - if ( tabKeyCode !== event.keyCode || ! $textarea.data( 'next-tab-blurs' ) ) { - return; - } - - // Focus on previous or next focusable item. - if ( event.shiftKey ) { - settings.onTabPrevious( codemirror, event ); - } else { - settings.onTabNext( codemirror, event ); - } - - // Reset tab state. - $textarea.data( 'next-tab-blurs', false ); - - // Prevent tab character from being added. - event.preventDefault(); - }); - } - - /** - * @typedef {object} wp.codeEditor~CodeEditorInstance - * @property {object} settings - The code editor settings. - * @property {CodeMirror} codemirror - The CodeMirror instance. - */ - - /** - * Initialize Code Editor (CodeMirror) for an existing textarea. - * - * @since 4.9.0 - * - * @param {string|jQuery|Element} textarea - The HTML id, jQuery object, or DOM Element for the textarea that is used for the editor. - * @param {object} [settings] - Settings to override defaults. - * @param {Function} [settings.onChangeLintingErrors] - Callback for when the linting errors have changed. - * @param {Function} [settings.onUpdateErrorNotice] - Callback for when error notice should be displayed. - * @param {Function} [settings.onTabPrevious] - Callback to handle tabbing to the previous tabbable element. - * @param {Function} [settings.onTabNext] - Callback to handle tabbing to the next tabbable element. - * @param {object} [settings.codemirror] - Options for CodeMirror. - * @param {object} [settings.csslint] - Rules for CSSLint. - * @param {object} [settings.htmlhint] - Rules for HTMLHint. - * @param {object} [settings.jshint] - Rules for JSHint. - * - * @returns {CodeEditorInstance} Instance. - */ - wp.codeEditor.initialize = function initialize( textarea, settings ) { - var $textarea, codemirror, instanceSettings, instance; - if ( 'string' === typeof textarea ) { - $textarea = $( '#' + textarea ); - } else { - $textarea = $( textarea ); - } - - instanceSettings = $.extend( {}, wp.codeEditor.defaultSettings, settings ); - instanceSettings.codemirror = $.extend( {}, instanceSettings.codemirror ); - - codemirror = wp.CodeMirror.fromTextArea( $textarea[0], instanceSettings.codemirror ); - - configureLinting( codemirror, instanceSettings ); - - instance = { - settings: instanceSettings, - codemirror: codemirror - }; - - if ( codemirror.showHint ) { - codemirror.on( 'keyup', function( editor, event ) { // eslint-disable-line complexity - var shouldAutocomplete, isAlphaKey = /^[a-zA-Z]$/.test( event.key ), lineBeforeCursor, innerMode, token; - if ( codemirror.state.completionActive && isAlphaKey ) { - return; - } - - // Prevent autocompletion in string literals or comments. - token = codemirror.getTokenAt( codemirror.getCursor() ); - if ( 'string' === token.type || 'comment' === token.type ) { - return; - } - - innerMode = wp.CodeMirror.innerMode( codemirror.getMode(), token.state ).mode.name; - lineBeforeCursor = codemirror.doc.getLine( codemirror.doc.getCursor().line ).substr( 0, codemirror.doc.getCursor().ch ); - if ( 'html' === innerMode || 'xml' === innerMode ) { - shouldAutocomplete = - '<' === event.key || - '/' === event.key && 'tag' === token.type || - isAlphaKey && 'tag' === token.type || - isAlphaKey && 'attribute' === token.type || - '=' === token.string && token.state.htmlState && token.state.htmlState.tagName; - } else if ( 'css' === innerMode ) { - shouldAutocomplete = - isAlphaKey || - ':' === event.key || - ' ' === event.key && /:\s+$/.test( lineBeforeCursor ); - } else if ( 'javascript' === innerMode ) { - shouldAutocomplete = isAlphaKey || '.' === event.key; - } else if ( 'clike' === innerMode && 'php' === codemirror.options.mode ) { - shouldAutocomplete = 'keyword' === token.type || 'variable' === token.type; - } - if ( shouldAutocomplete ) { - codemirror.showHint( { completeSingle: false } ); - } - }); - } - - // Facilitate tabbing out of the editor. - configureTabbing( codemirror, settings ); - - return instance; - }; - -})( window.jQuery, window.wp ); diff --git a/srcs/wordpress/wp-admin/js/code-editor.min.js b/srcs/wordpress/wp-admin/js/code-editor.min.js deleted file mode 100644 index 6e4b644..0000000 --- a/srcs/wordpress/wp-admin/js/code-editor.min.js +++ /dev/null @@ -1 +0,0 @@ -void 0===window.wp&&(window.wp={}),void 0===window.wp.codeEditor&&(window.wp.codeEditor={}),function(l,d){"use strict";d.codeEditor.defaultSettings={codemirror:{},csslint:{},htmlhint:{},jshint:{},onTabNext:function(){},onTabPrevious:function(){},onChangeLintingErrors:function(){},onUpdateErrorNotice:function(){}},d.codeEditor.initialize=function(t,n){var e,a,o,i;return e=l("string"==typeof t?"#"+t:t),(o=l.extend({},d.codeEditor.defaultSettings,n)).codemirror=l.extend({},o.codemirror),function(r,s){var a=[],d=[];function c(){s.onUpdateErrorNotice&&!_.isEqual(a,d)&&(s.onUpdateErrorNotice(a,r),d=a)}function u(){var i,t=r.getOption("lint");return!!t&&(!0===t?t={}:_.isObject(t)&&(t=l.extend({},t)),t.options||(t.options={}),"javascript"===s.codemirror.mode&&s.jshint&&l.extend(t.options,s.jshint),"css"===s.codemirror.mode&&s.csslint&&l.extend(t.options,s.csslint),"htmlmixed"===s.codemirror.mode&&s.htmlhint&&(t.options.rules=l.extend({},s.htmlhint),s.jshint&&(t.options.rules.jshint=s.jshint),s.csslint&&(t.options.rules.csslint=s.csslint)),t.onUpdateLinting=(i=t.onUpdateLinting,function(t,n,e){var o=_.filter(t,function(t){return"error"===t.severity});i&&i.apply(t,n,e),_.isEqual(o,a)||(a=o,s.onChangeLintingErrors&&s.onChangeLintingErrors(o,t,n,e),(!r.state.focused||0===a.length||0<d.length)&&c())}),t)}r.setOption("lint",u()),r.on("optionChange",function(t,n){var e,o,i="CodeMirror-lint-markers";"lint"===n&&(o=r.getOption("gutters")||[],!0===(e=r.getOption("lint"))?(_.contains(o,i)||r.setOption("gutters",[i].concat(o)),r.setOption("lint",u())):e||r.setOption("gutters",_.without(o,i)),r.getOption("lint")?r.performLint():(a=[],c()))}),r.on("blur",c),r.on("startCompletion",function(){r.off("blur",c)}),r.on("endCompletion",function(){r.on("blur",c),_.delay(function(){r.state.focused||c()},500)}),l(document.body).on("mousedown",function(t){!r.state.focused||l.contains(r.display.wrapper,t.target)||l(t.target).hasClass("CodeMirror-hint")||c()})}(a=d.CodeMirror.fromTextArea(e[0],o.codemirror),o),i={settings:o,codemirror:a},a.showHint&&a.on("keyup",function(t,n){var e,o,i,r,s=/^[a-zA-Z]$/.test(n.key);a.state.completionActive&&s||"string"!==(r=a.getTokenAt(a.getCursor())).type&&"comment"!==r.type&&(i=d.CodeMirror.innerMode(a.getMode(),r.state).mode.name,o=a.doc.getLine(a.doc.getCursor().line).substr(0,a.doc.getCursor().ch),"html"===i||"xml"===i?e="<"===n.key||"/"===n.key&&"tag"===r.type||s&&"tag"===r.type||s&&"attribute"===r.type||"="===r.string&&r.state.htmlState&&r.state.htmlState.tagName:"css"===i?e=s||":"===n.key||" "===n.key&&/:\s+$/.test(o):"javascript"===i?e=s||"."===n.key:"clike"===i&&"php"===a.options.mode&&(e="keyword"===r.type||"variable"===r.type),e&&a.showHint({completeSingle:!1}))}),function(e,o){var i=l(e.getTextArea());e.on("blur",function(){i.data("next-tab-blurs",!1)}),e.on("keydown",function(t,n){27!==n.keyCode?9===n.keyCode&&i.data("next-tab-blurs")&&(n.shiftKey?o.onTabPrevious(e,n):o.onTabNext(e,n),i.data("next-tab-blurs",!1),n.preventDefault()):i.data("next-tab-blurs",!0)})}(a,n),i}}(window.jQuery,window.wp);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/color-picker.js b/srcs/wordpress/wp-admin/js/color-picker.js deleted file mode 100644 index 89e6db0..0000000 --- a/srcs/wordpress/wp-admin/js/color-picker.js +++ /dev/null @@ -1,359 +0,0 @@ -/** - * @output wp-admin/js/color-picker.js - */ - -/* global wpColorPickerL10n */ -( function( $, undef ) { - - var ColorPicker, - _before = '<button type="button" class="button wp-color-result" aria-expanded="false"><span class="wp-color-result-text"></span></button>', - _after = '<div class="wp-picker-holder" />', - _wrap = '<div class="wp-picker-container" />', - _button = '<input type="button" class="button button-small" />', - _wrappingLabel = '<label></label>', - _wrappingLabelText = '<span class="screen-reader-text"></span>'; - - /** - * Creates a jQuery UI color picker that is used in the theme customizer. - * - * @class $.widget.wp.wpColorPicker - * - * @since 3.5.0 - */ - ColorPicker = /** @lends $.widget.wp.wpColorPicker.prototype */{ - options: { - defaultColor: false, - change: false, - clear: false, - hide: true, - palettes: true, - width: 255, - mode: 'hsv', - type: 'full', - slider: 'horizontal' - }, - /** - * Creates a color picker that only allows you to adjust the hue. - * - * @since 3.5.0 - * - * @access private - * - * @returns {void} - */ - _createHueOnly: function() { - var self = this, - el = self.element, - color; - - el.hide(); - - // Set the saturation to the maximum level. - color = 'hsl(' + el.val() + ', 100, 50)'; - - // Create an instance of the color picker, using the hsl mode. - el.iris( { - mode: 'hsl', - type: 'hue', - hide: false, - color: color, - /** - * Handles the onChange event if one has been defined in the options. - * - * @ignore - * - * @param {Event} event The event that's being called. - * @param {HTMLElement} ui The HTMLElement containing the color picker. - * - * @returns {void} - */ - change: function( event, ui ) { - if ( $.isFunction( self.options.change ) ) { - self.options.change.call( this, event, ui ); - } - }, - width: self.options.width, - slider: self.options.slider - } ); - }, - /** - * Creates the color picker, sets default values, css classes and wraps it all in HTML. - * - * @since 3.5.0 - * - * @access private - * - * @returns {void} - */ - _create: function() { - // Return early if Iris support is missing. - if ( ! $.support.iris ) { - return; - } - - var self = this, - el = self.element; - - // Override default options with options bound to the element. - $.extend( self.options, el.data() ); - - // Create a color picker which only allows adjustments to the hue. - if ( self.options.type === 'hue' ) { - return self._createHueOnly(); - } - - // Bind the close event. - self.close = $.proxy( self.close, self ); - - self.initialValue = el.val(); - - // Add a CSS class to the input field. - el.addClass( 'wp-color-picker' ); - - /* - * Check if there's already a wrapping label, e.g. in the Customizer. - * If there's no label, add a default one to match the Customizer template. - */ - if ( ! el.parent( 'label' ).length ) { - // Wrap the input field in the default label. - el.wrap( _wrappingLabel ); - // Insert the default label text. - self.wrappingLabelText = $( _wrappingLabelText ) - .insertBefore( el ) - .text( wpColorPickerL10n.defaultLabel ); - } - - /* - * At this point, either it's the standalone version or the Customizer - * one, we have a wrapping label to use as hook in the DOM, let's store it. - */ - self.wrappingLabel = el.parent(); - - // Wrap the label in the main wrapper. - self.wrappingLabel.wrap( _wrap ); - // Store a reference to the main wrapper. - self.wrap = self.wrappingLabel.parent(); - // Set up the toggle button and insert it before the wrapping label. - self.toggler = $( _before ) - .insertBefore( self.wrappingLabel ) - .css( { backgroundColor: self.initialValue } ); - // Set the toggle button span element text. - self.toggler.find( '.wp-color-result-text' ).text( wpColorPickerL10n.pick ); - // Set up the Iris container and insert it after the wrapping label. - self.pickerContainer = $( _after ).insertAfter( self.wrappingLabel ); - // Store a reference to the Clear/Default button. - self.button = $( _button ); - - // Set up the Clear/Default button. - if ( self.options.defaultColor ) { - self.button - .addClass( 'wp-picker-default' ) - .val( wpColorPickerL10n.defaultString ) - .attr( 'aria-label', wpColorPickerL10n.defaultAriaLabel ); - } else { - self.button - .addClass( 'wp-picker-clear' ) - .val( wpColorPickerL10n.clear ) - .attr( 'aria-label', wpColorPickerL10n.clearAriaLabel ); - } - - // Wrap the wrapping label in its wrapper and append the Clear/Default button. - self.wrappingLabel - .wrap( '<span class="wp-picker-input-wrap hidden" />' ) - .after( self.button ); - - /* - * The input wrapper now contains the label+input+Clear/Default button. - * Store a reference to the input wrapper: we'll use this to toggle - * the controls visibility. - */ - self.inputWrapper = el.closest( '.wp-picker-input-wrap' ); - - el.iris( { - target: self.pickerContainer, - hide: self.options.hide, - width: self.options.width, - mode: self.options.mode, - palettes: self.options.palettes, - /** - * Handles the onChange event if one has been defined in the options and additionally - * sets the background color for the toggler element. - * - * @since 3.5.0 - * - * @ignore - * - * @param {Event} event The event that's being called. - * @param {HTMLElement} ui The HTMLElement containing the color picker. - * - * @returns {void} - */ - change: function( event, ui ) { - self.toggler.css( { backgroundColor: ui.color.toString() } ); - - if ( $.isFunction( self.options.change ) ) { - self.options.change.call( this, event, ui ); - } - } - } ); - - el.val( self.initialValue ); - self._addListeners(); - - // Force the color picker to always be closed on initial load. - if ( ! self.options.hide ) { - self.toggler.click(); - } - }, - /** - * Binds event listeners to the color picker. - * - * @since 3.5.0 - * - * @access private - * - * @returns {void} - */ - _addListeners: function() { - var self = this; - - /** - * Prevent any clicks inside this widget from leaking to the top and closing it. - * - * @since 3.5.0 - * - * @param {Event} event The event that's being called. - * - * @returs {void} - */ - self.wrap.on( 'click.wpcolorpicker', function( event ) { - event.stopPropagation(); - }); - - /** - * Open or close the color picker depending on the class. - * - * @since 3.5 - */ - self.toggler.click( function(){ - if ( self.toggler.hasClass( 'wp-picker-open' ) ) { - self.close(); - } else { - self.open(); - } - }); - - /** - * Checks if value is empty when changing the color in the color picker. - * If so, the background color is cleared. - * - * @since 3.5.0 - * - * @param {Event} event The event that's being called. - * - * @returns {void} - */ - self.element.change( function( event ) { - var me = $( this ), - val = me.val(); - - if ( val === '' || val === '#' ) { - self.toggler.css( 'backgroundColor', '' ); - // Fire clear callback if we have one. - if ( $.isFunction( self.options.clear ) ) { - self.options.clear.call( this, event ); - } - } - }); - - /** - * Enables the user to either clear the color in the color picker or revert back to the default color. - * - * @since 3.5.0 - * - * @param {Event} event The event that's being called. - * - * @returns {void} - */ - self.button.click( function( event ) { - var me = $( this ); - if ( me.hasClass( 'wp-picker-clear' ) ) { - self.element.val( '' ); - self.toggler.css( 'backgroundColor', '' ); - if ( $.isFunction( self.options.clear ) ) { - self.options.clear.call( this, event ); - } - } else if ( me.hasClass( 'wp-picker-default' ) ) { - self.element.val( self.options.defaultColor ).change(); - } - }); - }, - /** - * Opens the color picker dialog. - * - * @since 3.5.0 - * - * @returns {void} - */ - open: function() { - this.element.iris( 'toggle' ); - this.inputWrapper.removeClass( 'hidden' ); - this.wrap.addClass( 'wp-picker-active' ); - this.toggler - .addClass( 'wp-picker-open' ) - .attr( 'aria-expanded', 'true' ); - $( 'body' ).trigger( 'click.wpcolorpicker' ).on( 'click.wpcolorpicker', this.close ); - }, - /** - * Closes the color picker dialog. - * - * @since 3.5.0 - * - * @returns {void} - */ - close: function() { - this.element.iris( 'toggle' ); - this.inputWrapper.addClass( 'hidden' ); - this.wrap.removeClass( 'wp-picker-active' ); - this.toggler - .removeClass( 'wp-picker-open' ) - .attr( 'aria-expanded', 'false' ); - $( 'body' ).off( 'click.wpcolorpicker', this.close ); - }, - /** - * Returns the iris object if no new color is provided. If a new color is provided, it sets the new color. - * - * @param newColor {string|*} The new color to use. Can be undefined. - * - * @since 3.5.0 - * - * @returns {string} The element's color - */ - color: function( newColor ) { - if ( newColor === undef ) { - return this.element.iris( 'option', 'color' ); - } - this.element.iris( 'option', 'color', newColor ); - }, - /** - * Returns the iris object if no new default color is provided. - * If a new default color is provided, it sets the new default color. - * - * @param newDefaultColor {string|*} The new default color to use. Can be undefined. - * - * @since 3.5.0 - * - * @returns {boolean|string} The element's color. - */ - defaultColor: function( newDefaultColor ) { - if ( newDefaultColor === undef ) { - return this.options.defaultColor; - } - - this.options.defaultColor = newDefaultColor; - } - }; - - // Register the color picker as a widget. - $.widget( 'wp.wpColorPicker', ColorPicker ); -}( jQuery ) ); diff --git a/srcs/wordpress/wp-admin/js/color-picker.min.js b/srcs/wordpress/wp-admin/js/color-picker.min.js deleted file mode 100644 index d16373b..0000000 --- a/srcs/wordpress/wp-admin/js/color-picker.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(i,t){var e;e={options:{defaultColor:!1,change:!1,clear:!1,hide:!0,palettes:!0,width:255,mode:"hsv",type:"full",slider:"horizontal"},_createHueOnly:function(){var e,o=this,t=o.element;t.hide(),e="hsl("+t.val()+", 100, 50)",t.iris({mode:"hsl",type:"hue",hide:!1,color:e,change:function(e,t){i.isFunction(o.options.change)&&o.options.change.call(this,e,t)},width:o.options.width,slider:o.options.slider})},_create:function(){if(i.support.iris){var o=this,e=o.element;if(i.extend(o.options,e.data()),"hue"===o.options.type)return o._createHueOnly();o.close=i.proxy(o.close,o),o.initialValue=e.val(),e.addClass("wp-color-picker"),e.parent("label").length||(e.wrap("<label></label>"),o.wrappingLabelText=i('<span class="screen-reader-text"></span>').insertBefore(e).text(wpColorPickerL10n.defaultLabel)),o.wrappingLabel=e.parent(),o.wrappingLabel.wrap('<div class="wp-picker-container" />'),o.wrap=o.wrappingLabel.parent(),o.toggler=i('<button type="button" class="button wp-color-result" aria-expanded="false"><span class="wp-color-result-text"></span></button>').insertBefore(o.wrappingLabel).css({backgroundColor:o.initialValue}),o.toggler.find(".wp-color-result-text").text(wpColorPickerL10n.pick),o.pickerContainer=i('<div class="wp-picker-holder" />').insertAfter(o.wrappingLabel),o.button=i('<input type="button" class="button button-small" />'),o.options.defaultColor?o.button.addClass("wp-picker-default").val(wpColorPickerL10n.defaultString).attr("aria-label",wpColorPickerL10n.defaultAriaLabel):o.button.addClass("wp-picker-clear").val(wpColorPickerL10n.clear).attr("aria-label",wpColorPickerL10n.clearAriaLabel),o.wrappingLabel.wrap('<span class="wp-picker-input-wrap hidden" />').after(o.button),o.inputWrapper=e.closest(".wp-picker-input-wrap"),e.iris({target:o.pickerContainer,hide:o.options.hide,width:o.options.width,mode:o.options.mode,palettes:o.options.palettes,change:function(e,t){o.toggler.css({backgroundColor:t.color.toString()}),i.isFunction(o.options.change)&&o.options.change.call(this,e,t)}}),e.val(o.initialValue),o._addListeners(),o.options.hide||o.toggler.click()}},_addListeners:function(){var o=this;o.wrap.on("click.wpcolorpicker",function(e){e.stopPropagation()}),o.toggler.click(function(){o.toggler.hasClass("wp-picker-open")?o.close():o.open()}),o.element.change(function(e){var t=i(this).val();""!==t&&"#"!==t||(o.toggler.css("backgroundColor",""),i.isFunction(o.options.clear)&&o.options.clear.call(this,e))}),o.button.click(function(e){var t=i(this);t.hasClass("wp-picker-clear")?(o.element.val(""),o.toggler.css("backgroundColor",""),i.isFunction(o.options.clear)&&o.options.clear.call(this,e)):t.hasClass("wp-picker-default")&&o.element.val(o.options.defaultColor).change()})},open:function(){this.element.iris("toggle"),this.inputWrapper.removeClass("hidden"),this.wrap.addClass("wp-picker-active"),this.toggler.addClass("wp-picker-open").attr("aria-expanded","true"),i("body").trigger("click.wpcolorpicker").on("click.wpcolorpicker",this.close)},close:function(){this.element.iris("toggle"),this.inputWrapper.addClass("hidden"),this.wrap.removeClass("wp-picker-active"),this.toggler.removeClass("wp-picker-open").attr("aria-expanded","false"),i("body").off("click.wpcolorpicker",this.close)},color:function(e){if(e===t)return this.element.iris("option","color");this.element.iris("option","color",e)},defaultColor:function(e){if(e===t)return this.options.defaultColor;this.options.defaultColor=e}},i.widget("wp.wpColorPicker",e)}(jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/comment.js b/srcs/wordpress/wp-admin/js/comment.js deleted file mode 100644 index 04d6e53..0000000 --- a/srcs/wordpress/wp-admin/js/comment.js +++ /dev/null @@ -1,101 +0,0 @@ -/** - * @output wp-admin/js/comment.js - */ - -/* global postboxes, commentL10n */ - -/** - * Binds to the document ready event. - * - * @since 2.5.0 - * - * @param {jQuery} $ The jQuery object. - */ -jQuery(document).ready( function($) { - - postboxes.add_postbox_toggles('comment'); - - var $timestampdiv = $('#timestampdiv'), - $timestamp = $( '#timestamp' ), - stamp = $timestamp.html(), - $timestampwrap = $timestampdiv.find( '.timestamp-wrap' ), - $edittimestamp = $timestampdiv.siblings( 'a.edit-timestamp' ); - - /** - * Adds event that opens the time stamp form if the form is hidden. - * - * @listens $edittimestamp:click - * - * @param {Event} event The event object. - * @returns {void} - */ - $edittimestamp.click( function( event ) { - if ( $timestampdiv.is( ':hidden' ) ) { - // Slide down the form and set focus on the first field. - $timestampdiv.slideDown( 'fast', function() { - $( 'input, select', $timestampwrap ).first().focus(); - } ); - $(this).hide(); - } - event.preventDefault(); - }); - - /** - * Resets the time stamp values when the cancel button is clicked. - * - * @listens .cancel-timestamp:click - * - * @param {Event} event The event object. - * @returns {void} - */ - - $timestampdiv.find('.cancel-timestamp').click( function( event ) { - // Move focus back to the Edit link. - $edittimestamp.show().focus(); - $timestampdiv.slideUp( 'fast' ); - $('#mm').val($('#hidden_mm').val()); - $('#jj').val($('#hidden_jj').val()); - $('#aa').val($('#hidden_aa').val()); - $('#hh').val($('#hidden_hh').val()); - $('#mn').val($('#hidden_mn').val()); - $timestamp.html( stamp ); - event.preventDefault(); - }); - - /** - * Sets the time stamp values when the ok button is clicked. - * - * @listens .save-timestamp:click - * - * @param {Event} event The event object. - * @returns {void} - */ - $timestampdiv.find('.save-timestamp').click( function( event ) { // crazyhorse - multiple ok cancels - var aa = $('#aa').val(), mm = $('#mm').val(), jj = $('#jj').val(), hh = $('#hh').val(), mn = $('#mn').val(), - newD = new Date( aa, mm - 1, jj, hh, mn ); - - event.preventDefault(); - - if ( newD.getFullYear() != aa || (1 + newD.getMonth()) != mm || newD.getDate() != jj || newD.getMinutes() != mn ) { - $timestampwrap.addClass( 'form-invalid' ); - return; - } else { - $timestampwrap.removeClass( 'form-invalid' ); - } - - $timestamp.html( - commentL10n.submittedOn + ' <b>' + - commentL10n.dateFormat - .replace( '%1$s', $( 'option[value="' + mm + '"]', '#mm' ).attr( 'data-text' ) ) - .replace( '%2$s', parseInt( jj, 10 ) ) - .replace( '%3$s', aa ) - .replace( '%4$s', ( '00' + hh ).slice( -2 ) ) - .replace( '%5$s', ( '00' + mn ).slice( -2 ) ) + - '</b> ' - ); - - // Move focus back to the Edit link. - $edittimestamp.show().focus(); - $timestampdiv.slideUp( 'fast' ); - }); -}); diff --git a/srcs/wordpress/wp-admin/js/comment.min.js b/srcs/wordpress/wp-admin/js/comment.min.js deleted file mode 100644 index 39c0efc..0000000 --- a/srcs/wordpress/wp-admin/js/comment.min.js +++ /dev/null @@ -1 +0,0 @@ -jQuery(document).ready(function(m){postboxes.add_postbox_toggles("comment");var d=m("#timestampdiv"),c=m("#timestamp"),a=c.html(),o=d.find(".timestamp-wrap"),v=d.siblings("a.edit-timestamp");v.click(function(e){d.is(":hidden")&&(d.slideDown("fast",function(){m("input, select",o).first().focus()}),m(this).hide()),e.preventDefault()}),d.find(".cancel-timestamp").click(function(e){v.show().focus(),d.slideUp("fast"),m("#mm").val(m("#hidden_mm").val()),m("#jj").val(m("#hidden_jj").val()),m("#aa").val(m("#hidden_aa").val()),m("#hh").val(m("#hidden_hh").val()),m("#mn").val(m("#hidden_mn").val()),c.html(a),e.preventDefault()}),d.find(".save-timestamp").click(function(e){var a=m("#aa").val(),t=m("#mm").val(),l=m("#jj").val(),i=m("#hh").val(),n=m("#mn").val(),s=new Date(a,t-1,l,i,n);e.preventDefault(),s.getFullYear()==a&&1+s.getMonth()==t&&s.getDate()==l&&s.getMinutes()==n?(o.removeClass("form-invalid"),c.html(commentL10n.submittedOn+" <b>"+commentL10n.dateFormat.replace("%1$s",m('option[value="'+t+'"]',"#mm").attr("data-text")).replace("%2$s",parseInt(l,10)).replace("%3$s",a).replace("%4$s",("00"+i).slice(-2)).replace("%5$s",("00"+n).slice(-2))+"</b> "),v.show().focus(),d.slideUp("fast")):o.addClass("form-invalid")})});
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/common.js b/srcs/wordpress/wp-admin/js/common.js deleted file mode 100644 index 049b7de..0000000 --- a/srcs/wordpress/wp-admin/js/common.js +++ /dev/null @@ -1,1648 +0,0 @@ -/** - * @output wp-admin/js/common.js - */ - -/* global setUserSetting, ajaxurl, commonL10n, alert, confirm, pagenow */ -/* global columns, screenMeta */ - -/** - * Adds common WordPress functionality to the window. - * - * @param {jQuery} $ jQuery object. - * @param {Object} window The window object. - * @param {mixed} undefined Unused. - */ -( function( $, window, undefined ) { - var $document = $( document ), - $window = $( window ), - $body = $( document.body ); - -/** - * Removed in 3.3.0, needed for back-compatibility. - * - * @since 2.7.0 - * @deprecated 3.3.0 - */ -window.adminMenu = { - init : function() {}, - fold : function() {}, - restoreMenuState : function() {}, - toggle : function() {}, - favorites : function() {} -}; - -// Show/hide/save table columns. -window.columns = { - - /** - * Initializes the column toggles in the screen options. - * - * Binds an onClick event to the checkboxes to show or hide the table columns - * based on their toggled state. And persists the toggled state. - * - * @since 2.7.0 - * - * @returns {void} - */ - init : function() { - var that = this; - $('.hide-column-tog', '#adv-settings').click( function() { - var $t = $(this), column = $t.val(); - if ( $t.prop('checked') ) - that.checked(column); - else - that.unchecked(column); - - columns.saveManageColumnsState(); - }); - }, - - /** - * Saves the toggled state for the columns. - * - * Saves whether the columns should be shown or hidden on a page. - * - * @since 3.0.0 - * - * @returns {void} - */ - saveManageColumnsState : function() { - var hidden = this.hidden(); - $.post(ajaxurl, { - action: 'hidden-columns', - hidden: hidden, - screenoptionnonce: $('#screenoptionnonce').val(), - page: pagenow - }); - }, - - /** - * Makes a column visible and adjusts the column span for the table. - * - * @since 3.0.0 - * @param {string} column The column name. - * - * @returns {void} - */ - checked : function(column) { - $('.column-' + column).removeClass( 'hidden' ); - this.colSpanChange(+1); - }, - - /** - * Hides a column and adjusts the column span for the table. - * - * @since 3.0.0 - * @param {string} column The column name. - * - * @returns {void} - */ - unchecked : function(column) { - $('.column-' + column).addClass( 'hidden' ); - this.colSpanChange(-1); - }, - - /** - * Gets all hidden columns. - * - * @since 3.0.0 - * - * @returns {string} The hidden column names separated by a comma. - */ - hidden : function() { - return $( '.manage-column[id]' ).filter( '.hidden' ).map(function() { - return this.id; - }).get().join( ',' ); - }, - - /** - * Gets the checked column toggles from the screen options. - * - * @since 3.0.0 - * - * @returns {string} String containing the checked column names. - */ - useCheckboxesForHidden : function() { - this.hidden = function(){ - return $('.hide-column-tog').not(':checked').map(function() { - var id = this.id; - return id.substring( id, id.length - 5 ); - }).get().join(','); - }; - }, - - /** - * Adjusts the column span for the table. - * - * @since 3.1.0 - * - * @param {int} diff The modifier for the column span. - */ - colSpanChange : function(diff) { - var $t = $('table').find('.colspanchange'), n; - if ( !$t.length ) - return; - n = parseInt( $t.attr('colspan'), 10 ) + diff; - $t.attr('colspan', n.toString()); - } -}; - -$document.ready(function(){columns.init();}); - -/** - * Validates that the required form fields are not empty. - * - * @since 2.9.0 - * - * @param {jQuery} form The form to validate. - * - * @returns {boolean} Returns true if all required fields are not an empty string. - */ -window.validateForm = function( form ) { - return !$( form ) - .find( '.form-required' ) - .filter( function() { return $( ':input:visible', this ).val() === ''; } ) - .addClass( 'form-invalid' ) - .find( ':input:visible' ) - .change( function() { $( this ).closest( '.form-invalid' ).removeClass( 'form-invalid' ); } ) - .length; -}; - -// stub for doing better warnings -/** - * Shows message pop-up notice or confirmation message. - * - * @since 2.7.0 - * - * @type {{warn: showNotice.warn, note: showNotice.note}} - * - * @returns {void} - */ -window.showNotice = { - - /** - * Shows a delete confirmation pop-up message. - * - * @since 2.7.0 - * - * @returns {boolean} Returns true if the message is confirmed. - */ - warn : function() { - var msg = commonL10n.warnDelete || ''; - if ( confirm(msg) ) { - return true; - } - - return false; - }, - - /** - * Shows an alert message. - * - * @since 2.7.0 - * - * @param text The text to display in the message. - */ - note : function(text) { - alert(text); - } -}; - -/** - * Represents the functions for the meta screen options panel. - * - * @since 3.2.0 - * - * @type {{element: null, toggles: null, page: null, init: screenMeta.init, - * toggleEvent: screenMeta.toggleEvent, open: screenMeta.open, - * close: screenMeta.close}} - * - * @returns {void} - */ -window.screenMeta = { - element: null, // #screen-meta - toggles: null, // .screen-meta-toggle - page: null, // #wpcontent - - /** - * Initializes the screen meta options panel. - * - * @since 3.2.0 - * - * @returns {void} - */ - init: function() { - this.element = $('#screen-meta'); - this.toggles = $( '#screen-meta-links' ).find( '.show-settings' ); - this.page = $('#wpcontent'); - - this.toggles.click( this.toggleEvent ); - }, - - /** - * Toggles the screen meta options panel. - * - * @since 3.2.0 - * - * @returns {void} - */ - toggleEvent: function() { - var panel = $( '#' + $( this ).attr( 'aria-controls' ) ); - - if ( !panel.length ) - return; - - if ( panel.is(':visible') ) - screenMeta.close( panel, $(this) ); - else - screenMeta.open( panel, $(this) ); - }, - - /** - * Opens the screen meta options panel. - * - * @since 3.2.0 - * - * @param {jQuery} panel The screen meta options panel div. - * @param {jQuery} button The toggle button. - * - * @returns {void} - */ - open: function( panel, button ) { - - $( '#screen-meta-links' ).find( '.screen-meta-toggle' ).not( button.parent() ).css( 'visibility', 'hidden' ); - - panel.parent().show(); - - /** - * Sets the focus to the meta options panel and adds the necessary CSS classes. - * - * @since 3.2.0 - * - * @returns {void} - */ - panel.slideDown( 'fast', function() { - panel.focus(); - button.addClass( 'screen-meta-active' ).attr( 'aria-expanded', true ); - }); - - $document.trigger( 'screen:options:open' ); - }, - - /** - * Closes the screen meta options panel. - * - * @since 3.2.0 - * - * @param {jQuery} panel The screen meta options panel div. - * @param {jQuery} button The toggle button. - * - * @returns {void} - */ - close: function( panel, button ) { - /** - * Hides the screen meta options panel. - * - * @since 3.2.0 - * - * @returns {void} - */ - panel.slideUp( 'fast', function() { - button.removeClass( 'screen-meta-active' ).attr( 'aria-expanded', false ); - $('.screen-meta-toggle').css('visibility', ''); - panel.parent().hide(); - }); - - $document.trigger( 'screen:options:close' ); - } -}; - -/** - * Initializes the help tabs in the help panel. - * - * @param {Event} e The event object. - * - * @returns {void} - */ -$('.contextual-help-tabs').delegate('a', 'click', function(e) { - var link = $(this), - panel; - - e.preventDefault(); - - // Don't do anything if the click is for the tab already showing. - if ( link.is('.active a') ) - return false; - - // Links - $('.contextual-help-tabs .active').removeClass('active'); - link.parent('li').addClass('active'); - - panel = $( link.attr('href') ); - - // Panels - $('.help-tab-content').not( panel ).removeClass('active').hide(); - panel.addClass('active').show(); -}); - -/** - * Update custom permalink structure via buttons. - */ -var permalinkStructureFocused = false, - $permalinkStructure = $( '#permalink_structure' ), - $permalinkStructureInputs = $( '.permalink-structure input:radio' ), - $permalinkCustomSelection = $( '#custom_selection' ), - $availableStructureTags = $( '.form-table.permalink-structure .available-structure-tags button' ); - -// Change permalink structure input when selecting one of the common structures. -$permalinkStructureInputs.on( 'change', function() { - if ( 'custom' === this.value ) { - return; - } - - $permalinkStructure.val( this.value ); - - // Update button states after selection. - $availableStructureTags.each( function() { - changeStructureTagButtonState( $( this ) ); - } ); -} ); - -$permalinkStructure.on( 'click input', function() { - $permalinkCustomSelection.prop( 'checked', true ); -} ); - -// Check if the permalink structure input field has had focus at least once. -$permalinkStructure.on( 'focus', function( event ) { - permalinkStructureFocused = true; - $( this ).off( event ); -} ); - -/** - * Enables or disables a structure tag button depending on its usage. - * - * If the structure is already used in the custom permalink structure, - * it will be disabled. - * - * @param {object} button Button jQuery object. - */ -function changeStructureTagButtonState( button ) { - if ( -1 !== $permalinkStructure.val().indexOf( button.text().trim() ) ) { - button.attr( 'data-label', button.attr( 'aria-label' ) ); - button.attr( 'aria-label', button.attr( 'data-used' ) ); - button.attr( 'aria-pressed', true ); - button.addClass( 'active' ); - } else if ( button.attr( 'data-label' ) ) { - button.attr( 'aria-label', button.attr( 'data-label' ) ); - button.attr( 'aria-pressed', false ); - button.removeClass( 'active' ); - } -} - -// Check initial button state. -$availableStructureTags.each( function() { - changeStructureTagButtonState( $( this ) ); -} ); - -// Observe permalink structure field and disable buttons of tags that are already present. -$permalinkStructure.on( 'change', function() { - $availableStructureTags.each( function() { - changeStructureTagButtonState( $( this ) ); - } ); -} ); - -$availableStructureTags.on( 'click', function() { - var permalinkStructureValue = $permalinkStructure.val(), - selectionStart = $permalinkStructure[ 0 ].selectionStart, - selectionEnd = $permalinkStructure[ 0 ].selectionEnd, - textToAppend = $( this ).text().trim(), - textToAnnounce = $( this ).attr( 'data-added' ), - newSelectionStart; - - // Remove structure tag if already part of the structure. - if ( -1 !== permalinkStructureValue.indexOf( textToAppend ) ) { - permalinkStructureValue = permalinkStructureValue.replace( textToAppend + '/', '' ); - - $permalinkStructure.val( '/' === permalinkStructureValue ? '' : permalinkStructureValue ); - - // Announce change to screen readers. - $( '#custom_selection_updated' ).text( textToAnnounce ); - - // Disable button. - changeStructureTagButtonState( $( this ) ); - - return; - } - - // Input field never had focus, move selection to end of input. - if ( ! permalinkStructureFocused && 0 === selectionStart && 0 === selectionEnd ) { - selectionStart = selectionEnd = permalinkStructureValue.length; - } - - $permalinkCustomSelection.prop( 'checked', true ); - - // Prepend and append slashes if necessary. - if ( '/' !== permalinkStructureValue.substr( 0, selectionStart ).substr( -1 ) ) { - textToAppend = '/' + textToAppend; - } - - if ( '/' !== permalinkStructureValue.substr( selectionEnd, 1 ) ) { - textToAppend = textToAppend + '/'; - } - - // Insert structure tag at the specified position. - $permalinkStructure.val( permalinkStructureValue.substr( 0, selectionStart ) + textToAppend + permalinkStructureValue.substr( selectionEnd ) ); - - // Announce change to screen readers. - $( '#custom_selection_updated' ).text( textToAnnounce ); - - // Disable button. - changeStructureTagButtonState( $( this ) ); - - // If input had focus give it back with cursor right after appended text. - if ( permalinkStructureFocused && $permalinkStructure[0].setSelectionRange ) { - newSelectionStart = ( permalinkStructureValue.substr( 0, selectionStart ) + textToAppend ).length; - $permalinkStructure[0].setSelectionRange( newSelectionStart, newSelectionStart ); - $permalinkStructure.focus(); - } -} ); - -$document.ready( function() { - var checks, first, last, checked, sliced, mobileEvent, transitionTimeout, focusedRowActions, - lastClicked = false, - pageInput = $('input.current-page'), - currentPage = pageInput.val(), - isIOS = /iPhone|iPad|iPod/.test( navigator.userAgent ), - isAndroid = navigator.userAgent.indexOf( 'Android' ) !== -1, - isIE8 = $( document.documentElement ).hasClass( 'ie8' ), - $adminMenuWrap = $( '#adminmenuwrap' ), - $wpwrap = $( '#wpwrap' ), - $adminmenu = $( '#adminmenu' ), - $overlay = $( '#wp-responsive-overlay' ), - $toolbar = $( '#wp-toolbar' ), - $toolbarPopups = $toolbar.find( 'a[aria-haspopup="true"]' ), - $sortables = $('.meta-box-sortables'), - wpResponsiveActive = false, - $adminbar = $( '#wpadminbar' ), - lastScrollPosition = 0, - pinnedMenuTop = false, - pinnedMenuBottom = false, - menuTop = 0, - menuState, - menuIsPinned = false, - height = { - window: $window.height(), - wpwrap: $wpwrap.height(), - adminbar: $adminbar.height(), - menu: $adminMenuWrap.height() - }, - $headerEnd = $( '.wp-header-end' ); - - /** - * Makes the fly-out submenu header clickable, when the menu is folded. - * - * @param {Event} e The event object. - * - * @returns {void} - */ - $adminmenu.on('click.wp-submenu-head', '.wp-submenu-head', function(e){ - $(e.target).parent().siblings('a').get(0).click(); - }); - - /** - * Collapses the admin menu. - * - * @returns {void} - */ - $( '#collapse-button' ).on( 'click.collapse-menu', function() { - var viewportWidth = getViewportWidth() || 961; - - // reset any compensation for submenus near the bottom of the screen - $('#adminmenu div.wp-submenu').css('margin-top', ''); - - if ( viewportWidth < 960 ) { - if ( $body.hasClass('auto-fold') ) { - $body.removeClass('auto-fold').removeClass('folded'); - setUserSetting('unfold', 1); - setUserSetting('mfold', 'o'); - menuState = 'open'; - } else { - $body.addClass('auto-fold'); - setUserSetting('unfold', 0); - menuState = 'folded'; - } - } else { - if ( $body.hasClass('folded') ) { - $body.removeClass('folded'); - setUserSetting('mfold', 'o'); - menuState = 'open'; - } else { - $body.addClass('folded'); - setUserSetting('mfold', 'f'); - menuState = 'folded'; - } - } - - $document.trigger( 'wp-collapse-menu', { state: menuState } ); - }); - - /** - * Handles the `aria-haspopup` attribute on the current menu item when it has a submenu. - * - * @since 4.4.0 - * - * @returns {void} - */ - function currentMenuItemHasPopup() { - var $current = $( 'a.wp-has-current-submenu' ); - - if ( 'folded' === menuState ) { - // When folded or auto-folded and not responsive view, the current menu item does have a fly-out sub-menu. - $current.attr( 'aria-haspopup', 'true' ); - } else { - // When expanded or in responsive view, reset aria-haspopup. - $current.attr( 'aria-haspopup', 'false' ); - } - } - - $document.on( 'wp-menu-state-set wp-collapse-menu wp-responsive-activate wp-responsive-deactivate', currentMenuItemHasPopup ); - - /** - * Ensures an admin submenu is within the visual viewport. - * - * @since 4.1.0 - * - * @param {jQuery} $menuItem The parent menu item containing the submenu. - * - * @returns {void} - */ - function adjustSubmenu( $menuItem ) { - var bottomOffset, pageHeight, adjustment, theFold, menutop, wintop, maxtop, - $submenu = $menuItem.find( '.wp-submenu' ); - - menutop = $menuItem.offset().top; - wintop = $window.scrollTop(); - maxtop = menutop - wintop - 30; // max = make the top of the sub almost touch admin bar - - bottomOffset = menutop + $submenu.height() + 1; // Bottom offset of the menu - pageHeight = $wpwrap.height(); // Height of the entire page - adjustment = 60 + bottomOffset - pageHeight; - theFold = $window.height() + wintop - 50; // The fold - - if ( theFold < ( bottomOffset - adjustment ) ) { - adjustment = bottomOffset - theFold; - } - - if ( adjustment > maxtop ) { - adjustment = maxtop; - } - - if ( adjustment > 1 ) { - $submenu.css( 'margin-top', '-' + adjustment + 'px' ); - } else { - $submenu.css( 'margin-top', '' ); - } - } - - if ( 'ontouchstart' in window || /IEMobile\/[1-9]/.test(navigator.userAgent) ) { // touch screen device - // iOS Safari works with touchstart, the rest work with click - mobileEvent = isIOS ? 'touchstart' : 'click'; - - /** - * Closes any open submenus when touch/click is not on the menu. - * - * @param {Event} e The event object. - * - * @returns {void} - */ - $body.on( mobileEvent+'.wp-mobile-hover', function(e) { - if ( $adminmenu.data('wp-responsive') ) { - return; - } - - if ( ! $( e.target ).closest( '#adminmenu' ).length ) { - $adminmenu.find( 'li.opensub' ).removeClass( 'opensub' ); - } - }); - - /** - * Handles the opening or closing the submenu based on the mobile click|touch event. - * - * @param {Event} event The event object. - * - * @returns {void} - */ - $adminmenu.find( 'a.wp-has-submenu' ).on( mobileEvent + '.wp-mobile-hover', function( event ) { - var $menuItem = $(this).parent(); - - if ( $adminmenu.data( 'wp-responsive' ) ) { - return; - } - - // Show the sub instead of following the link if: - // - the submenu is not open - // - the submenu is not shown inline or the menu is not folded - if ( ! $menuItem.hasClass( 'opensub' ) && ( ! $menuItem.hasClass( 'wp-menu-open' ) || $menuItem.width() < 40 ) ) { - event.preventDefault(); - adjustSubmenu( $menuItem ); - $adminmenu.find( 'li.opensub' ).removeClass( 'opensub' ); - $menuItem.addClass('opensub'); - } - }); - } - - if ( ! isIOS && ! isAndroid ) { - $adminmenu.find( 'li.wp-has-submenu' ).hoverIntent({ - - /** - * Opens the submenu when hovered over the menu item for desktops. - * - * @returns {void} - */ - over: function() { - var $menuItem = $( this ), - $submenu = $menuItem.find( '.wp-submenu' ), - top = parseInt( $submenu.css( 'top' ), 10 ); - - if ( isNaN( top ) || top > -5 ) { // the submenu is visible - return; - } - - if ( $adminmenu.data( 'wp-responsive' ) ) { - // The menu is in responsive mode, bail - return; - } - - adjustSubmenu( $menuItem ); - $adminmenu.find( 'li.opensub' ).removeClass( 'opensub' ); - $menuItem.addClass( 'opensub' ); - }, - - /** - * Closes the submenu when no longer hovering the menu item. - * - * @returns {void} - */ - out: function(){ - if ( $adminmenu.data( 'wp-responsive' ) ) { - // The menu is in responsive mode, bail - return; - } - - $( this ).removeClass( 'opensub' ).find( '.wp-submenu' ).css( 'margin-top', '' ); - }, - timeout: 200, - sensitivity: 7, - interval: 90 - }); - - /** - * Opens the submenu on when focused on the menu item. - * - * @param {Event} event The event object. - * - * @returns {void} - */ - $adminmenu.on( 'focus.adminmenu', '.wp-submenu a', function( event ) { - if ( $adminmenu.data( 'wp-responsive' ) ) { - // The menu is in responsive mode, bail - return; - } - - $( event.target ).closest( 'li.menu-top' ).addClass( 'opensub' ); - - /** - * Closes the submenu on blur from the menu item. - * - * @param {Event} event The event object. - * - * @returns {void} - */ - }).on( 'blur.adminmenu', '.wp-submenu a', function( event ) { - if ( $adminmenu.data( 'wp-responsive' ) ) { - return; - } - - $( event.target ).closest( 'li.menu-top' ).removeClass( 'opensub' ); - - /** - * Adjusts the size for the submenu. - * - * @returns {void} - */ - }).find( 'li.wp-has-submenu.wp-not-current-submenu' ).on( 'focusin.adminmenu', function() { - adjustSubmenu( $( this ) ); - }); - } - - /* - * The `.below-h2` class is here just for backward compatibility with plugins - * that are (incorrectly) using it. Do not use. Use `.inline` instead. See #34570. - * If '.wp-header-end' is found, append the notices after it otherwise - * after the first h1 or h2 heading found within the main content. - */ - if ( ! $headerEnd.length ) { - $headerEnd = $( '.wrap h1, .wrap h2' ).first(); - } - $( 'div.updated, div.error, div.notice' ).not( '.inline, .below-h2' ).insertAfter( $headerEnd ); - - /** - * Makes notices dismissible. - * - * @since 4.4.0 - * - * @returns {void} - */ - function makeNoticesDismissible() { - $( '.notice.is-dismissible' ).each( function() { - var $el = $( this ), - $button = $( '<button type="button" class="notice-dismiss"><span class="screen-reader-text"></span></button>' ), - btnText = commonL10n.dismiss || ''; - - // Ensure plain text - $button.find( '.screen-reader-text' ).text( btnText ); - $button.on( 'click.wp-dismiss-notice', function( event ) { - event.preventDefault(); - $el.fadeTo( 100, 0, function() { - $el.slideUp( 100, function() { - $el.remove(); - }); - }); - }); - - $el.append( $button ); - }); - } - - $document.on( 'wp-updates-notice-added wp-plugin-install-error wp-plugin-update-error wp-plugin-delete-error wp-theme-install-error wp-theme-delete-error', makeNoticesDismissible ); - - // Init screen meta - screenMeta.init(); - - /** - * Checks a checkbox. - * - * This event needs to be delegated. Ticket #37973. - * - * @returns {boolean} Returns whether a checkbox is checked or not. - */ - $body.on( 'click', 'tbody > tr > .check-column :checkbox', function( event ) { - // Shift click to select a range of checkboxes. - if ( 'undefined' == event.shiftKey ) { return true; } - if ( event.shiftKey ) { - if ( !lastClicked ) { return true; } - checks = $( lastClicked ).closest( 'form' ).find( ':checkbox' ).filter( ':visible:enabled' ); - first = checks.index( lastClicked ); - last = checks.index( this ); - checked = $(this).prop('checked'); - if ( 0 < first && 0 < last && first != last ) { - sliced = ( last > first ) ? checks.slice( first, last ) : checks.slice( last, first ); - sliced.prop( 'checked', function() { - if ( $(this).closest('tr').is(':visible') ) - return checked; - - return false; - }); - } - } - lastClicked = this; - - // Toggle the "Select all" checkboxes depending if the other ones are all checked or not. - var unchecked = $(this).closest('tbody').find(':checkbox').filter(':visible:enabled').not(':checked'); - - /** - * Determines if all checkboxes are checked. - * - * @returns {boolean} Returns true if there are no unchecked checkboxes. - */ - $(this).closest('table').children('thead, tfoot').find(':checkbox').prop('checked', function() { - return ( 0 === unchecked.length ); - }); - - return true; - }); - - /** - * Controls all the toggles on bulk toggle change. - * - * When the bulk checkbox is changed, all the checkboxes in the tables are changed accordingly. - * When the shift-button is pressed while changing the bulk checkbox the checkboxes in the table are inverted. - * - * This event needs to be delegated. Ticket #37973. - * - * @param {Event} event The event object. - * - * @returns {boolean} - */ - $body.on( 'click.wp-toggle-checkboxes', 'thead .check-column :checkbox, tfoot .check-column :checkbox', function( event ) { - var $this = $(this), - $table = $this.closest( 'table' ), - controlChecked = $this.prop('checked'), - toggle = event.shiftKey || $this.data('wp-toggle'); - - $table.children( 'tbody' ).filter(':visible') - .children().children('.check-column').find(':checkbox') - /** - * Updates the checked state on the checkbox in the table. - * - * @returns {boolean} True checks the checkbox, False unchecks the checkbox. - */ - .prop('checked', function() { - if ( $(this).is(':hidden,:disabled') ) { - return false; - } - - if ( toggle ) { - return ! $(this).prop( 'checked' ); - } else if ( controlChecked ) { - return true; - } - - return false; - }); - - $table.children('thead, tfoot').filter(':visible') - .children().children('.check-column').find(':checkbox') - - /** - * Syncs the bulk checkboxes on the top and bottom of the table. - * - * @returns {boolean} True checks the checkbox, False unchecks the checkbox. - */ - .prop('checked', function() { - if ( toggle ) { - return false; - } else if ( controlChecked ) { - return true; - } - - return false; - }); - }); - - /** - * Shows row actions on focus of its parent container element or any other elements contained within. - * - * @returns {void} - */ - $( '#wpbody-content' ).on({ - focusin: function() { - clearTimeout( transitionTimeout ); - focusedRowActions = $( this ).find( '.row-actions' ); - // transitionTimeout is necessary for Firefox, but Chrome won't remove the CSS class without a little help. - $( '.row-actions' ).not( this ).removeClass( 'visible' ); - focusedRowActions.addClass( 'visible' ); - }, - focusout: function() { - // Tabbing between post title and .row-actions links needs a brief pause, otherwise - // the .row-actions div gets hidden in transit in some browsers (ahem, Firefox). - transitionTimeout = setTimeout( function() { - focusedRowActions.removeClass( 'visible' ); - }, 30 ); - } - }, '.has-row-actions' ); - - // Toggle list table rows on small screens - $( 'tbody' ).on( 'click', '.toggle-row', function() { - $( this ).closest( 'tr' ).toggleClass( 'is-expanded' ); - }); - - $('#default-password-nag-no').click( function() { - setUserSetting('default_password_nag', 'hide'); - $('div.default-password-nag').hide(); - return false; - }); - - /** - * Handles tab keypresses in theme and plugin editor textareas. - * - * @param {Event} e The event object. - * - * @returns {void} - */ - $('#newcontent').bind('keydown.wpevent_InsertTab', function(e) { - var el = e.target, selStart, selEnd, val, scroll, sel; - - // After pressing escape key (keyCode: 27), the tab key should tab out of the textarea. - if ( e.keyCode == 27 ) { - // when pressing Escape: Opera 12 and 27 blur form fields, IE 8 clears them - e.preventDefault(); - $(el).data('tab-out', true); - return; - } - - // Only listen for plain tab key (keyCode: 9) without any modifiers. - if ( e.keyCode != 9 || e.ctrlKey || e.altKey || e.shiftKey ) - return; - - // After tabbing out, reset it so next time the tab key can be used again. - if ( $(el).data('tab-out') ) { - $(el).data('tab-out', false); - return; - } - - selStart = el.selectionStart; - selEnd = el.selectionEnd; - val = el.value; - - // If any text is selected, replace the selection with a tab character. - if ( document.selection ) { - el.focus(); - sel = document.selection.createRange(); - sel.text = '\t'; - } else if ( selStart >= 0 ) { - scroll = this.scrollTop; - el.value = val.substring(0, selStart).concat('\t', val.substring(selEnd) ); - el.selectionStart = el.selectionEnd = selStart + 1; - this.scrollTop = scroll; - } - - // Cancel the regular tab functionality, to prevent losing focus of the textarea. - if ( e.stopPropagation ) - e.stopPropagation(); - if ( e.preventDefault ) - e.preventDefault(); - }); - - // Reset page number variable for new filters/searches but not for bulk actions. See #17685. - if ( pageInput.length ) { - - /** - * Handles pagination variable when filtering the list table. - * - * Set the pagination argument to the first page when the post-filter form is submitted. - * This happens when pressing the 'filter' button on the list table page. - * - * The pagination argument should not be touched when the bulk action dropdowns are set to do anything. - * - * The form closest to the pageInput is the post-filter form. - * - * @returns {void} - */ - pageInput.closest('form').submit( function() { - /* - * action = bulk action dropdown at the top of the table - * action2 = bulk action dropdow at the bottom of the table - */ - if ( $('select[name="action"]').val() == -1 && $('select[name="action2"]').val() == -1 && pageInput.val() == currentPage ) - pageInput.val('1'); - }); - } - - /** - * Resets the bulk actions when the search button is clicked. - * - * @returns {void} - */ - $('.search-box input[type="search"], .search-box input[type="submit"]').mousedown(function () { - $('select[name^="action"]').val('-1'); - }); - - /** - * Scrolls into view when focus.scroll-into-view is triggered. - * - * @param {Event} e The event object. - * - * @returns {void} - */ - $('#contextual-help-link, #show-settings-link').on( 'focus.scroll-into-view', function(e){ - if ( e.target.scrollIntoView ) - e.target.scrollIntoView(false); - }); - - /** - * Disables the submit upload buttons when no data is entered. - * - * @returns {void} - */ - (function(){ - var button, input, form = $('form.wp-upload-form'); - - // Exit when no upload form is found. - if ( ! form.length ) - return; - - button = form.find('input[type="submit"]'); - input = form.find('input[type="file"]'); - - /** - * Determines if any data is entered in any file upload input. - * - * @since 3.5.0 - * - * @returns {void} - */ - function toggleUploadButton() { - // When no inputs have a value, disable the upload buttons. - button.prop('disabled', '' === input.map( function() { - return $(this).val(); - }).get().join('')); - } - - // Update the status initially. - toggleUploadButton(); - // Update the status when any file input changes. - input.on('change', toggleUploadButton); - })(); - - /** - * Pins the menu while distraction-free writing is enabled. - * - * @param {Event} event Event data. - * - * @since 4.1.0 - * - * @returns {void} - */ - function pinMenu( event ) { - var windowPos = $window.scrollTop(), - resizing = ! event || event.type !== 'scroll'; - - if ( isIOS || isIE8 || $adminmenu.data( 'wp-responsive' ) ) { - return; - } - - /* - * When the menu is higher than the window and smaller than the entire page. - * It should be adjusted to be able to see the entire menu. - * - * Otherwise it can be accessed normally. - */ - if ( height.menu + height.adminbar < height.window || - height.menu + height.adminbar + 20 > height.wpwrap ) { - unpinMenu(); - return; - } - - menuIsPinned = true; - - // If the menu is higher than the window, compensate on scroll. - if ( height.menu + height.adminbar > height.window ) { - // Check for overscrolling, this happens when swiping up at the top of the document in modern browsers. - if ( windowPos < 0 ) { - // Stick the menu to the top. - if ( ! pinnedMenuTop ) { - pinnedMenuTop = true; - pinnedMenuBottom = false; - - $adminMenuWrap.css({ - position: 'fixed', - top: '', - bottom: '' - }); - } - - return; - } else if ( windowPos + height.window > $document.height() - 1 ) { - // When overscrolling at the bottom, stick the menu to the bottom. - if ( ! pinnedMenuBottom ) { - pinnedMenuBottom = true; - pinnedMenuTop = false; - - $adminMenuWrap.css({ - position: 'fixed', - top: '', - bottom: 0 - }); - } - - return; - } - - if ( windowPos > lastScrollPosition ) { - // When a down scroll has been detected. - - // If it was pinned to the top, unpin and calculate relative scroll. - if ( pinnedMenuTop ) { - pinnedMenuTop = false; - // Calculate new offset position. - menuTop = $adminMenuWrap.offset().top - height.adminbar - ( windowPos - lastScrollPosition ); - - if ( menuTop + height.menu + height.adminbar < windowPos + height.window ) { - menuTop = windowPos + height.window - height.menu - height.adminbar; - } - - $adminMenuWrap.css({ - position: 'absolute', - top: menuTop, - bottom: '' - }); - } else if ( ! pinnedMenuBottom && $adminMenuWrap.offset().top + height.menu < windowPos + height.window ) { - // Pin it to the bottom. - pinnedMenuBottom = true; - - $adminMenuWrap.css({ - position: 'fixed', - top: '', - bottom: 0 - }); - } - } else if ( windowPos < lastScrollPosition ) { - // When a scroll up is detected. - - // If it was pinned to the bottom, unpin and calculate relative scroll. - if ( pinnedMenuBottom ) { - pinnedMenuBottom = false; - - // Calculate new offset position. - menuTop = $adminMenuWrap.offset().top - height.adminbar + ( lastScrollPosition - windowPos ); - - if ( menuTop + height.menu > windowPos + height.window ) { - menuTop = windowPos; - } - - $adminMenuWrap.css({ - position: 'absolute', - top: menuTop, - bottom: '' - }); - } else if ( ! pinnedMenuTop && $adminMenuWrap.offset().top >= windowPos + height.adminbar ) { - - // Pin it to the top. - pinnedMenuTop = true; - - $adminMenuWrap.css({ - position: 'fixed', - top: '', - bottom: '' - }); - } - } else if ( resizing ) { - // Window is being resized. - - pinnedMenuTop = pinnedMenuBottom = false; - - // Calculate the new offset. - menuTop = windowPos + height.window - height.menu - height.adminbar - 1; - - if ( menuTop > 0 ) { - $adminMenuWrap.css({ - position: 'absolute', - top: menuTop, - bottom: '' - }); - } else { - unpinMenu(); - } - } - } - - lastScrollPosition = windowPos; - } - - /** - * Determines the height of certain elements. - * - * @since 4.1.0 - * - * @returns {void} - */ - function resetHeights() { - height = { - window: $window.height(), - wpwrap: $wpwrap.height(), - adminbar: $adminbar.height(), - menu: $adminMenuWrap.height() - }; - } - - /** - * Unpins the menu. - * - * @since 4.1.0 - * - * @returns {void} - */ - function unpinMenu() { - if ( isIOS || ! menuIsPinned ) { - return; - } - - pinnedMenuTop = pinnedMenuBottom = menuIsPinned = false; - $adminMenuWrap.css({ - position: '', - top: '', - bottom: '' - }); - } - - /** - * Pins and unpins the menu when applicable. - * - * @since 4.1.0 - * - * @returns {void} - */ - function setPinMenu() { - resetHeights(); - - if ( $adminmenu.data('wp-responsive') ) { - $body.removeClass( 'sticky-menu' ); - unpinMenu(); - } else if ( height.menu + height.adminbar > height.window ) { - pinMenu(); - $body.removeClass( 'sticky-menu' ); - } else { - $body.addClass( 'sticky-menu' ); - unpinMenu(); - } - } - - if ( ! isIOS ) { - $window.on( 'scroll.pin-menu', pinMenu ); - $document.on( 'tinymce-editor-init.pin-menu', function( event, editor ) { - editor.on( 'wp-autoresize', resetHeights ); - }); - } - - /** - * Changes the sortables and responsiveness of metaboxes. - * - * @since 3.8.0 - * - *@returns {void} - */ - window.wpResponsive = { - - /** - * Initializes the wpResponsive object. - * - * @since 3.8.0 - * - * @returns {void} - */ - init: function() { - var self = this; - - this.maybeDisableSortables = this.maybeDisableSortables.bind( this ); - - // Modify functionality based on custom activate/deactivate event - $document.on( 'wp-responsive-activate.wp-responsive', function() { - self.activate(); - }).on( 'wp-responsive-deactivate.wp-responsive', function() { - self.deactivate(); - }); - - $( '#wp-admin-bar-menu-toggle a' ).attr( 'aria-expanded', 'false' ); - - // Toggle sidebar when toggle is clicked. - $( '#wp-admin-bar-menu-toggle' ).on( 'click.wp-responsive', function( event ) { - event.preventDefault(); - - // close any open toolbar submenus. - $adminbar.find( '.hover' ).removeClass( 'hover' ); - - $wpwrap.toggleClass( 'wp-responsive-open' ); - if ( $wpwrap.hasClass( 'wp-responsive-open' ) ) { - $(this).find('a').attr( 'aria-expanded', 'true' ); - $( '#adminmenu a:first' ).focus(); - } else { - $(this).find('a').attr( 'aria-expanded', 'false' ); - } - } ); - - // Add menu events. - $adminmenu.on( 'click.wp-responsive', 'li.wp-has-submenu > a', function( event ) { - if ( ! $adminmenu.data('wp-responsive') ) { - return; - } - - $( this ).parent( 'li' ).toggleClass( 'selected' ); - event.preventDefault(); - }); - - self.trigger(); - $document.on( 'wp-window-resized.wp-responsive', $.proxy( this.trigger, this ) ); - - // This needs to run later as UI Sortable may be initialized later on $(document).ready(). - $window.on( 'load.wp-responsive', this.maybeDisableSortables ); - $document.on( 'postbox-toggled', this.maybeDisableSortables ); - - // When the screen columns are changed, potentially disable sortables. - $( '#screen-options-wrap input' ).on( 'click', this.maybeDisableSortables ); - }, - - /** - * Disable sortables if there is only one metabox, or the screen is in one column mode. Otherwise, enable sortables. - * - * @since 5.3.0 - * - * @returns {void} - */ - maybeDisableSortables: function() { - var width = navigator.userAgent.indexOf('AppleWebKit/') > -1 ? $window.width() : window.innerWidth; - - if ( - ( width <= 782 ) || - ( 1 >= $sortables.find( '.ui-sortable-handle:visible' ).length && jQuery( '.columns-prefs-1 input' ).prop( 'checked' ) ) - ) { - this.disableSortables(); - } else { - this.enableSortables(); - } - }, - - /** - * Changes properties of body and admin menu. - * - * Pins and unpins the menu and adds the auto-fold class to the body. - * Makes the admin menu responsive and disables the metabox sortables. - * - * @since 3.8.0 - * - * @returns {void} - */ - activate: function() { - setPinMenu(); - - if ( ! $body.hasClass( 'auto-fold' ) ) { - $body.addClass( 'auto-fold' ); - } - - $adminmenu.data( 'wp-responsive', 1 ); - this.disableSortables(); - }, - - /** - * Changes properties of admin menu and enables metabox sortables. - * - * Pin and unpin the menu. - * Removes the responsiveness of the admin menu and enables the metabox sortables. - * - * @since 3.8.0 - * - * @returns {void} - */ - deactivate: function() { - setPinMenu(); - $adminmenu.removeData('wp-responsive'); - - this.maybeDisableSortables(); - }, - - /** - * Sets the responsiveness and enables the overlay based on the viewport width. - * - * @since 3.8.0 - * - * @returns {void} - */ - trigger: function() { - var viewportWidth = getViewportWidth(); - - // Exclude IE < 9, it doesn't support @media CSS rules. - if ( ! viewportWidth ) { - return; - } - - if ( viewportWidth <= 782 ) { - if ( ! wpResponsiveActive ) { - $document.trigger( 'wp-responsive-activate' ); - wpResponsiveActive = true; - } - } else { - if ( wpResponsiveActive ) { - $document.trigger( 'wp-responsive-deactivate' ); - wpResponsiveActive = false; - } - } - - if ( viewportWidth <= 480 ) { - this.enableOverlay(); - } else { - this.disableOverlay(); - } - - this.maybeDisableSortables(); - }, - - /** - * Inserts a responsive overlay and toggles the window. - * - * @since 3.8.0 - * - * @returns {void} - */ - enableOverlay: function() { - if ( $overlay.length === 0 ) { - $overlay = $( '<div id="wp-responsive-overlay"></div>' ) - .insertAfter( '#wpcontent' ) - .hide() - .on( 'click.wp-responsive', function() { - $toolbar.find( '.menupop.hover' ).removeClass( 'hover' ); - $( this ).hide(); - }); - } - - $toolbarPopups.on( 'click.wp-responsive', function() { - $overlay.show(); - }); - }, - - /** - * Disables the responsive overlay and removes the overlay. - * - * @since 3.8.0 - * - * @returns {void} - */ - disableOverlay: function() { - $toolbarPopups.off( 'click.wp-responsive' ); - $overlay.hide(); - }, - - /** - * Disables sortables. - * - * @since 3.8.0 - * - * @returns {void} - */ - disableSortables: function() { - if ( $sortables.length ) { - try { - $sortables.sortable( 'disable' ); - $sortables.find( '.ui-sortable-handle' ).addClass( 'is-non-sortable' ); - } catch ( e ) {} - } - }, - - /** - * Enables sortables. - * - * @since 3.8.0 - * - * @returns {void} - */ - enableSortables: function() { - if ( $sortables.length ) { - try { - $sortables.sortable( 'enable' ); - $sortables.find( '.ui-sortable-handle' ).removeClass( 'is-non-sortable' ); - } catch ( e ) {} - } - } - }; - - /** - * Add an ARIA role `button` to elements that behave like UI controls when JavaScript is on. - * - * @since 4.5.0 - * - * @returns {void} - */ - function aria_button_if_js() { - $( '.aria-button-if-js' ).attr( 'role', 'button' ); - } - - $( document ).ajaxComplete( function() { - aria_button_if_js(); - }); - - /** - * Get the viewport width. - * - * @since 4.7.0 - * - * @returns {number|boolean} The current viewport width or false if the - * browser doesn't support innerWidth (IE < 9). - */ - function getViewportWidth() { - var viewportWidth = false; - - if ( window.innerWidth ) { - // On phones, window.innerWidth is affected by zooming. - viewportWidth = Math.max( window.innerWidth, document.documentElement.clientWidth ); - } - - return viewportWidth; - } - - /** - * Sets the admin menu collapsed/expanded state. - * - * Sets the global variable `menuState` and triggers a custom event passing - * the current menu state. - * - * @since 4.7.0 - * - * @returns {void} - */ - function setMenuState() { - var viewportWidth = getViewportWidth() || 961; - - if ( viewportWidth <= 782 ) { - menuState = 'responsive'; - } else if ( $body.hasClass( 'folded' ) || ( $body.hasClass( 'auto-fold' ) && viewportWidth <= 960 && viewportWidth > 782 ) ) { - menuState = 'folded'; - } else { - menuState = 'open'; - } - - $document.trigger( 'wp-menu-state-set', { state: menuState } ); - } - - // Set the menu state when the window gets resized. - $document.on( 'wp-window-resized.set-menu-state', setMenuState ); - - /** - * Sets ARIA attributes on the collapse/expand menu button. - * - * When the admin menu is open or folded, updates the `aria-expanded` and - * `aria-label` attributes of the button to give feedback to assistive - * technologies. In the responsive view, the button is always hidden. - * - * @since 4.7.0 - * - * @returns {void} - */ - $document.on( 'wp-menu-state-set wp-collapse-menu', function( event, eventData ) { - var $collapseButton = $( '#collapse-button' ), - ariaExpanded = 'true', - ariaLabelText = commonL10n.collapseMenu; - - if ( 'folded' === eventData.state ) { - ariaExpanded = 'false'; - ariaLabelText = commonL10n.expandMenu; - } - - $collapseButton.attr({ - 'aria-expanded': ariaExpanded, - 'aria-label': ariaLabelText - }); - }); - - window.wpResponsive.init(); - setPinMenu(); - setMenuState(); - currentMenuItemHasPopup(); - makeNoticesDismissible(); - aria_button_if_js(); - - $document.on( 'wp-pin-menu wp-window-resized.pin-menu postboxes-columnchange.pin-menu postbox-toggled.pin-menu wp-collapse-menu.pin-menu wp-scroll-start.pin-menu', setPinMenu ); - - // Set initial focus on a specific element. - $( '.wp-initial-focus' ).focus(); - - // Toggle update details on update-core.php. - $body.on( 'click', '.js-update-details-toggle', function() { - var $updateNotice = $( this ).closest( '.js-update-details' ), - $progressDiv = $( '#' + $updateNotice.data( 'update-details' ) ); - - /* - * When clicking on "Show details" move the progress div below the update - * notice. Make sure it gets moved just the first time. - */ - if ( ! $progressDiv.hasClass( 'update-details-moved' ) ) { - $progressDiv.insertAfter( $updateNotice ).addClass( 'update-details-moved' ); - } - - // Toggle the progress div visibility. - $progressDiv.toggle(); - // Toggle the Show Details button expanded state. - $( this ).attr( 'aria-expanded', $progressDiv.is( ':visible' ) ); - }); -}); - -// Fire a custom jQuery event at the end of window resize. -( function() { - var timeout; - - /** - * Triggers the WP window-resize event. - * - * @since 3.8.0 - * - * @returns {void} - */ - function triggerEvent() { - $document.trigger( 'wp-window-resized' ); - } - - /** - * Fires the trigger event again after 200 ms. - * - * @since 3.8.0 - * - * @returns {void} - */ - function fireOnce() { - window.clearTimeout( timeout ); - timeout = window.setTimeout( triggerEvent, 200 ); - } - - $window.on( 'resize.wp-fire-once', fireOnce ); -}()); - -// Make Windows 8 devices play along nicely. -(function(){ - if ( '-ms-user-select' in document.documentElement.style && navigator.userAgent.match(/IEMobile\/10\.0/) ) { - var msViewportStyle = document.createElement( 'style' ); - msViewportStyle.appendChild( - document.createTextNode( '@-ms-viewport{width:auto!important}' ) - ); - document.getElementsByTagName( 'head' )[0].appendChild( msViewportStyle ); - } -})(); - -}( jQuery, window )); diff --git a/srcs/wordpress/wp-admin/js/common.min.js b/srcs/wordpress/wp-admin/js/common.min.js deleted file mode 100644 index 36fec71..0000000 --- a/srcs/wordpress/wp-admin/js/common.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(V,q){var B=V(document),H=V(q),G=V(document.body);q.adminMenu={init:function(){},fold:function(){},restoreMenuState:function(){},toggle:function(){},favorites:function(){}},q.columns={init:function(){var n=this;V(".hide-column-tog","#adv-settings").click(function(){var e=V(this),t=e.val();e.prop("checked")?n.checked(t):n.unchecked(t),columns.saveManageColumnsState()})},saveManageColumnsState:function(){var e=this.hidden();V.post(ajaxurl,{action:"hidden-columns",hidden:e,screenoptionnonce:V("#screenoptionnonce").val(),page:pagenow})},checked:function(e){V(".column-"+e).removeClass("hidden"),this.colSpanChange(1)},unchecked:function(e){V(".column-"+e).addClass("hidden"),this.colSpanChange(-1)},hidden:function(){return V(".manage-column[id]").filter(".hidden").map(function(){return this.id}).get().join(",")},useCheckboxesForHidden:function(){this.hidden=function(){return V(".hide-column-tog").not(":checked").map(function(){var e=this.id;return e.substring(e,e.length-5)}).get().join(",")}},colSpanChange:function(e){var t,n=V("table").find(".colspanchange");n.length&&(t=parseInt(n.attr("colspan"),10)+e,n.attr("colspan",t.toString()))}},B.ready(function(){columns.init()}),q.validateForm=function(e){return!V(e).find(".form-required").filter(function(){return""===V(":input:visible",this).val()}).addClass("form-invalid").find(":input:visible").change(function(){V(this).closest(".form-invalid").removeClass("form-invalid")}).length},q.showNotice={warn:function(){var e=commonL10n.warnDelete||"";return!!confirm(e)},note:function(e){alert(e)}},q.screenMeta={element:null,toggles:null,page:null,init:function(){this.element=V("#screen-meta"),this.toggles=V("#screen-meta-links").find(".show-settings"),this.page=V("#wpcontent"),this.toggles.click(this.toggleEvent)},toggleEvent:function(){var e=V("#"+V(this).attr("aria-controls"));e.length&&(e.is(":visible")?screenMeta.close(e,V(this)):screenMeta.open(e,V(this)))},open:function(e,t){V("#screen-meta-links").find(".screen-meta-toggle").not(t.parent()).css("visibility","hidden"),e.parent().show(),e.slideDown("fast",function(){e.focus(),t.addClass("screen-meta-active").attr("aria-expanded",!0)}),B.trigger("screen:options:open")},close:function(e,t){e.slideUp("fast",function(){t.removeClass("screen-meta-active").attr("aria-expanded",!1),V(".screen-meta-toggle").css("visibility",""),e.parent().hide()}),B.trigger("screen:options:close")}},V(".contextual-help-tabs").delegate("a","click",function(e){var t,n=V(this);if(e.preventDefault(),n.is(".active a"))return!1;V(".contextual-help-tabs .active").removeClass("active"),n.parent("li").addClass("active"),t=V(n.attr("href")),V(".help-tab-content").not(t).removeClass("active").hide(),t.addClass("active").show()});var e,a=!1,r=V("#permalink_structure"),t=V(".permalink-structure input:radio"),l=V("#custom_selection"),n=V(".form-table.permalink-structure .available-structure-tags button");function c(e){-1!==r.val().indexOf(e.text().trim())?(e.attr("data-label",e.attr("aria-label")),e.attr("aria-label",e.attr("data-used")),e.attr("aria-pressed",!0),e.addClass("active")):e.attr("data-label")&&(e.attr("aria-label",e.attr("data-label")),e.attr("aria-pressed",!1),e.removeClass("active"))}function i(){B.trigger("wp-window-resized")}t.on("change",function(){"custom"!==this.value&&(r.val(this.value),n.each(function(){c(V(this))}))}),r.on("click input",function(){l.prop("checked",!0)}),r.on("focus",function(e){a=!0,V(this).off(e)}),n.each(function(){c(V(this))}),r.on("change",function(){n.each(function(){c(V(this))})}),n.on("click",function(){var e,t=r.val(),n=r[0].selectionStart,i=r[0].selectionEnd,o=V(this).text().trim(),s=V(this).attr("data-added");if(-1!==t.indexOf(o))return t=t.replace(o+"/",""),r.val("/"===t?"":t),V("#custom_selection_updated").text(s),void c(V(this));a||0!==n||0!==i||(n=i=t.length),l.prop("checked",!0),"/"!==t.substr(0,n).substr(-1)&&(o="/"+o),"/"!==t.substr(i,1)&&(o+="/"),r.val(t.substr(0,n)+o+t.substr(i)),V("#custom_selection_updated").text(s),c(V(this)),a&&r[0].setSelectionRange&&(e=(t.substr(0,n)+o).length,r[0].setSelectionRange(e,e),r.focus())}),B.ready(function(){var n,i,o,s,e,t,a,r,l,c,d,u=!1,p=V("input.current-page"),f=p.val(),h=/iPhone|iPad|iPod/.test(navigator.userAgent),m=-1!==navigator.userAgent.indexOf("Android"),v=V(document.documentElement).hasClass("ie8"),b=V("#adminmenuwrap"),g=V("#wpwrap"),w=V("#adminmenu"),k=V("#wp-responsive-overlay"),C=V("#wp-toolbar"),x=C.find('a[aria-haspopup="true"]'),y=V(".meta-box-sortables"),S=!1,D=V("#wpadminbar"),M=0,E=!1,T=!1,j=0,A=!1,_={window:H.height(),wpwrap:g.height(),adminbar:D.height(),menu:b.height()},I=V(".wp-header-end");function O(){var e=V("a.wp-has-current-submenu");"folded"===r?e.attr("aria-haspopup","true"):e.attr("aria-haspopup","false")}function U(e){var t,n,i,o,s,a,r=e.find(".wp-submenu");a=(o=e.offset().top)-(s=H.scrollTop())-30,n=60+(t=o+r.height()+1)-g.height(),(i=H.height()+s-50)<t-n&&(n=t-i),a<n&&(n=a),1<n?r.css("margin-top","-"+n+"px"):r.css("margin-top","")}function K(){V(".notice.is-dismissible").each(function(){var t=V(this),e=V('<button type="button" class="notice-dismiss"><span class="screen-reader-text"></span></button>'),n=commonL10n.dismiss||"";e.find(".screen-reader-text").text(n),e.on("click.wp-dismiss-notice",function(e){e.preventDefault(),t.fadeTo(100,0,function(){t.slideUp(100,function(){t.remove()})})}),t.append(e)})}function z(){l.prop("disabled",""===c.map(function(){return V(this).val()}).get().join(""))}function N(e){var t=H.scrollTop(),n=!e||"scroll"!==e.type;if(!(h||v||w.data("wp-responsive")))if(_.menu+_.adminbar<_.window||_.menu+_.adminbar+20>_.wpwrap)R();else{if(A=!0,_.menu+_.adminbar>_.window){if(t<0)return void(E||(T=!(E=!0),b.css({position:"fixed",top:"",bottom:""})));if(t+_.window>B.height()-1)return void(T||(E=!(T=!0),b.css({position:"fixed",top:"",bottom:0})));M<t?E?(E=!1,(j=b.offset().top-_.adminbar-(t-M))+_.menu+_.adminbar<t+_.window&&(j=t+_.window-_.menu-_.adminbar),b.css({position:"absolute",top:j,bottom:""})):!T&&b.offset().top+_.menu<t+_.window&&(T=!0,b.css({position:"fixed",top:"",bottom:0})):t<M?T?(T=!1,(j=b.offset().top-_.adminbar+(M-t))+_.menu>t+_.window&&(j=t),b.css({position:"absolute",top:j,bottom:""})):!E&&b.offset().top>=t+_.adminbar&&(E=!0,b.css({position:"fixed",top:"",bottom:""})):n&&(E=T=!1,0<(j=t+_.window-_.menu-_.adminbar-1)?b.css({position:"absolute",top:j,bottom:""}):R())}M=t}}function P(){_={window:H.height(),wpwrap:g.height(),adminbar:D.height(),menu:b.height()}}function R(){!h&&A&&(E=T=A=!1,b.css({position:"",top:"",bottom:""}))}function W(){P(),w.data("wp-responsive")?(G.removeClass("sticky-menu"),R()):_.menu+_.adminbar>_.window?(N(),G.removeClass("sticky-menu")):(G.addClass("sticky-menu"),R())}function L(){V(".aria-button-if-js").attr("role","button")}function F(){var e=!1;return q.innerWidth&&(e=Math.max(q.innerWidth,document.documentElement.clientWidth)),e}function Q(){var e=F()||961;r=e<=782?"responsive":G.hasClass("folded")||G.hasClass("auto-fold")&&e<=960&&782<e?"folded":"open",B.trigger("wp-menu-state-set",{state:r})}w.on("click.wp-submenu-head",".wp-submenu-head",function(e){V(e.target).parent().siblings("a").get(0).click()}),V("#collapse-button").on("click.collapse-menu",function(){var e=F()||961;V("#adminmenu div.wp-submenu").css("margin-top",""),r=e<960?G.hasClass("auto-fold")?(G.removeClass("auto-fold").removeClass("folded"),setUserSetting("unfold",1),setUserSetting("mfold","o"),"open"):(G.addClass("auto-fold"),setUserSetting("unfold",0),"folded"):G.hasClass("folded")?(G.removeClass("folded"),setUserSetting("mfold","o"),"open"):(G.addClass("folded"),setUserSetting("mfold","f"),"folded"),B.trigger("wp-collapse-menu",{state:r})}),B.on("wp-menu-state-set wp-collapse-menu wp-responsive-activate wp-responsive-deactivate",O),("ontouchstart"in q||/IEMobile\/[1-9]/.test(navigator.userAgent))&&(e=h?"touchstart":"click",G.on(e+".wp-mobile-hover",function(e){w.data("wp-responsive")||V(e.target).closest("#adminmenu").length||w.find("li.opensub").removeClass("opensub")}),w.find("a.wp-has-submenu").on(e+".wp-mobile-hover",function(e){var t=V(this).parent();w.data("wp-responsive")||t.hasClass("opensub")||t.hasClass("wp-menu-open")&&!(t.width()<40)||(e.preventDefault(),U(t),w.find("li.opensub").removeClass("opensub"),t.addClass("opensub"))})),h||m||(w.find("li.wp-has-submenu").hoverIntent({over:function(){var e=V(this),t=e.find(".wp-submenu"),n=parseInt(t.css("top"),10);isNaN(n)||-5<n||w.data("wp-responsive")||(U(e),w.find("li.opensub").removeClass("opensub"),e.addClass("opensub"))},out:function(){w.data("wp-responsive")||V(this).removeClass("opensub").find(".wp-submenu").css("margin-top","")},timeout:200,sensitivity:7,interval:90}),w.on("focus.adminmenu",".wp-submenu a",function(e){w.data("wp-responsive")||V(e.target).closest("li.menu-top").addClass("opensub")}).on("blur.adminmenu",".wp-submenu a",function(e){w.data("wp-responsive")||V(e.target).closest("li.menu-top").removeClass("opensub")}).find("li.wp-has-submenu.wp-not-current-submenu").on("focusin.adminmenu",function(){U(V(this))})),I.length||(I=V(".wrap h1, .wrap h2").first()),V("div.updated, div.error, div.notice").not(".inline, .below-h2").insertAfter(I),B.on("wp-updates-notice-added wp-plugin-install-error wp-plugin-update-error wp-plugin-delete-error wp-theme-install-error wp-theme-delete-error",K),screenMeta.init(),G.on("click","tbody > tr > .check-column :checkbox",function(e){if("undefined"==e.shiftKey)return!0;if(e.shiftKey){if(!u)return!0;n=V(u).closest("form").find(":checkbox").filter(":visible:enabled"),i=n.index(u),o=n.index(this),s=V(this).prop("checked"),0<i&&0<o&&i!=o&&(i<o?n.slice(i,o):n.slice(o,i)).prop("checked",function(){return!!V(this).closest("tr").is(":visible")&&s})}var t=V(u=this).closest("tbody").find(":checkbox").filter(":visible:enabled").not(":checked");return V(this).closest("table").children("thead, tfoot").find(":checkbox").prop("checked",function(){return 0===t.length}),!0}),G.on("click.wp-toggle-checkboxes","thead .check-column :checkbox, tfoot .check-column :checkbox",function(e){var t=V(this),n=t.closest("table"),i=t.prop("checked"),o=e.shiftKey||t.data("wp-toggle");n.children("tbody").filter(":visible").children().children(".check-column").find(":checkbox").prop("checked",function(){return!V(this).is(":hidden,:disabled")&&(o?!V(this).prop("checked"):!!i)}),n.children("thead, tfoot").filter(":visible").children().children(".check-column").find(":checkbox").prop("checked",function(){return!o&&!!i})}),V("#wpbody-content").on({focusin:function(){clearTimeout(t),a=V(this).find(".row-actions"),V(".row-actions").not(this).removeClass("visible"),a.addClass("visible")},focusout:function(){t=setTimeout(function(){a.removeClass("visible")},30)}},".has-row-actions"),V("tbody").on("click",".toggle-row",function(){V(this).closest("tr").toggleClass("is-expanded")}),V("#default-password-nag-no").click(function(){return setUserSetting("default_password_nag","hide"),V("div.default-password-nag").hide(),!1}),V("#newcontent").bind("keydown.wpevent_InsertTab",function(e){var t,n,i,o,s=e.target;if(27==e.keyCode)return e.preventDefault(),void V(s).data("tab-out",!0);9!=e.keyCode||e.ctrlKey||e.altKey||e.shiftKey||(V(s).data("tab-out")?V(s).data("tab-out",!1):(t=s.selectionStart,n=s.selectionEnd,i=s.value,document.selection?(s.focus(),document.selection.createRange().text="\t"):0<=t&&(o=this.scrollTop,s.value=i.substring(0,t).concat("\t",i.substring(n)),s.selectionStart=s.selectionEnd=t+1,this.scrollTop=o),e.stopPropagation&&e.stopPropagation(),e.preventDefault&&e.preventDefault()))}),p.length&&p.closest("form").submit(function(){-1==V('select[name="action"]').val()&&-1==V('select[name="action2"]').val()&&p.val()==f&&p.val("1")}),V('.search-box input[type="search"], .search-box input[type="submit"]').mousedown(function(){V('select[name^="action"]').val("-1")}),V("#contextual-help-link, #show-settings-link").on("focus.scroll-into-view",function(e){e.target.scrollIntoView&&e.target.scrollIntoView(!1)}),(d=V("form.wp-upload-form")).length&&(l=d.find('input[type="submit"]'),c=d.find('input[type="file"]'),z(),c.on("change",z)),h||(H.on("scroll.pin-menu",N),B.on("tinymce-editor-init.pin-menu",function(e,t){t.on("wp-autoresize",P)})),q.wpResponsive={init:function(){var e=this;this.maybeDisableSortables=this.maybeDisableSortables.bind(this),B.on("wp-responsive-activate.wp-responsive",function(){e.activate()}).on("wp-responsive-deactivate.wp-responsive",function(){e.deactivate()}),V("#wp-admin-bar-menu-toggle a").attr("aria-expanded","false"),V("#wp-admin-bar-menu-toggle").on("click.wp-responsive",function(e){e.preventDefault(),D.find(".hover").removeClass("hover"),g.toggleClass("wp-responsive-open"),g.hasClass("wp-responsive-open")?(V(this).find("a").attr("aria-expanded","true"),V("#adminmenu a:first").focus()):V(this).find("a").attr("aria-expanded","false")}),w.on("click.wp-responsive","li.wp-has-submenu > a",function(e){w.data("wp-responsive")&&(V(this).parent("li").toggleClass("selected"),e.preventDefault())}),e.trigger(),B.on("wp-window-resized.wp-responsive",V.proxy(this.trigger,this)),H.on("load.wp-responsive",this.maybeDisableSortables),B.on("postbox-toggled",this.maybeDisableSortables),V("#screen-options-wrap input").on("click",this.maybeDisableSortables)},maybeDisableSortables:function(){(-1<navigator.userAgent.indexOf("AppleWebKit/")?H.width():q.innerWidth)<=782||y.find(".ui-sortable-handle:visible").length<=1&&jQuery(".columns-prefs-1 input").prop("checked")?this.disableSortables():this.enableSortables()},activate:function(){W(),G.hasClass("auto-fold")||G.addClass("auto-fold"),w.data("wp-responsive",1),this.disableSortables()},deactivate:function(){W(),w.removeData("wp-responsive"),this.maybeDisableSortables()},trigger:function(){var e=F();e&&(e<=782?S||(B.trigger("wp-responsive-activate"),S=!0):S&&(B.trigger("wp-responsive-deactivate"),S=!1),e<=480?this.enableOverlay():this.disableOverlay(),this.maybeDisableSortables())},enableOverlay:function(){0===k.length&&(k=V('<div id="wp-responsive-overlay"></div>').insertAfter("#wpcontent").hide().on("click.wp-responsive",function(){C.find(".menupop.hover").removeClass("hover"),V(this).hide()})),x.on("click.wp-responsive",function(){k.show()})},disableOverlay:function(){x.off("click.wp-responsive"),k.hide()},disableSortables:function(){if(y.length)try{y.sortable("disable"),y.find(".ui-sortable-handle").addClass("is-non-sortable")}catch(e){}},enableSortables:function(){if(y.length)try{y.sortable("enable"),y.find(".ui-sortable-handle").removeClass("is-non-sortable")}catch(e){}}},V(document).ajaxComplete(function(){L()}),B.on("wp-window-resized.set-menu-state",Q),B.on("wp-menu-state-set wp-collapse-menu",function(e,t){var n=V("#collapse-button"),i="true",o=commonL10n.collapseMenu;"folded"===t.state&&(i="false",o=commonL10n.expandMenu),n.attr({"aria-expanded":i,"aria-label":o})}),q.wpResponsive.init(),W(),Q(),O(),K(),L(),B.on("wp-pin-menu wp-window-resized.pin-menu postboxes-columnchange.pin-menu postbox-toggled.pin-menu wp-collapse-menu.pin-menu wp-scroll-start.pin-menu",W),V(".wp-initial-focus").focus(),G.on("click",".js-update-details-toggle",function(){var e=V(this).closest(".js-update-details"),t=V("#"+e.data("update-details"));t.hasClass("update-details-moved")||t.insertAfter(e).addClass("update-details-moved"),t.toggle(),V(this).attr("aria-expanded",t.is(":visible"))})}),H.on("resize.wp-fire-once",function(){q.clearTimeout(e),e=q.setTimeout(i,200)}),function(){if("-ms-user-select"in document.documentElement.style&&navigator.userAgent.match(/IEMobile\/10\.0/)){var e=document.createElement("style");e.appendChild(document.createTextNode("@-ms-viewport{width:auto!important}")),document.getElementsByTagName("head")[0].appendChild(e)}}()}(jQuery,window);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/custom-background.js b/srcs/wordpress/wp-admin/js/custom-background.js deleted file mode 100644 index a948e78..0000000 --- a/srcs/wordpress/wp-admin/js/custom-background.js +++ /dev/null @@ -1,145 +0,0 @@ -/** - * @output wp-admin/js/custom-background.js - */ - -/* global ajaxurl */ - -/** - * Registers all events for customizing the background. - * - * @since 3.0.0 - * - * @requires jQuery - */ -(function($) { - $(document).ready(function() { - var frame, - bgImage = $( '#custom-background-image' ); - - /** - * Instantiates the WordPress color picker and binds the change and clear events. - * - * @since 3.5.0 - * - * @returns {void} - */ - $('#background-color').wpColorPicker({ - change: function( event, ui ) { - bgImage.css('background-color', ui.color.toString()); - }, - clear: function() { - bgImage.css('background-color', ''); - } - }); - - /** - * Alters the background size CSS property whenever the background size input has changed. - * - * @since 4.7.0 - * - * @returns {void} - */ - $( 'select[name="background-size"]' ).change( function() { - bgImage.css( 'background-size', $( this ).val() ); - }); - - /** - * Alters the background position CSS property whenever the background position input has changed. - * - * @since 4.7.0 - * - * @returns {void} - */ - $( 'input[name="background-position"]' ).change( function() { - bgImage.css( 'background-position', $( this ).val() ); - }); - - /** - * Alters the background repeat CSS property whenever the background repeat input has changed. - * - * @since 3.0.0 - * - * @returns {void} - */ - $( 'input[name="background-repeat"]' ).change( function() { - bgImage.css( 'background-repeat', $( this ).is( ':checked' ) ? 'repeat' : 'no-repeat' ); - }); - - /** - * Alters the background attachment CSS property whenever the background attachment input has changed. - * - * @since 4.7.0 - * - * @returns {void} - */ - $( 'input[name="background-attachment"]' ).change( function() { - bgImage.css( 'background-attachment', $( this ).is( ':checked' ) ? 'scroll' : 'fixed' ); - }); - - /** - * Binds the event for opening the WP Media dialog. - * - * @since 3.5.0 - * - * @returns {void} - */ - $('#choose-from-library-link').click( function( event ) { - var $el = $(this); - - event.preventDefault(); - - // If the media frame already exists, reopen it. - if ( frame ) { - frame.open(); - return; - } - - // Create the media frame. - frame = wp.media.frames.customBackground = wp.media({ - // Set the title of the modal. - title: $el.data('choose'), - - // Tell the modal to show only images. - library: { - type: 'image' - }, - - // Customize the submit button. - button: { - // Set the text of the button. - text: $el.data('update'), - /* - * Tell the button not to close the modal, since we're - * going to refresh the page when the image is selected. - */ - close: false - } - }); - - /** - * When an image is selected, run a callback. - * - * @since 3.5.0 - * - * @returns {void} - */ - frame.on( 'select', function() { - // Grab the selected attachment. - var attachment = frame.state().get('selection').first(); - - // Run an AJAX request to set the background image. - $.post( ajaxurl, { - action: 'set-background-image', - attachment_id: attachment.id, - size: 'full' - }).done( function() { - // When the request completes, reload the window. - window.location.reload(); - }); - }); - - // Finally, open the modal. - frame.open(); - }); - }); -})(jQuery); diff --git a/srcs/wordpress/wp-admin/js/custom-background.min.js b/srcs/wordpress/wp-admin/js/custom-background.min.js deleted file mode 100644 index 377bf45..0000000 --- a/srcs/wordpress/wp-admin/js/custom-background.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(e){e(document).ready(function(){var o,t=e("#custom-background-image");e("#background-color").wpColorPicker({change:function(n,c){t.css("background-color",c.color.toString())},clear:function(){t.css("background-color","")}}),e('select[name="background-size"]').change(function(){t.css("background-size",e(this).val())}),e('input[name="background-position"]').change(function(){t.css("background-position",e(this).val())}),e('input[name="background-repeat"]').change(function(){t.css("background-repeat",e(this).is(":checked")?"repeat":"no-repeat")}),e('input[name="background-attachment"]').change(function(){t.css("background-attachment",e(this).is(":checked")?"scroll":"fixed")}),e("#choose-from-library-link").click(function(n){var c=e(this);n.preventDefault(),o||(o=wp.media.frames.customBackground=wp.media({title:c.data("choose"),library:{type:"image"},button:{text:c.data("update"),close:!1}})).on("select",function(){var n=o.state().get("selection").first();e.post(ajaxurl,{action:"set-background-image",attachment_id:n.id,size:"full"}).done(function(){window.location.reload()})}),o.open()})})}(jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/custom-header.js b/srcs/wordpress/wp-admin/js/custom-header.js deleted file mode 100644 index e00c70c..0000000 --- a/srcs/wordpress/wp-admin/js/custom-header.js +++ /dev/null @@ -1,88 +0,0 @@ -/** - * @output wp-admin/js/custom-header.js - */ - -/* global isRtl */ - -/** - * Initializes the custom header selection page. - * - * @since 3.5.0 - * - * @deprecated 4.1.0 The page this is used on is never linked to from the UI. - * Setting a custom header is completely handled by the Customizer. - */ -(function($) { - var frame; - - $( function() { - // Fetch available headers. - var $headers = $('.available-headers'); - - // Apply jQuery.masonry once the images have loaded. - $headers.imagesLoaded( function() { - $headers.masonry({ - itemSelector: '.default-header', - isRTL: !! ( 'undefined' != typeof isRtl && isRtl ) - }); - }); - - /** - * Opens the 'choose from library' frame and creates it if it doesn't exist. - * - * @since 3.5.0 - * @deprecated 4.1.0 - * - * @returns {void} - */ - $('#choose-from-library-link').click( function( event ) { - var $el = $(this); - event.preventDefault(); - - // If the media frame already exists, reopen it. - if ( frame ) { - frame.open(); - return; - } - - // Create the media frame. - frame = wp.media.frames.customHeader = wp.media({ - // Set the title of the modal. - title: $el.data('choose'), - - // Tell the modal to show only images. - library: { - type: 'image' - }, - - // Customize the submit button. - button: { - // Set the text of the button. - text: $el.data('update'), - // Tell the button not to close the modal, since we're - // going to refresh the page when the image is selected. - close: false - } - }); - - /** - * Updates the window location to include the selected attachment. - * - * @since 3.5.0 - * @deprecated 4.1.0 - * - * @returns {void} - */ - frame.on( 'select', function() { - // Grab the selected attachment. - var attachment = frame.state().get('selection').first(), - link = $el.data('updateLink'); - - // Tell the browser to navigate to the crop step. - window.location = link + '&file=' + attachment.id; - }); - - frame.open(); - }); - }); -}(jQuery)); diff --git a/srcs/wordpress/wp-admin/js/customize-controls.js b/srcs/wordpress/wp-admin/js/customize-controls.js deleted file mode 100644 index 2edc498..0000000 --- a/srcs/wordpress/wp-admin/js/customize-controls.js +++ /dev/null @@ -1,9270 +0,0 @@ -/** - * @output wp-admin/js/customize-controls.js - */ - -/* global _wpCustomizeHeader, _wpCustomizeBackground, _wpMediaViewsL10n, MediaElementPlayer, console, confirm */ -(function( exports, $ ){ - var Container, focus, normalizedTransitionendEventName, api = wp.customize; - - api.OverlayNotification = api.Notification.extend(/** @lends wp.customize.OverlayNotification.prototype */{ - - /** - * Whether the notification should show a loading spinner. - * - * @since 4.9.0 - * @var {boolean} - */ - loading: false, - - /** - * A notification that is displayed in a full-screen overlay. - * - * @constructs wp.customize.OverlayNotification - * @augments wp.customize.Notification - * - * @since 4.9.0 - * - * @param {string} code - Code. - * @param {object} params - Params. - */ - initialize: function( code, params ) { - var notification = this; - api.Notification.prototype.initialize.call( notification, code, params ); - notification.containerClasses += ' notification-overlay'; - if ( notification.loading ) { - notification.containerClasses += ' notification-loading'; - } - }, - - /** - * Render notification. - * - * @since 4.9.0 - * - * @return {jQuery} Notification container. - */ - render: function() { - var li = api.Notification.prototype.render.call( this ); - li.on( 'keydown', _.bind( this.handleEscape, this ) ); - return li; - }, - - /** - * Stop propagation on escape key presses, but also dismiss notification if it is dismissible. - * - * @since 4.9.0 - * - * @param {jQuery.Event} event - Event. - * @returns {void} - */ - handleEscape: function( event ) { - var notification = this; - if ( 27 === event.which ) { - event.stopPropagation(); - if ( notification.dismissible && notification.parent ) { - notification.parent.remove( notification.code ); - } - } - } - }); - - api.Notifications = api.Values.extend(/** @lends wp.customize.Notifications.prototype */{ - - /** - * Whether the alternative style should be used. - * - * @since 4.9.0 - * @type {boolean} - */ - alt: false, - - /** - * The default constructor for items of the collection. - * - * @since 4.9.0 - * @type {object} - */ - defaultConstructor: api.Notification, - - /** - * A collection of observable notifications. - * - * @since 4.9.0 - * - * @constructs wp.customize.Notifications - * @augments wp.customize.Values - * - * @param {object} options - Options. - * @param {jQuery} [options.container] - Container element for notifications. This can be injected later. - * @param {boolean} [options.alt] - Whether alternative style should be used when rendering notifications. - * - * @returns {void} - */ - initialize: function( options ) { - var collection = this; - - api.Values.prototype.initialize.call( collection, options ); - - _.bindAll( collection, 'constrainFocus' ); - - // Keep track of the order in which the notifications were added for sorting purposes. - collection._addedIncrement = 0; - collection._addedOrder = {}; - - // Trigger change event when notification is added or removed. - collection.bind( 'add', function( notification ) { - collection.trigger( 'change', notification ); - }); - collection.bind( 'removed', function( notification ) { - collection.trigger( 'change', notification ); - }); - }, - - /** - * Get the number of notifications added. - * - * @since 4.9.0 - * @return {number} Count of notifications. - */ - count: function() { - return _.size( this._value ); - }, - - /** - * Add notification to the collection. - * - * @since 4.9.0 - * - * @param {string|wp.customize.Notification} notification - Notification object to add. Alternatively code may be supplied, and in that case the second notificationObject argument must be supplied. - * @param {wp.customize.Notification} [notificationObject] - Notification to add when first argument is the code string. - * @returns {wp.customize.Notification} Added notification (or existing instance if it was already added). - */ - add: function( notification, notificationObject ) { - var collection = this, code, instance; - if ( 'string' === typeof notification ) { - code = notification; - instance = notificationObject; - } else { - code = notification.code; - instance = notification; - } - if ( ! collection.has( code ) ) { - collection._addedIncrement += 1; - collection._addedOrder[ code ] = collection._addedIncrement; - } - return api.Values.prototype.add.call( collection, code, instance ); - }, - - /** - * Add notification to the collection. - * - * @since 4.9.0 - * @param {string} code - Notification code to remove. - * @return {api.Notification} Added instance (or existing instance if it was already added). - */ - remove: function( code ) { - var collection = this; - delete collection._addedOrder[ code ]; - return api.Values.prototype.remove.call( this, code ); - }, - - /** - * Get list of notifications. - * - * Notifications may be sorted by type followed by added time. - * - * @since 4.9.0 - * @param {object} args - Args. - * @param {boolean} [args.sort=false] - Whether to return the notifications sorted. - * @return {Array.<wp.customize.Notification>} Notifications. - */ - get: function( args ) { - var collection = this, notifications, errorTypePriorities, params; - notifications = _.values( collection._value ); - - params = _.extend( - { sort: false }, - args - ); - - if ( params.sort ) { - errorTypePriorities = { error: 4, warning: 3, success: 2, info: 1 }; - notifications.sort( function( a, b ) { - var aPriority = 0, bPriority = 0; - if ( ! _.isUndefined( errorTypePriorities[ a.type ] ) ) { - aPriority = errorTypePriorities[ a.type ]; - } - if ( ! _.isUndefined( errorTypePriorities[ b.type ] ) ) { - bPriority = errorTypePriorities[ b.type ]; - } - if ( aPriority !== bPriority ) { - return bPriority - aPriority; // Show errors first. - } - return collection._addedOrder[ b.code ] - collection._addedOrder[ a.code ]; // Show newer notifications higher. - }); - } - - return notifications; - }, - - /** - * Render notifications area. - * - * @since 4.9.0 - * @returns {void} - */ - render: function() { - var collection = this, - notifications, hadOverlayNotification = false, hasOverlayNotification, overlayNotifications = [], - previousNotificationsByCode = {}, - listElement, focusableElements; - - // Short-circuit if there are no container to render into. - if ( ! collection.container || ! collection.container.length ) { - return; - } - - notifications = collection.get( { sort: true } ); - collection.container.toggle( 0 !== notifications.length ); - - // Short-circuit if there are no changes to the notifications. - if ( collection.container.is( collection.previousContainer ) && _.isEqual( notifications, collection.previousNotifications ) ) { - return; - } - - // Make sure list is part of the container. - listElement = collection.container.children( 'ul' ).first(); - if ( ! listElement.length ) { - listElement = $( '<ul></ul>' ); - collection.container.append( listElement ); - } - - // Remove all notifications prior to re-rendering. - listElement.find( '> [data-code]' ).remove(); - - _.each( collection.previousNotifications, function( notification ) { - previousNotificationsByCode[ notification.code ] = notification; - }); - - // Add all notifications in the sorted order. - _.each( notifications, function( notification ) { - var notificationContainer; - if ( wp.a11y && ( ! previousNotificationsByCode[ notification.code ] || ! _.isEqual( notification.message, previousNotificationsByCode[ notification.code ].message ) ) ) { - wp.a11y.speak( notification.message, 'assertive' ); - } - notificationContainer = $( notification.render() ); - notification.container = notificationContainer; - listElement.append( notificationContainer ); // @todo Consider slideDown() as enhancement. - - if ( notification.extended( api.OverlayNotification ) ) { - overlayNotifications.push( notification ); - } - }); - hasOverlayNotification = Boolean( overlayNotifications.length ); - - if ( collection.previousNotifications ) { - hadOverlayNotification = Boolean( _.find( collection.previousNotifications, function( notification ) { - return notification.extended( api.OverlayNotification ); - } ) ); - } - - if ( hasOverlayNotification !== hadOverlayNotification ) { - $( document.body ).toggleClass( 'customize-loading', hasOverlayNotification ); - collection.container.toggleClass( 'has-overlay-notifications', hasOverlayNotification ); - if ( hasOverlayNotification ) { - collection.previousActiveElement = document.activeElement; - $( document ).on( 'keydown', collection.constrainFocus ); - } else { - $( document ).off( 'keydown', collection.constrainFocus ); - } - } - - if ( hasOverlayNotification ) { - collection.focusContainer = overlayNotifications[ overlayNotifications.length - 1 ].container; - collection.focusContainer.prop( 'tabIndex', -1 ); - focusableElements = collection.focusContainer.find( ':focusable' ); - if ( focusableElements.length ) { - focusableElements.first().focus(); - } else { - collection.focusContainer.focus(); - } - } else if ( collection.previousActiveElement ) { - $( collection.previousActiveElement ).focus(); - collection.previousActiveElement = null; - } - - collection.previousNotifications = notifications; - collection.previousContainer = collection.container; - collection.trigger( 'rendered' ); - }, - - /** - * Constrain focus on focus container. - * - * @since 4.9.0 - * - * @param {jQuery.Event} event - Event. - * @returns {void} - */ - constrainFocus: function constrainFocus( event ) { - var collection = this, focusableElements; - - // Prevent keys from escaping. - event.stopPropagation(); - - if ( 9 !== event.which ) { // Tab key. - return; - } - - focusableElements = collection.focusContainer.find( ':focusable' ); - if ( 0 === focusableElements.length ) { - focusableElements = collection.focusContainer; - } - - if ( ! $.contains( collection.focusContainer[0], event.target ) || ! $.contains( collection.focusContainer[0], document.activeElement ) ) { - event.preventDefault(); - focusableElements.first().focus(); - } else if ( focusableElements.last().is( event.target ) && ! event.shiftKey ) { - event.preventDefault(); - focusableElements.first().focus(); - } else if ( focusableElements.first().is( event.target ) && event.shiftKey ) { - event.preventDefault(); - focusableElements.last().focus(); - } - } - }); - - api.Setting = api.Value.extend(/** @lends wp.customize.Setting.prototype */{ - - /** - * Default params. - * - * @since 4.9.0 - * @var {object} - */ - defaults: { - transport: 'refresh', - dirty: false - }, - - /** - * A Customizer Setting. - * - * A setting is WordPress data (theme mod, option, menu, etc.) that the user can - * draft changes to in the Customizer. - * - * @see PHP class WP_Customize_Setting. - * - * @constructs wp.customize.Setting - * @augments wp.customize.Value - * - * @since 3.4.0 - * - * @param {string} id - The setting ID. - * @param {*} value - The initial value of the setting. - * @param {object} [options={}] - Options. - * @param {string} [options.transport=refresh] - The transport to use for previewing. Supports 'refresh' and 'postMessage'. - * @param {boolean} [options.dirty=false] - Whether the setting should be considered initially dirty. - * @param {object} [options.previewer] - The Previewer instance to sync with. Defaults to wp.customize.previewer. - */ - initialize: function( id, value, options ) { - var setting = this, params; - params = _.extend( - { previewer: api.previewer }, - setting.defaults, - options || {} - ); - - api.Value.prototype.initialize.call( setting, value, params ); - - setting.id = id; - setting._dirty = params.dirty; // The _dirty property is what the Customizer reads from. - setting.notifications = new api.Notifications(); - - // Whenever the setting's value changes, refresh the preview. - setting.bind( setting.preview ); - }, - - /** - * Refresh the preview, respective of the setting's refresh policy. - * - * If the preview hasn't sent a keep-alive message and is likely - * disconnected by having navigated to a non-allowed URL, then the - * refresh transport will be forced when postMessage is the transport. - * Note that postMessage does not throw an error when the recipient window - * fails to match the origin window, so using try/catch around the - * previewer.send() call to then fallback to refresh will not work. - * - * @since 3.4.0 - * @access public - * - * @returns {void} - */ - preview: function() { - var setting = this, transport; - transport = setting.transport; - - if ( 'postMessage' === transport && ! api.state( 'previewerAlive' ).get() ) { - transport = 'refresh'; - } - - if ( 'postMessage' === transport ) { - setting.previewer.send( 'setting', [ setting.id, setting() ] ); - } else if ( 'refresh' === transport ) { - setting.previewer.refresh(); - } - }, - - /** - * Find controls associated with this setting. - * - * @since 4.6.0 - * @returns {wp.customize.Control[]} Controls associated with setting. - */ - findControls: function() { - var setting = this, controls = []; - api.control.each( function( control ) { - _.each( control.settings, function( controlSetting ) { - if ( controlSetting.id === setting.id ) { - controls.push( control ); - } - } ); - } ); - return controls; - } - }); - - /** - * Current change count. - * - * @alias wp.customize._latestRevision - * - * @since 4.7.0 - * @type {number} - * @protected - */ - api._latestRevision = 0; - - /** - * Last revision that was saved. - * - * @alias wp.customize._lastSavedRevision - * - * @since 4.7.0 - * @type {number} - * @protected - */ - api._lastSavedRevision = 0; - - /** - * Latest revisions associated with the updated setting. - * - * @alias wp.customize._latestSettingRevisions - * - * @since 4.7.0 - * @type {object} - * @protected - */ - api._latestSettingRevisions = {}; - - /* - * Keep track of the revision associated with each updated setting so that - * requestChangesetUpdate knows which dirty settings to include. Also, once - * ready is triggered and all initial settings have been added, increment - * revision for each newly-created initially-dirty setting so that it will - * also be included in changeset update requests. - */ - api.bind( 'change', function incrementChangedSettingRevision( setting ) { - api._latestRevision += 1; - api._latestSettingRevisions[ setting.id ] = api._latestRevision; - } ); - api.bind( 'ready', function() { - api.bind( 'add', function incrementCreatedSettingRevision( setting ) { - if ( setting._dirty ) { - api._latestRevision += 1; - api._latestSettingRevisions[ setting.id ] = api._latestRevision; - } - } ); - } ); - - /** - * Get the dirty setting values. - * - * @alias wp.customize.dirtyValues - * - * @since 4.7.0 - * @access public - * - * @param {object} [options] Options. - * @param {boolean} [options.unsaved=false] Whether only values not saved yet into a changeset will be returned (differential changes). - * @returns {object} Dirty setting values. - */ - api.dirtyValues = function dirtyValues( options ) { - var values = {}; - api.each( function( setting ) { - var settingRevision; - - if ( ! setting._dirty ) { - return; - } - - settingRevision = api._latestSettingRevisions[ setting.id ]; - - // Skip including settings that have already been included in the changeset, if only requesting unsaved. - if ( api.state( 'changesetStatus' ).get() && ( options && options.unsaved ) && ( _.isUndefined( settingRevision ) || settingRevision <= api._lastSavedRevision ) ) { - return; - } - - values[ setting.id ] = setting.get(); - } ); - return values; - }; - - /** - * Request updates to the changeset. - * - * @alias wp.customize.requestChangesetUpdate - * - * @since 4.7.0 - * @access public - * - * @param {object} [changes] - Mapping of setting IDs to setting params each normally including a value property, or mapping to null. - * If not provided, then the changes will still be obtained from unsaved dirty settings. - * @param {object} [args] - Additional options for the save request. - * @param {boolean} [args.autosave=false] - Whether changes will be stored in autosave revision if the changeset has been promoted from an auto-draft. - * @param {boolean} [args.force=false] - Send request to update even when there are no changes to submit. This can be used to request the latest status of the changeset on the server. - * @param {string} [args.title] - Title to update in the changeset. Optional. - * @param {string} [args.date] - Date to update in the changeset. Optional. - * @returns {jQuery.Promise} Promise resolving with the response data. - */ - api.requestChangesetUpdate = function requestChangesetUpdate( changes, args ) { - var deferred, request, submittedChanges = {}, data, submittedArgs; - deferred = new $.Deferred(); - - // Prevent attempting changeset update while request is being made. - if ( 0 !== api.state( 'processing' ).get() ) { - deferred.reject( 'already_processing' ); - return deferred.promise(); - } - - submittedArgs = _.extend( { - title: null, - date: null, - autosave: false, - force: false - }, args ); - - if ( changes ) { - _.extend( submittedChanges, changes ); - } - - // Ensure all revised settings (changes pending save) are also included, but not if marked for deletion in changes. - _.each( api.dirtyValues( { unsaved: true } ), function( dirtyValue, settingId ) { - if ( ! changes || null !== changes[ settingId ] ) { - submittedChanges[ settingId ] = _.extend( - {}, - submittedChanges[ settingId ] || {}, - { value: dirtyValue } - ); - } - } ); - - // Allow plugins to attach additional params to the settings. - api.trigger( 'changeset-save', submittedChanges, submittedArgs ); - - // Short-circuit when there are no pending changes. - if ( ! submittedArgs.force && _.isEmpty( submittedChanges ) && null === submittedArgs.title && null === submittedArgs.date ) { - deferred.resolve( {} ); - return deferred.promise(); - } - - // A status would cause a revision to be made, and for this wp.customize.previewer.save() should be used. Status is also disallowed for revisions regardless. - if ( submittedArgs.status ) { - return deferred.reject( { code: 'illegal_status_in_changeset_update' } ).promise(); - } - - // Dates not beung allowed for revisions are is a technical limitation of post revisions. - if ( submittedArgs.date && submittedArgs.autosave ) { - return deferred.reject( { code: 'illegal_autosave_with_date_gmt' } ).promise(); - } - - // Make sure that publishing a changeset waits for all changeset update requests to complete. - api.state( 'processing' ).set( api.state( 'processing' ).get() + 1 ); - deferred.always( function() { - api.state( 'processing' ).set( api.state( 'processing' ).get() - 1 ); - } ); - - // Ensure that if any plugins add data to save requests by extending query() that they get included here. - data = api.previewer.query( { excludeCustomizedSaved: true } ); - delete data.customized; // Being sent in customize_changeset_data instead. - _.extend( data, { - nonce: api.settings.nonce.save, - customize_theme: api.settings.theme.stylesheet, - customize_changeset_data: JSON.stringify( submittedChanges ) - } ); - if ( null !== submittedArgs.title ) { - data.customize_changeset_title = submittedArgs.title; - } - if ( null !== submittedArgs.date ) { - data.customize_changeset_date = submittedArgs.date; - } - if ( false !== submittedArgs.autosave ) { - data.customize_changeset_autosave = 'true'; - } - - // Allow plugins to modify the params included with the save request. - api.trigger( 'save-request-params', data ); - - request = wp.ajax.post( 'customize_save', data ); - - request.done( function requestChangesetUpdateDone( data ) { - var savedChangesetValues = {}; - - // Ensure that all settings updated subsequently will be included in the next changeset update request. - api._lastSavedRevision = Math.max( api._latestRevision, api._lastSavedRevision ); - - api.state( 'changesetStatus' ).set( data.changeset_status ); - - if ( data.changeset_date ) { - api.state( 'changesetDate' ).set( data.changeset_date ); - } - - deferred.resolve( data ); - api.trigger( 'changeset-saved', data ); - - if ( data.setting_validities ) { - _.each( data.setting_validities, function( validity, settingId ) { - if ( true === validity && _.isObject( submittedChanges[ settingId ] ) && ! _.isUndefined( submittedChanges[ settingId ].value ) ) { - savedChangesetValues[ settingId ] = submittedChanges[ settingId ].value; - } - } ); - } - - api.previewer.send( 'changeset-saved', _.extend( {}, data, { saved_changeset_values: savedChangesetValues } ) ); - } ); - request.fail( function requestChangesetUpdateFail( data ) { - deferred.reject( data ); - api.trigger( 'changeset-error', data ); - } ); - request.always( function( data ) { - if ( data.setting_validities ) { - api._handleSettingValidities( { - settingValidities: data.setting_validities - } ); - } - } ); - - return deferred.promise(); - }; - - /** - * Watch all changes to Value properties, and bubble changes to parent Values instance - * - * @alias wp.customize.utils.bubbleChildValueChanges - * - * @since 4.1.0 - * - * @param {wp.customize.Class} instance - * @param {Array} properties The names of the Value instances to watch. - */ - api.utils.bubbleChildValueChanges = function ( instance, properties ) { - $.each( properties, function ( i, key ) { - instance[ key ].bind( function ( to, from ) { - if ( instance.parent && to !== from ) { - instance.parent.trigger( 'change', instance ); - } - } ); - } ); - }; - - /** - * Expand a panel, section, or control and focus on the first focusable element. - * - * @alias wp.customize~focus - * - * @since 4.1.0 - * - * @param {Object} [params] - * @param {Function} [params.completeCallback] - */ - focus = function ( params ) { - var construct, completeCallback, focus, focusElement; - construct = this; - params = params || {}; - focus = function () { - var focusContainer; - if ( ( construct.extended( api.Panel ) || construct.extended( api.Section ) ) && construct.expanded && construct.expanded() ) { - focusContainer = construct.contentContainer; - } else { - focusContainer = construct.container; - } - - focusElement = focusContainer.find( '.control-focus:first' ); - if ( 0 === focusElement.length ) { - // Note that we can't use :focusable due to a jQuery UI issue. See: https://github.com/jquery/jquery-ui/pull/1583 - focusElement = focusContainer.find( 'input, select, textarea, button, object, a[href], [tabindex]' ).filter( ':visible' ).first(); - } - focusElement.focus(); - }; - if ( params.completeCallback ) { - completeCallback = params.completeCallback; - params.completeCallback = function () { - focus(); - completeCallback(); - }; - } else { - params.completeCallback = focus; - } - - api.state( 'paneVisible' ).set( true ); - if ( construct.expand ) { - construct.expand( params ); - } else { - params.completeCallback(); - } - }; - - /** - * Stable sort for Panels, Sections, and Controls. - * - * If a.priority() === b.priority(), then sort by their respective params.instanceNumber. - * - * @alias wp.customize.utils.prioritySort - * - * @since 4.1.0 - * - * @param {(wp.customize.Panel|wp.customize.Section|wp.customize.Control)} a - * @param {(wp.customize.Panel|wp.customize.Section|wp.customize.Control)} b - * @returns {Number} - */ - api.utils.prioritySort = function ( a, b ) { - if ( a.priority() === b.priority() && typeof a.params.instanceNumber === 'number' && typeof b.params.instanceNumber === 'number' ) { - return a.params.instanceNumber - b.params.instanceNumber; - } else { - return a.priority() - b.priority(); - } - }; - - /** - * Return whether the supplied Event object is for a keydown event but not the Enter key. - * - * @alias wp.customize.utils.isKeydownButNotEnterEvent - * - * @since 4.1.0 - * - * @param {jQuery.Event} event - * @returns {boolean} - */ - api.utils.isKeydownButNotEnterEvent = function ( event ) { - return ( 'keydown' === event.type && 13 !== event.which ); - }; - - /** - * Return whether the two lists of elements are the same and are in the same order. - * - * @alias wp.customize.utils.areElementListsEqual - * - * @since 4.1.0 - * - * @param {Array|jQuery} listA - * @param {Array|jQuery} listB - * @returns {boolean} - */ - api.utils.areElementListsEqual = function ( listA, listB ) { - var equal = ( - listA.length === listB.length && // if lists are different lengths, then naturally they are not equal - -1 === _.indexOf( _.map( // are there any false values in the list returned by map? - _.zip( listA, listB ), // pair up each element between the two lists - function ( pair ) { - return $( pair[0] ).is( pair[1] ); // compare to see if each pair are equal - } - ), false ) // check for presence of false in map's return value - ); - return equal; - }; - - /** - * Highlight the existence of a button. - * - * This function reminds the user of a button represented by the specified - * UI element, after an optional delay. If the user focuses the element - * before the delay passes, the reminder is canceled. - * - * @alias wp.customize.utils.highlightButton - * - * @since 4.9.0 - * - * @param {jQuery} button - The element to highlight. - * @param {object} [options] - Options. - * @param {number} [options.delay=0] - Delay in milliseconds. - * @param {jQuery} [options.focusTarget] - A target for user focus that defaults to the highlighted element. - * If the user focuses the target before the delay passes, the reminder - * is canceled. This option exists to accommodate compound buttons - * containing auxiliary UI, such as the Publish button augmented with a - * Settings button. - * @returns {Function} An idempotent function that cancels the reminder. - */ - api.utils.highlightButton = function highlightButton( button, options ) { - var animationClass = 'button-see-me', - canceled = false, - params; - - params = _.extend( - { - delay: 0, - focusTarget: button - }, - options - ); - - function cancelReminder() { - canceled = true; - } - - params.focusTarget.on( 'focusin', cancelReminder ); - setTimeout( function() { - params.focusTarget.off( 'focusin', cancelReminder ); - - if ( ! canceled ) { - button.addClass( animationClass ); - button.one( 'animationend', function() { - /* - * Remove animation class to avoid situations in Customizer where - * DOM nodes are moved (re-inserted) and the animation repeats. - */ - button.removeClass( animationClass ); - } ); - } - }, params.delay ); - - return cancelReminder; - }; - - /** - * Get current timestamp adjusted for server clock time. - * - * Same functionality as the `current_time( 'mysql', false )` function in PHP. - * - * @alias wp.customize.utils.getCurrentTimestamp - * - * @since 4.9.0 - * - * @returns {int} Current timestamp. - */ - api.utils.getCurrentTimestamp = function getCurrentTimestamp() { - var currentDate, currentClientTimestamp, timestampDifferential; - currentClientTimestamp = _.now(); - currentDate = new Date( api.settings.initialServerDate.replace( /-/g, '/' ) ); - timestampDifferential = currentClientTimestamp - api.settings.initialClientTimestamp; - timestampDifferential += api.settings.initialClientTimestamp - api.settings.initialServerTimestamp; - currentDate.setTime( currentDate.getTime() + timestampDifferential ); - return currentDate.getTime(); - }; - - /** - * Get remaining time of when the date is set. - * - * @alias wp.customize.utils.getRemainingTime - * - * @since 4.9.0 - * - * @param {string|int|Date} datetime - Date time or timestamp of the future date. - * @return {int} remainingTime - Remaining time in milliseconds. - */ - api.utils.getRemainingTime = function getRemainingTime( datetime ) { - var millisecondsDivider = 1000, remainingTime, timestamp; - if ( datetime instanceof Date ) { - timestamp = datetime.getTime(); - } else if ( 'string' === typeof datetime ) { - timestamp = ( new Date( datetime.replace( /-/g, '/' ) ) ).getTime(); - } else { - timestamp = datetime; - } - - remainingTime = timestamp - api.utils.getCurrentTimestamp(); - remainingTime = Math.ceil( remainingTime / millisecondsDivider ); - return remainingTime; - }; - - /** - * Return browser supported `transitionend` event name. - * - * @since 4.7.0 - * - * @ignore - * - * @returns {string|null} Normalized `transitionend` event name or null if CSS transitions are not supported. - */ - normalizedTransitionendEventName = (function () { - var el, transitions, prop; - el = document.createElement( 'div' ); - transitions = { - 'transition' : 'transitionend', - 'OTransition' : 'oTransitionEnd', - 'MozTransition' : 'transitionend', - 'WebkitTransition': 'webkitTransitionEnd' - }; - prop = _.find( _.keys( transitions ), function( prop ) { - return ! _.isUndefined( el.style[ prop ] ); - } ); - if ( prop ) { - return transitions[ prop ]; - } else { - return null; - } - })(); - - Container = api.Class.extend(/** @lends wp.customize~Container.prototype */{ - defaultActiveArguments: { duration: 'fast', completeCallback: $.noop }, - defaultExpandedArguments: { duration: 'fast', completeCallback: $.noop }, - containerType: 'container', - defaults: { - title: '', - description: '', - priority: 100, - type: 'default', - content: null, - active: true, - instanceNumber: null - }, - - /** - * Base class for Panel and Section. - * - * @constructs wp.customize~Container - * @augments wp.customize.Class - * - * @since 4.1.0 - * - * @borrows wp.customize~focus as focus - * - * @param {string} id - The ID for the container. - * @param {object} options - Object containing one property: params. - * @param {string} options.title - Title shown when panel is collapsed and expanded. - * @param {string} [options.description] - Description shown at the top of the panel. - * @param {number} [options.priority=100] - The sort priority for the panel. - * @param {string} [options.templateId] - Template selector for container. - * @param {string} [options.type=default] - The type of the panel. See wp.customize.panelConstructor. - * @param {string} [options.content] - The markup to be used for the panel container. If empty, a JS template is used. - * @param {boolean} [options.active=true] - Whether the panel is active or not. - * @param {object} [options.params] - Deprecated wrapper for the above properties. - */ - initialize: function ( id, options ) { - var container = this; - container.id = id; - - if ( ! Container.instanceCounter ) { - Container.instanceCounter = 0; - } - Container.instanceCounter++; - - $.extend( container, { - params: _.defaults( - options.params || options, // Passing the params is deprecated. - container.defaults - ) - } ); - if ( ! container.params.instanceNumber ) { - container.params.instanceNumber = Container.instanceCounter; - } - container.notifications = new api.Notifications(); - container.templateSelector = container.params.templateId || 'customize-' + container.containerType + '-' + container.params.type; - container.container = $( container.params.content ); - if ( 0 === container.container.length ) { - container.container = $( container.getContainer() ); - } - container.headContainer = container.container; - container.contentContainer = container.getContent(); - container.container = container.container.add( container.contentContainer ); - - container.deferred = { - embedded: new $.Deferred() - }; - container.priority = new api.Value(); - container.active = new api.Value(); - container.activeArgumentsQueue = []; - container.expanded = new api.Value(); - container.expandedArgumentsQueue = []; - - container.active.bind( function ( active ) { - var args = container.activeArgumentsQueue.shift(); - args = $.extend( {}, container.defaultActiveArguments, args ); - active = ( active && container.isContextuallyActive() ); - container.onChangeActive( active, args ); - }); - container.expanded.bind( function ( expanded ) { - var args = container.expandedArgumentsQueue.shift(); - args = $.extend( {}, container.defaultExpandedArguments, args ); - container.onChangeExpanded( expanded, args ); - }); - - container.deferred.embedded.done( function () { - container.setupNotifications(); - container.attachEvents(); - }); - - api.utils.bubbleChildValueChanges( container, [ 'priority', 'active' ] ); - - container.priority.set( container.params.priority ); - container.active.set( container.params.active ); - container.expanded.set( false ); - }, - - /** - * Get the element that will contain the notifications. - * - * @since 4.9.0 - * @returns {jQuery} Notification container element. - */ - getNotificationsContainerElement: function() { - var container = this; - return container.contentContainer.find( '.customize-control-notifications-container:first' ); - }, - - /** - * Set up notifications. - * - * @since 4.9.0 - * @returns {void} - */ - setupNotifications: function() { - var container = this, renderNotifications; - container.notifications.container = container.getNotificationsContainerElement(); - - // Render notifications when they change and when the construct is expanded. - renderNotifications = function() { - if ( container.expanded.get() ) { - container.notifications.render(); - } - }; - container.expanded.bind( renderNotifications ); - renderNotifications(); - container.notifications.bind( 'change', _.debounce( renderNotifications ) ); - }, - - /** - * @since 4.1.0 - * - * @abstract - */ - ready: function() {}, - - /** - * Get the child models associated with this parent, sorting them by their priority Value. - * - * @since 4.1.0 - * - * @param {String} parentType - * @param {String} childType - * @returns {Array} - */ - _children: function ( parentType, childType ) { - var parent = this, - children = []; - api[ childType ].each( function ( child ) { - if ( child[ parentType ].get() === parent.id ) { - children.push( child ); - } - } ); - children.sort( api.utils.prioritySort ); - return children; - }, - - /** - * To override by subclass, to return whether the container has active children. - * - * @since 4.1.0 - * - * @abstract - */ - isContextuallyActive: function () { - throw new Error( 'Container.isContextuallyActive() must be overridden in a subclass.' ); - }, - - /** - * Active state change handler. - * - * Shows the container if it is active, hides it if not. - * - * To override by subclass, update the container's UI to reflect the provided active state. - * - * @since 4.1.0 - * - * @param {boolean} active - The active state to transiution to. - * @param {Object} [args] - Args. - * @param {Object} [args.duration] - The duration for the slideUp/slideDown animation. - * @param {boolean} [args.unchanged] - Whether the state is already known to not be changed, and so short-circuit with calling completeCallback early. - * @param {Function} [args.completeCallback] - Function to call when the slideUp/slideDown has completed. - */ - onChangeActive: function( active, args ) { - var construct = this, - headContainer = construct.headContainer, - duration, expandedOtherPanel; - - if ( args.unchanged ) { - if ( args.completeCallback ) { - args.completeCallback(); - } - return; - } - - duration = ( 'resolved' === api.previewer.deferred.active.state() ? args.duration : 0 ); - - if ( construct.extended( api.Panel ) ) { - // If this is a panel is not currently expanded but another panel is expanded, do not animate. - api.panel.each(function ( panel ) { - if ( panel !== construct && panel.expanded() ) { - expandedOtherPanel = panel; - duration = 0; - } - }); - - // Collapse any expanded sections inside of this panel first before deactivating. - if ( ! active ) { - _.each( construct.sections(), function( section ) { - section.collapse( { duration: 0 } ); - } ); - } - } - - if ( ! $.contains( document, headContainer.get( 0 ) ) ) { - // If the element is not in the DOM, then jQuery.fn.slideUp() does nothing. In this case, a hard toggle is required instead. - headContainer.toggle( active ); - if ( args.completeCallback ) { - args.completeCallback(); - } - } else if ( active ) { - headContainer.slideDown( duration, args.completeCallback ); - } else { - if ( construct.expanded() ) { - construct.collapse({ - duration: duration, - completeCallback: function() { - headContainer.slideUp( duration, args.completeCallback ); - } - }); - } else { - headContainer.slideUp( duration, args.completeCallback ); - } - } - }, - - /** - * @since 4.1.0 - * - * @params {Boolean} active - * @param {Object} [params] - * @returns {Boolean} false if state already applied - */ - _toggleActive: function ( active, params ) { - var self = this; - params = params || {}; - if ( ( active && this.active.get() ) || ( ! active && ! this.active.get() ) ) { - params.unchanged = true; - self.onChangeActive( self.active.get(), params ); - return false; - } else { - params.unchanged = false; - this.activeArgumentsQueue.push( params ); - this.active.set( active ); - return true; - } - }, - - /** - * @param {Object} [params] - * @returns {Boolean} false if already active - */ - activate: function ( params ) { - return this._toggleActive( true, params ); - }, - - /** - * @param {Object} [params] - * @returns {Boolean} false if already inactive - */ - deactivate: function ( params ) { - return this._toggleActive( false, params ); - }, - - /** - * To override by subclass, update the container's UI to reflect the provided active state. - * @abstract - */ - onChangeExpanded: function () { - throw new Error( 'Must override with subclass.' ); - }, - - /** - * Handle the toggle logic for expand/collapse. - * - * @param {Boolean} expanded - The new state to apply. - * @param {Object} [params] - Object containing options for expand/collapse. - * @param {Function} [params.completeCallback] - Function to call when expansion/collapse is complete. - * @returns {Boolean} false if state already applied or active state is false - */ - _toggleExpanded: function( expanded, params ) { - var instance = this, previousCompleteCallback; - params = params || {}; - previousCompleteCallback = params.completeCallback; - - // Short-circuit expand() if the instance is not active. - if ( expanded && ! instance.active() ) { - return false; - } - - api.state( 'paneVisible' ).set( true ); - params.completeCallback = function() { - if ( previousCompleteCallback ) { - previousCompleteCallback.apply( instance, arguments ); - } - if ( expanded ) { - instance.container.trigger( 'expanded' ); - } else { - instance.container.trigger( 'collapsed' ); - } - }; - if ( ( expanded && instance.expanded.get() ) || ( ! expanded && ! instance.expanded.get() ) ) { - params.unchanged = true; - instance.onChangeExpanded( instance.expanded.get(), params ); - return false; - } else { - params.unchanged = false; - instance.expandedArgumentsQueue.push( params ); - instance.expanded.set( expanded ); - return true; - } - }, - - /** - * @param {Object} [params] - * @returns {Boolean} false if already expanded or if inactive. - */ - expand: function ( params ) { - return this._toggleExpanded( true, params ); - }, - - /** - * @param {Object} [params] - * @returns {Boolean} false if already collapsed. - */ - collapse: function ( params ) { - return this._toggleExpanded( false, params ); - }, - - /** - * Animate container state change if transitions are supported by the browser. - * - * @since 4.7.0 - * @private - * - * @param {function} completeCallback Function to be called after transition is completed. - * @returns {void} - */ - _animateChangeExpanded: function( completeCallback ) { - // Return if CSS transitions are not supported. - if ( ! normalizedTransitionendEventName ) { - if ( completeCallback ) { - completeCallback(); - } - return; - } - - var construct = this, - content = construct.contentContainer, - overlay = content.closest( '.wp-full-overlay' ), - elements, transitionEndCallback, transitionParentPane; - - // Determine set of elements that are affected by the animation. - elements = overlay.add( content ); - - if ( ! construct.panel || '' === construct.panel() ) { - transitionParentPane = true; - } else if ( api.panel( construct.panel() ).contentContainer.hasClass( 'skip-transition' ) ) { - transitionParentPane = true; - } else { - transitionParentPane = false; - } - if ( transitionParentPane ) { - elements = elements.add( '#customize-info, .customize-pane-parent' ); - } - - // Handle `transitionEnd` event. - transitionEndCallback = function( e ) { - if ( 2 !== e.eventPhase || ! $( e.target ).is( content ) ) { - return; - } - content.off( normalizedTransitionendEventName, transitionEndCallback ); - elements.removeClass( 'busy' ); - if ( completeCallback ) { - completeCallback(); - } - }; - content.on( normalizedTransitionendEventName, transitionEndCallback ); - elements.addClass( 'busy' ); - - // Prevent screen flicker when pane has been scrolled before expanding. - _.defer( function() { - var container = content.closest( '.wp-full-overlay-sidebar-content' ), - currentScrollTop = container.scrollTop(), - previousScrollTop = content.data( 'previous-scrollTop' ) || 0, - expanded = construct.expanded(); - - if ( expanded && 0 < currentScrollTop ) { - content.css( 'top', currentScrollTop + 'px' ); - content.data( 'previous-scrollTop', currentScrollTop ); - } else if ( ! expanded && 0 < currentScrollTop + previousScrollTop ) { - content.css( 'top', previousScrollTop - currentScrollTop + 'px' ); - container.scrollTop( previousScrollTop ); - } - } ); - }, - - /* - * is documented using @borrows in the constructor. - */ - focus: focus, - - /** - * Return the container html, generated from its JS template, if it exists. - * - * @since 4.3.0 - */ - getContainer: function () { - var template, - container = this; - - if ( 0 !== $( '#tmpl-' + container.templateSelector ).length ) { - template = wp.template( container.templateSelector ); - } else { - template = wp.template( 'customize-' + container.containerType + '-default' ); - } - if ( template && container.container ) { - return $.trim( template( _.extend( - { id: container.id }, - container.params - ) ) ); - } - - return '<li></li>'; - }, - - /** - * Find content element which is displayed when the section is expanded. - * - * After a construct is initialized, the return value will be available via the `contentContainer` property. - * By default the element will be related it to the parent container with `aria-owns` and detached. - * Custom panels and sections (such as the `NewMenuSection`) that do not have a sliding pane should - * just return the content element without needing to add the `aria-owns` element or detach it from - * the container. Such non-sliding pane custom sections also need to override the `onChangeExpanded` - * method to handle animating the panel/section into and out of view. - * - * @since 4.7.0 - * @access public - * - * @returns {jQuery} Detached content element. - */ - getContent: function() { - var construct = this, - container = construct.container, - content = container.find( '.accordion-section-content, .control-panel-content' ).first(), - contentId = 'sub-' + container.attr( 'id' ), - ownedElements = contentId, - alreadyOwnedElements = container.attr( 'aria-owns' ); - - if ( alreadyOwnedElements ) { - ownedElements = ownedElements + ' ' + alreadyOwnedElements; - } - container.attr( 'aria-owns', ownedElements ); - - return content.detach().attr( { - 'id': contentId, - 'class': 'customize-pane-child ' + content.attr( 'class' ) + ' ' + container.attr( 'class' ) - } ); - } - }); - - api.Section = Container.extend(/** @lends wp.customize.Section.prototype */{ - containerType: 'section', - containerParent: '#customize-theme-controls', - containerPaneParent: '.customize-pane-parent', - defaults: { - title: '', - description: '', - priority: 100, - type: 'default', - content: null, - active: true, - instanceNumber: null, - panel: null, - customizeAction: '' - }, - - /** - * @constructs wp.customize.Section - * @augments wp.customize~Container - * - * @since 4.1.0 - * - * @param {string} id - The ID for the section. - * @param {object} options - Options. - * @param {string} options.title - Title shown when section is collapsed and expanded. - * @param {string} [options.description] - Description shown at the top of the section. - * @param {number} [options.priority=100] - The sort priority for the section. - * @param {string} [options.type=default] - The type of the section. See wp.customize.sectionConstructor. - * @param {string} [options.content] - The markup to be used for the section container. If empty, a JS template is used. - * @param {boolean} [options.active=true] - Whether the section is active or not. - * @param {string} options.panel - The ID for the panel this section is associated with. - * @param {string} [options.customizeAction] - Additional context information shown before the section title when expanded. - * @param {object} [options.params] - Deprecated wrapper for the above properties. - */ - initialize: function ( id, options ) { - var section = this, params; - params = options.params || options; - - // Look up the type if one was not supplied. - if ( ! params.type ) { - _.find( api.sectionConstructor, function( Constructor, type ) { - if ( Constructor === section.constructor ) { - params.type = type; - return true; - } - return false; - } ); - } - - Container.prototype.initialize.call( section, id, params ); - - section.id = id; - section.panel = new api.Value(); - section.panel.bind( function ( id ) { - $( section.headContainer ).toggleClass( 'control-subsection', !! id ); - }); - section.panel.set( section.params.panel || '' ); - api.utils.bubbleChildValueChanges( section, [ 'panel' ] ); - - section.embed(); - section.deferred.embedded.done( function () { - section.ready(); - }); - }, - - /** - * Embed the container in the DOM when any parent panel is ready. - * - * @since 4.1.0 - */ - embed: function () { - var inject, - section = this; - - section.containerParent = api.ensure( section.containerParent ); - - // Watch for changes to the panel state. - inject = function ( panelId ) { - var parentContainer; - if ( panelId ) { - // The panel has been supplied, so wait until the panel object is registered. - api.panel( panelId, function ( panel ) { - // The panel has been registered, wait for it to become ready/initialized. - panel.deferred.embedded.done( function () { - parentContainer = panel.contentContainer; - if ( ! section.headContainer.parent().is( parentContainer ) ) { - parentContainer.append( section.headContainer ); - } - if ( ! section.contentContainer.parent().is( section.headContainer ) ) { - section.containerParent.append( section.contentContainer ); - } - section.deferred.embedded.resolve(); - }); - } ); - } else { - // There is no panel, so embed the section in the root of the customizer - parentContainer = api.ensure( section.containerPaneParent ); - if ( ! section.headContainer.parent().is( parentContainer ) ) { - parentContainer.append( section.headContainer ); - } - if ( ! section.contentContainer.parent().is( section.headContainer ) ) { - section.containerParent.append( section.contentContainer ); - } - section.deferred.embedded.resolve(); - } - }; - section.panel.bind( inject ); - inject( section.panel.get() ); // Since a section may never get a panel, assume that it won't ever get one. - }, - - /** - * Add behaviors for the accordion section. - * - * @since 4.1.0 - */ - attachEvents: function () { - var meta, content, section = this; - - if ( section.container.hasClass( 'cannot-expand' ) ) { - return; - } - - // Expand/Collapse accordion sections on click. - section.container.find( '.accordion-section-title, .customize-section-back' ).on( 'click keydown', function( event ) { - if ( api.utils.isKeydownButNotEnterEvent( event ) ) { - return; - } - event.preventDefault(); // Keep this AFTER the key filter above - - if ( section.expanded() ) { - section.collapse(); - } else { - section.expand(); - } - }); - - // This is very similar to what is found for api.Panel.attachEvents(). - section.container.find( '.customize-section-title .customize-help-toggle' ).on( 'click', function() { - - meta = section.container.find( '.section-meta' ); - if ( meta.hasClass( 'cannot-expand' ) ) { - return; - } - content = meta.find( '.customize-section-description:first' ); - content.toggleClass( 'open' ); - content.slideToggle( section.defaultExpandedArguments.duration, function() { - content.trigger( 'toggled' ); - } ); - $( this ).attr( 'aria-expanded', function( i, attr ) { - return 'true' === attr ? 'false' : 'true'; - }); - }); - }, - - /** - * Return whether this section has any active controls. - * - * @since 4.1.0 - * - * @returns {Boolean} - */ - isContextuallyActive: function () { - var section = this, - controls = section.controls(), - activeCount = 0; - _( controls ).each( function ( control ) { - if ( control.active() ) { - activeCount += 1; - } - } ); - return ( activeCount !== 0 ); - }, - - /** - * Get the controls that are associated with this section, sorted by their priority Value. - * - * @since 4.1.0 - * - * @returns {Array} - */ - controls: function () { - return this._children( 'section', 'control' ); - }, - - /** - * Update UI to reflect expanded state. - * - * @since 4.1.0 - * - * @param {Boolean} expanded - * @param {Object} args - */ - onChangeExpanded: function ( expanded, args ) { - var section = this, - container = section.headContainer.closest( '.wp-full-overlay-sidebar-content' ), - content = section.contentContainer, - overlay = section.headContainer.closest( '.wp-full-overlay' ), - backBtn = content.find( '.customize-section-back' ), - sectionTitle = section.headContainer.find( '.accordion-section-title' ).first(), - expand, panel; - - if ( expanded && ! content.hasClass( 'open' ) ) { - - if ( args.unchanged ) { - expand = args.completeCallback; - } else { - expand = $.proxy( function() { - section._animateChangeExpanded( function() { - sectionTitle.attr( 'tabindex', '-1' ); - backBtn.attr( 'tabindex', '0' ); - - backBtn.focus(); - content.css( 'top', '' ); - container.scrollTop( 0 ); - - if ( args.completeCallback ) { - args.completeCallback(); - } - } ); - - content.addClass( 'open' ); - overlay.addClass( 'section-open' ); - api.state( 'expandedSection' ).set( section ); - }, this ); - } - - if ( ! args.allowMultiple ) { - api.section.each( function ( otherSection ) { - if ( otherSection !== section ) { - otherSection.collapse( { duration: args.duration } ); - } - }); - } - - if ( section.panel() ) { - api.panel( section.panel() ).expand({ - duration: args.duration, - completeCallback: expand - }); - } else { - if ( ! args.allowMultiple ) { - api.panel.each( function( panel ) { - panel.collapse(); - }); - } - expand(); - } - - } else if ( ! expanded && content.hasClass( 'open' ) ) { - if ( section.panel() ) { - panel = api.panel( section.panel() ); - if ( panel.contentContainer.hasClass( 'skip-transition' ) ) { - panel.collapse(); - } - } - section._animateChangeExpanded( function() { - backBtn.attr( 'tabindex', '-1' ); - sectionTitle.attr( 'tabindex', '0' ); - - sectionTitle.focus(); - content.css( 'top', '' ); - - if ( args.completeCallback ) { - args.completeCallback(); - } - } ); - - content.removeClass( 'open' ); - overlay.removeClass( 'section-open' ); - if ( section === api.state( 'expandedSection' ).get() ) { - api.state( 'expandedSection' ).set( false ); - } - - } else { - if ( args.completeCallback ) { - args.completeCallback(); - } - } - } - }); - - api.ThemesSection = api.Section.extend(/** @lends wp.customize.ThemesSection.prototype */{ - currentTheme: '', - overlay: '', - template: '', - screenshotQueue: null, - $window: null, - $body: null, - loaded: 0, - loading: false, - fullyLoaded: false, - term: '', - tags: '', - nextTerm: '', - nextTags: '', - filtersHeight: 0, - headerContainer: null, - updateCountDebounced: null, - - /** - * wp.customize.ThemesSection - * - * Custom section for themes that loads themes by category, and also - * handles the theme-details view rendering and navigation. - * - * @constructs wp.customize.ThemesSection - * @augments wp.customize.Section - * - * @since 4.9.0 - * - * @param {string} id - ID. - * @param {object} options - Options. - * @returns {void} - */ - initialize: function( id, options ) { - var section = this; - section.headerContainer = $(); - section.$window = $( window ); - section.$body = $( document.body ); - api.Section.prototype.initialize.call( section, id, options ); - section.updateCountDebounced = _.debounce( section.updateCount, 500 ); - }, - - /** - * Embed the section in the DOM when the themes panel is ready. - * - * Insert the section before the themes container. Assume that a themes section is within a panel, but not necessarily the themes panel. - * - * @since 4.9.0 - */ - embed: function() { - var inject, - section = this; - - // Watch for changes to the panel state - inject = function( panelId ) { - var parentContainer; - api.panel( panelId, function( panel ) { - - // The panel has been registered, wait for it to become ready/initialized - panel.deferred.embedded.done( function() { - parentContainer = panel.contentContainer; - if ( ! section.headContainer.parent().is( parentContainer ) ) { - parentContainer.find( '.customize-themes-full-container-container' ).before( section.headContainer ); - } - if ( ! section.contentContainer.parent().is( section.headContainer ) ) { - section.containerParent.append( section.contentContainer ); - } - section.deferred.embedded.resolve(); - }); - } ); - }; - section.panel.bind( inject ); - inject( section.panel.get() ); // Since a section may never get a panel, assume that it won't ever get one - }, - - /** - * Set up. - * - * @since 4.2.0 - * - * @returns {void} - */ - ready: function() { - var section = this; - section.overlay = section.container.find( '.theme-overlay' ); - section.template = wp.template( 'customize-themes-details-view' ); - - // Bind global keyboard events. - section.container.on( 'keydown', function( event ) { - if ( ! section.overlay.find( '.theme-wrap' ).is( ':visible' ) ) { - return; - } - - // Pressing the right arrow key fires a theme:next event - if ( 39 === event.keyCode ) { - section.nextTheme(); - } - - // Pressing the left arrow key fires a theme:previous event - if ( 37 === event.keyCode ) { - section.previousTheme(); - } - - // Pressing the escape key fires a theme:collapse event - if ( 27 === event.keyCode ) { - if ( section.$body.hasClass( 'modal-open' ) ) { - - // Escape from the details modal. - section.closeDetails(); - } else { - - // Escape from the inifinite scroll list. - section.headerContainer.find( '.customize-themes-section-title' ).focus(); - } - event.stopPropagation(); // Prevent section from being collapsed. - } - }); - - section.renderScreenshots = _.throttle( section.renderScreenshots, 100 ); - - _.bindAll( section, 'renderScreenshots', 'loadMore', 'checkTerm', 'filtersChecked' ); - }, - - /** - * Override Section.isContextuallyActive method. - * - * Ignore the active states' of the contained theme controls, and just - * use the section's own active state instead. This prevents empty search - * results for theme sections from causing the section to become inactive. - * - * @since 4.2.0 - * - * @returns {Boolean} - */ - isContextuallyActive: function () { - return this.active(); - }, - - /** - * Attach events. - * - * @since 4.2.0 - * - * @returns {void} - */ - attachEvents: function () { - var section = this, debounced; - - // Expand/Collapse accordion sections on click. - section.container.find( '.customize-section-back' ).on( 'click keydown', function( event ) { - if ( api.utils.isKeydownButNotEnterEvent( event ) ) { - return; - } - event.preventDefault(); // Keep this AFTER the key filter above - section.collapse(); - }); - - section.headerContainer = $( '#accordion-section-' + section.id ); - - // Expand section/panel. Only collapse when opening another section. - section.headerContainer.on( 'click', '.customize-themes-section-title', function() { - - // Toggle accordion filters under section headers. - if ( section.headerContainer.find( '.filter-details' ).length ) { - section.headerContainer.find( '.customize-themes-section-title' ) - .toggleClass( 'details-open' ) - .attr( 'aria-expanded', function( i, attr ) { - return 'true' === attr ? 'false' : 'true'; - }); - section.headerContainer.find( '.filter-details' ).slideToggle( 180 ); - } - - // Open the section. - if ( ! section.expanded() ) { - section.expand(); - } - }); - - // Preview installed themes. - section.container.on( 'click', '.theme-actions .preview-theme', function() { - api.panel( 'themes' ).loadThemePreview( $( this ).data( 'slug' ) ); - }); - - // Theme navigation in details view. - section.container.on( 'click', '.left', function() { - section.previousTheme(); - }); - - section.container.on( 'click', '.right', function() { - section.nextTheme(); - }); - - section.container.on( 'click', '.theme-backdrop, .close', function() { - section.closeDetails(); - }); - - if ( 'local' === section.params.filter_type ) { - - // Filter-search all theme objects loaded in the section. - section.container.on( 'input', '.wp-filter-search-themes', function( event ) { - section.filterSearch( event.currentTarget.value ); - }); - - } else if ( 'remote' === section.params.filter_type ) { - - // Event listeners for remote queries with user-entered terms. - // Search terms. - debounced = _.debounce( section.checkTerm, 500 ); // Wait until there is no input for 500 milliseconds to initiate a search. - section.contentContainer.on( 'input', '.wp-filter-search', function() { - if ( ! api.panel( 'themes' ).expanded() ) { - return; - } - debounced( section ); - if ( ! section.expanded() ) { - section.expand(); - } - }); - - // Feature filters. - section.contentContainer.on( 'click', '.filter-group input', function() { - section.filtersChecked(); - section.checkTerm( section ); - }); - } - - // Toggle feature filters. - section.contentContainer.on( 'click', '.feature-filter-toggle', function( e ) { - var $themeContainer = $( '.customize-themes-full-container' ), - $filterToggle = $( e.currentTarget ); - section.filtersHeight = $filterToggle.parent().next( '.filter-drawer' ).height(); - - if ( 0 < $themeContainer.scrollTop() ) { - $themeContainer.animate( { scrollTop: 0 }, 400 ); - - if ( $filterToggle.hasClass( 'open' ) ) { - return; - } - } - - $filterToggle - .toggleClass( 'open' ) - .attr( 'aria-expanded', function( i, attr ) { - return 'true' === attr ? 'false' : 'true'; - }) - .parent().next( '.filter-drawer' ).slideToggle( 180, 'linear' ); - - if ( $filterToggle.hasClass( 'open' ) ) { - var marginOffset = 1018 < window.innerWidth ? 50 : 76; - - section.contentContainer.find( '.themes' ).css( 'margin-top', section.filtersHeight + marginOffset ); - } else { - section.contentContainer.find( '.themes' ).css( 'margin-top', 0 ); - } - }); - - // Setup section cross-linking. - section.contentContainer.on( 'click', '.no-themes-local .search-dotorg-themes', function() { - api.section( 'wporg_themes' ).focus(); - }); - - function updateSelectedState() { - var el = section.headerContainer.find( '.customize-themes-section-title' ); - el.toggleClass( 'selected', section.expanded() ); - el.attr( 'aria-expanded', section.expanded() ? 'true' : 'false' ); - if ( ! section.expanded() ) { - el.removeClass( 'details-open' ); - } - } - section.expanded.bind( updateSelectedState ); - updateSelectedState(); - - // Move section controls to the themes area. - api.bind( 'ready', function () { - section.contentContainer = section.container.find( '.customize-themes-section' ); - section.contentContainer.appendTo( $( '.customize-themes-full-container' ) ); - section.container.add( section.headerContainer ); - }); - }, - - /** - * Update UI to reflect expanded state - * - * @since 4.2.0 - * - * @param {Boolean} expanded - * @param {Object} args - * @param {Boolean} args.unchanged - * @param {Function} args.completeCallback - * @returns {void} - */ - onChangeExpanded: function ( expanded, args ) { - - // Note: there is a second argument 'args' passed - var section = this, - container = section.contentContainer.closest( '.customize-themes-full-container' ); - - // Immediately call the complete callback if there were no changes - if ( args.unchanged ) { - if ( args.completeCallback ) { - args.completeCallback(); - } - return; - } - - function expand() { - - // Try to load controls if none are loaded yet. - if ( 0 === section.loaded ) { - section.loadThemes(); - } - - // Collapse any sibling sections/panels - api.section.each( function ( otherSection ) { - var searchTerm; - - if ( otherSection !== section ) { - - // Try to sync the current search term to the new section. - if ( 'themes' === otherSection.params.type ) { - searchTerm = otherSection.contentContainer.find( '.wp-filter-search' ).val(); - section.contentContainer.find( '.wp-filter-search' ).val( searchTerm ); - - // Directly initialize an empty remote search to avoid a race condition. - if ( '' === searchTerm && '' !== section.term && 'local' !== section.params.filter_type ) { - section.term = ''; - section.initializeNewQuery( section.term, section.tags ); - } else { - if ( 'remote' === section.params.filter_type ) { - section.checkTerm( section ); - } else if ( 'local' === section.params.filter_type ) { - section.filterSearch( searchTerm ); - } - } - otherSection.collapse( { duration: args.duration } ); - } - } - }); - - section.contentContainer.addClass( 'current-section' ); - container.scrollTop(); - - container.on( 'scroll', _.throttle( section.renderScreenshots, 300 ) ); - container.on( 'scroll', _.throttle( section.loadMore, 300 ) ); - - if ( args.completeCallback ) { - args.completeCallback(); - } - section.updateCount(); // Show this section's count. - } - - if ( expanded ) { - if ( section.panel() && api.panel.has( section.panel() ) ) { - api.panel( section.panel() ).expand({ - duration: args.duration, - completeCallback: expand - }); - } else { - expand(); - } - } else { - section.contentContainer.removeClass( 'current-section' ); - - // Always hide, even if they don't exist or are already hidden. - section.headerContainer.find( '.filter-details' ).slideUp( 180 ); - - container.off( 'scroll' ); - - if ( args.completeCallback ) { - args.completeCallback(); - } - } - }, - - /** - * Return the section's content element without detaching from the parent. - * - * @since 4.9.0 - * - * @returns {jQuery} - */ - getContent: function() { - return this.container.find( '.control-section-content' ); - }, - - /** - * Load theme data via Ajax and add themes to the section as controls. - * - * @since 4.9.0 - * - * @returns {void} - */ - loadThemes: function() { - var section = this, params, page, request; - - if ( section.loading ) { - return; // We're already loading a batch of themes. - } - - // Parameters for every API query. Additional params are set in PHP. - page = Math.ceil( section.loaded / 100 ) + 1; - params = { - 'nonce': api.settings.nonce.switch_themes, - 'wp_customize': 'on', - 'theme_action': section.params.action, - 'customized_theme': api.settings.theme.stylesheet, - 'page': page - }; - - // Add fields for remote filtering. - if ( 'remote' === section.params.filter_type ) { - params.search = section.term; - params.tags = section.tags; - } - - // Load themes. - section.headContainer.closest( '.wp-full-overlay' ).addClass( 'loading' ); - section.loading = true; - section.container.find( '.no-themes' ).hide(); - request = wp.ajax.post( 'customize_load_themes', params ); - request.done(function( data ) { - var themes = data.themes; - - // Stop and try again if the term changed while loading. - if ( '' !== section.nextTerm || '' !== section.nextTags ) { - if ( section.nextTerm ) { - section.term = section.nextTerm; - } - if ( section.nextTags ) { - section.tags = section.nextTags; - } - section.nextTerm = ''; - section.nextTags = ''; - section.loading = false; - section.loadThemes(); - return; - } - - if ( 0 !== themes.length ) { - - section.loadControls( themes, page ); - - if ( 1 === page ) { - - // Pre-load the first 3 theme screenshots. - _.each( section.controls().slice( 0, 3 ), function( control ) { - var img, src = control.params.theme.screenshot[0]; - if ( src ) { - img = new Image(); - img.src = src; - } - }); - if ( 'local' !== section.params.filter_type ) { - wp.a11y.speak( api.settings.l10n.themeSearchResults.replace( '%d', data.info.results ) ); - } - } - - _.delay( section.renderScreenshots, 100 ); // Wait for the controls to become visible. - - if ( 'local' === section.params.filter_type || 100 > themes.length ) { // If we have less than the requested 100 themes, it's the end of the list. - section.fullyLoaded = true; - } - } else { - if ( 0 === section.loaded ) { - section.container.find( '.no-themes' ).show(); - wp.a11y.speak( section.container.find( '.no-themes' ).text() ); - } else { - section.fullyLoaded = true; - } - } - if ( 'local' === section.params.filter_type ) { - section.updateCount(); // Count of visible theme controls. - } else { - section.updateCount( data.info.results ); // Total number of results including pages not yet loaded. - } - section.container.find( '.unexpected-error' ).hide(); // Hide error notice in case it was previously shown. - - // This cannot run on request.always, as section.loading may turn false before the new controls load in the success case. - section.headContainer.closest( '.wp-full-overlay' ).removeClass( 'loading' ); - section.loading = false; - }); - request.fail(function( data ) { - if ( 'undefined' === typeof data ) { - section.container.find( '.unexpected-error' ).show(); - wp.a11y.speak( section.container.find( '.unexpected-error' ).text() ); - } else if ( 'undefined' !== typeof console && console.error ) { - console.error( data ); - } - - // This cannot run on request.always, as section.loading may turn false before the new controls load in the success case. - section.headContainer.closest( '.wp-full-overlay' ).removeClass( 'loading' ); - section.loading = false; - }); - }, - - /** - * Loads controls into the section from data received from loadThemes(). - * - * @since 4.9.0 - * @param {Array} themes - Array of theme data to create controls with. - * @param {integer} page - Page of results being loaded. - * @returns {void} - */ - loadControls: function( themes, page ) { - var newThemeControls = [], - section = this; - - // Add controls for each theme. - _.each( themes, function( theme ) { - var themeControl = new api.controlConstructor.theme( section.params.action + '_theme_' + theme.id, { - type: 'theme', - section: section.params.id, - theme: theme, - priority: section.loaded + 1 - } ); - - api.control.add( themeControl ); - newThemeControls.push( themeControl ); - section.loaded = section.loaded + 1; - }); - - if ( 1 !== page ) { - Array.prototype.push.apply( section.screenshotQueue, newThemeControls ); // Add new themes to the screenshot queue. - } - }, - - /** - * Determines whether more themes should be loaded, and loads them. - * - * @since 4.9.0 - * @returns {void} - */ - loadMore: function() { - var section = this, container, bottom, threshold; - if ( ! section.fullyLoaded && ! section.loading ) { - container = section.container.closest( '.customize-themes-full-container' ); - - bottom = container.scrollTop() + container.height(); - threshold = container.prop( 'scrollHeight' ) - 3000; // Use a fixed distance to the bottom of loaded results to avoid unnecessarily loading results sooner when using a percentage of scroll distance. - - if ( bottom > threshold ) { - section.loadThemes(); - } - } - }, - - /** - * Event handler for search input that filters visible controls. - * - * @since 4.9.0 - * - * @param {string} term - The raw search input value. - * @returns {void} - */ - filterSearch: function( term ) { - var count = 0, - visible = false, - section = this, - noFilter = ( api.section.has( 'wporg_themes' ) && 'remote' !== section.params.filter_type ) ? '.no-themes-local' : '.no-themes', - controls = section.controls(), - terms; - - if ( section.loading ) { - return; - } - - // Standardize search term format and split into an array of individual words. - terms = term.toLowerCase().trim().replace( /-/g, ' ' ).split( ' ' ); - - _.each( controls, function( control ) { - visible = control.filter( terms ); // Shows/hides and sorts control based on the applicability of the search term. - if ( visible ) { - count = count + 1; - } - }); - - if ( 0 === count ) { - section.container.find( noFilter ).show(); - wp.a11y.speak( section.container.find( noFilter ).text() ); - } else { - section.container.find( noFilter ).hide(); - } - - section.renderScreenshots(); - api.reflowPaneContents(); - - // Update theme count. - section.updateCountDebounced( count ); - }, - - /** - * Event handler for search input that determines if the terms have changed and loads new controls as needed. - * - * @since 4.9.0 - * - * @param {wp.customize.ThemesSection} section - The current theme section, passed through the debouncer. - * @returns {void} - */ - checkTerm: function( section ) { - var newTerm; - if ( 'remote' === section.params.filter_type ) { - newTerm = section.contentContainer.find( '.wp-filter-search' ).val(); - if ( section.term !== newTerm.trim() ) { - section.initializeNewQuery( newTerm, section.tags ); - } - } - }, - - /** - * Check for filters checked in the feature filter list and initialize a new query. - * - * @since 4.9.0 - * - * @returns {void} - */ - filtersChecked: function() { - var section = this, - items = section.container.find( '.filter-group' ).find( ':checkbox' ), - tags = []; - - _.each( items.filter( ':checked' ), function( item ) { - tags.push( $( item ).prop( 'value' ) ); - }); - - // When no filters are checked, restore initial state. Update filter count. - if ( 0 === tags.length ) { - tags = ''; - section.contentContainer.find( '.feature-filter-toggle .filter-count-0' ).show(); - section.contentContainer.find( '.feature-filter-toggle .filter-count-filters' ).hide(); - } else { - section.contentContainer.find( '.feature-filter-toggle .theme-filter-count' ).text( tags.length ); - section.contentContainer.find( '.feature-filter-toggle .filter-count-0' ).hide(); - section.contentContainer.find( '.feature-filter-toggle .filter-count-filters' ).show(); - } - - // Check whether tags have changed, and either load or queue them. - if ( ! _.isEqual( section.tags, tags ) ) { - if ( section.loading ) { - section.nextTags = tags; - } else { - if ( 'remote' === section.params.filter_type ) { - section.initializeNewQuery( section.term, tags ); - } else if ( 'local' === section.params.filter_type ) { - section.filterSearch( tags.join( ' ' ) ); - } - } - } - }, - - /** - * Reset the current query and load new results. - * - * @since 4.9.0 - * - * @param {string} newTerm - New term. - * @param {Array} newTags - New tags. - * @returns {void} - */ - initializeNewQuery: function( newTerm, newTags ) { - var section = this; - - // Clear the controls in the section. - _.each( section.controls(), function( control ) { - control.container.remove(); - api.control.remove( control.id ); - }); - section.loaded = 0; - section.fullyLoaded = false; - section.screenshotQueue = null; - - // Run a new query, with loadThemes handling paging, etc. - if ( ! section.loading ) { - section.term = newTerm; - section.tags = newTags; - section.loadThemes(); - } else { - section.nextTerm = newTerm; // This will reload from loadThemes() with the newest term once the current batch is loaded. - section.nextTags = newTags; // This will reload from loadThemes() with the newest tags once the current batch is loaded. - } - if ( ! section.expanded() ) { - section.expand(); // Expand the section if it isn't expanded. - } - }, - - /** - * Render control's screenshot if the control comes into view. - * - * @since 4.2.0 - * - * @returns {void} - */ - renderScreenshots: function() { - var section = this; - - // Fill queue initially, or check for more if empty. - if ( null === section.screenshotQueue || 0 === section.screenshotQueue.length ) { - - // Add controls that haven't had their screenshots rendered. - section.screenshotQueue = _.filter( section.controls(), function( control ) { - return ! control.screenshotRendered; - }); - } - - // Are all screenshots rendered (for now)? - if ( ! section.screenshotQueue.length ) { - return; - } - - section.screenshotQueue = _.filter( section.screenshotQueue, function( control ) { - var $imageWrapper = control.container.find( '.theme-screenshot' ), - $image = $imageWrapper.find( 'img' ); - - if ( ! $image.length ) { - return false; - } - - if ( $image.is( ':hidden' ) ) { - return true; - } - - // Based on unveil.js. - var wt = section.$window.scrollTop(), - wb = wt + section.$window.height(), - et = $image.offset().top, - ih = $imageWrapper.height(), - eb = et + ih, - threshold = ih * 3, - inView = eb >= wt - threshold && et <= wb + threshold; - - if ( inView ) { - control.container.trigger( 'render-screenshot' ); - } - - // If the image is in view return false so it's cleared from the queue. - return ! inView; - } ); - }, - - /** - * Get visible count. - * - * @since 4.9.0 - * - * @returns {int} Visible count. - */ - getVisibleCount: function() { - return this.contentContainer.find( 'li.customize-control:visible' ).length; - }, - - /** - * Update the number of themes in the section. - * - * @since 4.9.0 - * - * @returns {void} - */ - updateCount: function( count ) { - var section = this, countEl, displayed; - - if ( ! count && 0 !== count ) { - count = section.getVisibleCount(); - } - - displayed = section.contentContainer.find( '.themes-displayed' ); - countEl = section.contentContainer.find( '.theme-count' ); - - if ( 0 === count ) { - countEl.text( '0' ); - } else { - - // Animate the count change for emphasis. - displayed.fadeOut( 180, function() { - countEl.text( count ); - displayed.fadeIn( 180 ); - } ); - wp.a11y.speak( api.settings.l10n.announceThemeCount.replace( '%d', count ) ); - } - }, - - /** - * Advance the modal to the next theme. - * - * @since 4.2.0 - * - * @returns {void} - */ - nextTheme: function () { - var section = this; - if ( section.getNextTheme() ) { - section.showDetails( section.getNextTheme(), function() { - section.overlay.find( '.right' ).focus(); - } ); - } - }, - - /** - * Get the next theme model. - * - * @since 4.2.0 - * - * @returns {wp.customize.ThemeControl|boolean} Next theme. - */ - getNextTheme: function () { - var section = this, control, nextControl, sectionControls, i; - control = api.control( section.params.action + '_theme_' + section.currentTheme ); - sectionControls = section.controls(); - i = _.indexOf( sectionControls, control ); - if ( -1 === i ) { - return false; - } - - nextControl = sectionControls[ i + 1 ]; - if ( ! nextControl ) { - return false; - } - return nextControl.params.theme; - }, - - /** - * Advance the modal to the previous theme. - * - * @since 4.2.0 - * @returns {void} - */ - previousTheme: function () { - var section = this; - if ( section.getPreviousTheme() ) { - section.showDetails( section.getPreviousTheme(), function() { - section.overlay.find( '.left' ).focus(); - } ); - } - }, - - /** - * Get the previous theme model. - * - * @since 4.2.0 - * @returns {wp.customize.ThemeControl|boolean} Previous theme. - */ - getPreviousTheme: function () { - var section = this, control, nextControl, sectionControls, i; - control = api.control( section.params.action + '_theme_' + section.currentTheme ); - sectionControls = section.controls(); - i = _.indexOf( sectionControls, control ); - if ( -1 === i ) { - return false; - } - - nextControl = sectionControls[ i - 1 ]; - if ( ! nextControl ) { - return false; - } - return nextControl.params.theme; - }, - - /** - * Disable buttons when we're viewing the first or last theme. - * - * @since 4.2.0 - * - * @returns {void} - */ - updateLimits: function () { - if ( ! this.getNextTheme() ) { - this.overlay.find( '.right' ).addClass( 'disabled' ); - } - if ( ! this.getPreviousTheme() ) { - this.overlay.find( '.left' ).addClass( 'disabled' ); - } - }, - - /** - * Load theme preview. - * - * @since 4.7.0 - * @access public - * - * @deprecated - * @param {string} themeId Theme ID. - * @returns {jQuery.promise} Promise. - */ - loadThemePreview: function( themeId ) { - return api.ThemesPanel.prototype.loadThemePreview.call( this, themeId ); - }, - - /** - * Render & show the theme details for a given theme model. - * - * @since 4.2.0 - * - * @param {object} theme - Theme. - * @param {Function} [callback] - Callback once the details have been shown. - * @returns {void} - */ - showDetails: function ( theme, callback ) { - var section = this, panel = api.panel( 'themes' ); - section.currentTheme = theme.id; - section.overlay.html( section.template( theme ) ) - .fadeIn( 'fast' ) - .focus(); - - function disableSwitchButtons() { - return ! panel.canSwitchTheme( theme.id ); - } - - // Temporary special function since supplying SFTP credentials does not work yet. See #42184. - function disableInstallButtons() { - return disableSwitchButtons() || false === api.settings.theme._canInstall || true === api.settings.theme._filesystemCredentialsNeeded; - } - - section.overlay.find( 'button.preview, button.preview-theme' ).toggleClass( 'disabled', disableSwitchButtons() ); - section.overlay.find( 'button.theme-install' ).toggleClass( 'disabled', disableInstallButtons() ); - - section.$body.addClass( 'modal-open' ); - section.containFocus( section.overlay ); - section.updateLimits(); - wp.a11y.speak( api.settings.l10n.announceThemeDetails.replace( '%s', theme.name ) ); - if ( callback ) { - callback(); - } - }, - - /** - * Close the theme details modal. - * - * @since 4.2.0 - * - * @returns {void} - */ - closeDetails: function () { - var section = this; - section.$body.removeClass( 'modal-open' ); - section.overlay.fadeOut( 'fast' ); - api.control( section.params.action + '_theme_' + section.currentTheme ).container.find( '.theme' ).focus(); - }, - - /** - * Keep tab focus within the theme details modal. - * - * @since 4.2.0 - * - * @param {jQuery} el - Element to contain focus. - * @returns {void} - */ - containFocus: function( el ) { - var tabbables; - - el.on( 'keydown', function( event ) { - - // Return if it's not the tab key - // When navigating with prev/next focus is already handled - if ( 9 !== event.keyCode ) { - return; - } - - // uses jQuery UI to get the tabbable elements - tabbables = $( ':tabbable', el ); - - // Keep focus within the overlay - if ( tabbables.last()[0] === event.target && ! event.shiftKey ) { - tabbables.first().focus(); - return false; - } else if ( tabbables.first()[0] === event.target && event.shiftKey ) { - tabbables.last().focus(); - return false; - } - }); - } - }); - - api.OuterSection = api.Section.extend(/** @lends wp.customize.OuterSection.prototype */{ - - /** - * Class wp.customize.OuterSection. - * - * Creates section outside of the sidebar, there is no ui to trigger collapse/expand so - * it would require custom handling. - * - * @constructs wp.customize.OuterSection - * @augments wp.customize.Section - * - * @since 4.9.0 - * - * @returns {void} - */ - initialize: function() { - var section = this; - section.containerParent = '#customize-outer-theme-controls'; - section.containerPaneParent = '.customize-outer-pane-parent'; - api.Section.prototype.initialize.apply( section, arguments ); - }, - - /** - * Overrides api.Section.prototype.onChangeExpanded to prevent collapse/expand effect - * on other sections and panels. - * - * @since 4.9.0 - * - * @param {Boolean} expanded - The expanded state to transition to. - * @param {Object} [args] - Args. - * @param {boolean} [args.unchanged] - Whether the state is already known to not be changed, and so short-circuit with calling completeCallback early. - * @param {Function} [args.completeCallback] - Function to call when the slideUp/slideDown has completed. - * @param {Object} [args.duration] - The duration for the animation. - */ - onChangeExpanded: function( expanded, args ) { - var section = this, - container = section.headContainer.closest( '.wp-full-overlay-sidebar-content' ), - content = section.contentContainer, - backBtn = content.find( '.customize-section-back' ), - sectionTitle = section.headContainer.find( '.accordion-section-title' ).first(), - body = $( document.body ), - expand, panel; - - body.toggleClass( 'outer-section-open', expanded ); - section.container.toggleClass( 'open', expanded ); - section.container.removeClass( 'busy' ); - api.section.each( function( _section ) { - if ( 'outer' === _section.params.type && _section.id !== section.id ) { - _section.container.removeClass( 'open' ); - } - } ); - - if ( expanded && ! content.hasClass( 'open' ) ) { - - if ( args.unchanged ) { - expand = args.completeCallback; - } else { - expand = $.proxy( function() { - section._animateChangeExpanded( function() { - sectionTitle.attr( 'tabindex', '-1' ); - backBtn.attr( 'tabindex', '0' ); - - backBtn.focus(); - content.css( 'top', '' ); - container.scrollTop( 0 ); - - if ( args.completeCallback ) { - args.completeCallback(); - } - } ); - - content.addClass( 'open' ); - }, this ); - } - - if ( section.panel() ) { - api.panel( section.panel() ).expand({ - duration: args.duration, - completeCallback: expand - }); - } else { - expand(); - } - - } else if ( ! expanded && content.hasClass( 'open' ) ) { - if ( section.panel() ) { - panel = api.panel( section.panel() ); - if ( panel.contentContainer.hasClass( 'skip-transition' ) ) { - panel.collapse(); - } - } - section._animateChangeExpanded( function() { - backBtn.attr( 'tabindex', '-1' ); - sectionTitle.attr( 'tabindex', '0' ); - - sectionTitle.focus(); - content.css( 'top', '' ); - - if ( args.completeCallback ) { - args.completeCallback(); - } - } ); - - content.removeClass( 'open' ); - - } else { - if ( args.completeCallback ) { - args.completeCallback(); - } - } - } - }); - - api.Panel = Container.extend(/** @lends wp.customize.Panel.prototype */{ - containerType: 'panel', - - /** - * @constructs wp.customize.Panel - * @augments wp.customize~Container - * - * @since 4.1.0 - * - * @param {string} id - The ID for the panel. - * @param {object} options - Object containing one property: params. - * @param {string} options.title - Title shown when panel is collapsed and expanded. - * @param {string} [options.description] - Description shown at the top of the panel. - * @param {number} [options.priority=100] - The sort priority for the panel. - * @param {string} [options.type=default] - The type of the panel. See wp.customize.panelConstructor. - * @param {string} [options.content] - The markup to be used for the panel container. If empty, a JS template is used. - * @param {boolean} [options.active=true] - Whether the panel is active or not. - * @param {object} [options.params] - Deprecated wrapper for the above properties. - */ - initialize: function ( id, options ) { - var panel = this, params; - params = options.params || options; - - // Look up the type if one was not supplied. - if ( ! params.type ) { - _.find( api.panelConstructor, function( Constructor, type ) { - if ( Constructor === panel.constructor ) { - params.type = type; - return true; - } - return false; - } ); - } - - Container.prototype.initialize.call( panel, id, params ); - - panel.embed(); - panel.deferred.embedded.done( function () { - panel.ready(); - }); - }, - - /** - * Embed the container in the DOM when any parent panel is ready. - * - * @since 4.1.0 - */ - embed: function () { - var panel = this, - container = $( '#customize-theme-controls' ), - parentContainer = $( '.customize-pane-parent' ); // @todo This should be defined elsewhere, and to be configurable - - if ( ! panel.headContainer.parent().is( parentContainer ) ) { - parentContainer.append( panel.headContainer ); - } - if ( ! panel.contentContainer.parent().is( panel.headContainer ) ) { - container.append( panel.contentContainer ); - } - panel.renderContent(); - - panel.deferred.embedded.resolve(); - }, - - /** - * @since 4.1.0 - */ - attachEvents: function () { - var meta, panel = this; - - // Expand/Collapse accordion sections on click. - panel.headContainer.find( '.accordion-section-title' ).on( 'click keydown', function( event ) { - if ( api.utils.isKeydownButNotEnterEvent( event ) ) { - return; - } - event.preventDefault(); // Keep this AFTER the key filter above - - if ( ! panel.expanded() ) { - panel.expand(); - } - }); - - // Close panel. - panel.container.find( '.customize-panel-back' ).on( 'click keydown', function( event ) { - if ( api.utils.isKeydownButNotEnterEvent( event ) ) { - return; - } - event.preventDefault(); // Keep this AFTER the key filter above - - if ( panel.expanded() ) { - panel.collapse(); - } - }); - - meta = panel.container.find( '.panel-meta:first' ); - - meta.find( '> .accordion-section-title .customize-help-toggle' ).on( 'click', function() { - if ( meta.hasClass( 'cannot-expand' ) ) { - return; - } - - var content = meta.find( '.customize-panel-description:first' ); - if ( meta.hasClass( 'open' ) ) { - meta.toggleClass( 'open' ); - content.slideUp( panel.defaultExpandedArguments.duration, function() { - content.trigger( 'toggled' ); - } ); - $( this ).attr( 'aria-expanded', false ); - } else { - content.slideDown( panel.defaultExpandedArguments.duration, function() { - content.trigger( 'toggled' ); - } ); - meta.toggleClass( 'open' ); - $( this ).attr( 'aria-expanded', true ); - } - }); - - }, - - /** - * Get the sections that are associated with this panel, sorted by their priority Value. - * - * @since 4.1.0 - * - * @returns {Array} - */ - sections: function () { - return this._children( 'panel', 'section' ); - }, - - /** - * Return whether this panel has any active sections. - * - * @since 4.1.0 - * - * @returns {boolean} Whether contextually active. - */ - isContextuallyActive: function () { - var panel = this, - sections = panel.sections(), - activeCount = 0; - _( sections ).each( function ( section ) { - if ( section.active() && section.isContextuallyActive() ) { - activeCount += 1; - } - } ); - return ( activeCount !== 0 ); - }, - - /** - * Update UI to reflect expanded state. - * - * @since 4.1.0 - * - * @param {Boolean} expanded - * @param {Object} args - * @param {Boolean} args.unchanged - * @param {Function} args.completeCallback - * @returns {void} - */ - onChangeExpanded: function ( expanded, args ) { - - // Immediately call the complete callback if there were no changes - if ( args.unchanged ) { - if ( args.completeCallback ) { - args.completeCallback(); - } - return; - } - - // Note: there is a second argument 'args' passed - var panel = this, - accordionSection = panel.contentContainer, - overlay = accordionSection.closest( '.wp-full-overlay' ), - container = accordionSection.closest( '.wp-full-overlay-sidebar-content' ), - topPanel = panel.headContainer.find( '.accordion-section-title' ), - backBtn = accordionSection.find( '.customize-panel-back' ), - childSections = panel.sections(), - skipTransition; - - if ( expanded && ! accordionSection.hasClass( 'current-panel' ) ) { - // Collapse any sibling sections/panels - api.section.each( function ( section ) { - if ( panel.id !== section.panel() ) { - section.collapse( { duration: 0 } ); - } - }); - api.panel.each( function ( otherPanel ) { - if ( panel !== otherPanel ) { - otherPanel.collapse( { duration: 0 } ); - } - }); - - if ( panel.params.autoExpandSoleSection && 1 === childSections.length && childSections[0].active.get() ) { - accordionSection.addClass( 'current-panel skip-transition' ); - overlay.addClass( 'in-sub-panel' ); - - childSections[0].expand( { - completeCallback: args.completeCallback - } ); - } else { - panel._animateChangeExpanded( function() { - topPanel.attr( 'tabindex', '-1' ); - backBtn.attr( 'tabindex', '0' ); - - backBtn.focus(); - accordionSection.css( 'top', '' ); - container.scrollTop( 0 ); - - if ( args.completeCallback ) { - args.completeCallback(); - } - } ); - - accordionSection.addClass( 'current-panel' ); - overlay.addClass( 'in-sub-panel' ); - } - - api.state( 'expandedPanel' ).set( panel ); - - } else if ( ! expanded && accordionSection.hasClass( 'current-panel' ) ) { - skipTransition = accordionSection.hasClass( 'skip-transition' ); - if ( ! skipTransition ) { - panel._animateChangeExpanded( function() { - topPanel.attr( 'tabindex', '0' ); - backBtn.attr( 'tabindex', '-1' ); - - topPanel.focus(); - accordionSection.css( 'top', '' ); - - if ( args.completeCallback ) { - args.completeCallback(); - } - } ); - } else { - accordionSection.removeClass( 'skip-transition' ); - } - - overlay.removeClass( 'in-sub-panel' ); - accordionSection.removeClass( 'current-panel' ); - if ( panel === api.state( 'expandedPanel' ).get() ) { - api.state( 'expandedPanel' ).set( false ); - } - } - }, - - /** - * Render the panel from its JS template, if it exists. - * - * The panel's container must already exist in the DOM. - * - * @since 4.3.0 - */ - renderContent: function () { - var template, - panel = this; - - // Add the content to the container. - if ( 0 !== $( '#tmpl-' + panel.templateSelector + '-content' ).length ) { - template = wp.template( panel.templateSelector + '-content' ); - } else { - template = wp.template( 'customize-panel-default-content' ); - } - if ( template && panel.headContainer ) { - panel.contentContainer.html( template( _.extend( - { id: panel.id }, - panel.params - ) ) ); - } - } - }); - - api.ThemesPanel = api.Panel.extend(/** @lends wp.customize.ThemsPanel.prototype */{ - - /** - * Class wp.customize.ThemesPanel. - * - * Custom section for themes that displays without the customize preview. - * - * @constructs wp.customize.ThemesPanel - * @augments wp.customize.Panel - * - * @since 4.9.0 - * - * @param {string} id - The ID for the panel. - * @param {object} options - Options. - * @returns {void} - */ - initialize: function( id, options ) { - var panel = this; - panel.installingThemes = []; - api.Panel.prototype.initialize.call( panel, id, options ); - }, - - /** - * Determine whether a given theme can be switched to, or in general. - * - * @since 4.9.0 - * - * @param {string} [slug] - Theme slug. - * @returns {boolean} Whether the theme can be switched to. - */ - canSwitchTheme: function canSwitchTheme( slug ) { - if ( slug && slug === api.settings.theme.stylesheet ) { - return true; - } - return 'publish' === api.state( 'selectedChangesetStatus' ).get() && ( '' === api.state( 'changesetStatus' ).get() || 'auto-draft' === api.state( 'changesetStatus' ).get() ); - }, - - /** - * Attach events. - * - * @since 4.9.0 - * @returns {void} - */ - attachEvents: function() { - var panel = this; - - // Attach regular panel events. - api.Panel.prototype.attachEvents.apply( panel ); - - // Temporary since supplying SFTP credentials does not work yet. See #42184 - if ( api.settings.theme._canInstall && api.settings.theme._filesystemCredentialsNeeded ) { - panel.notifications.add( new api.Notification( 'theme_install_unavailable', { - message: api.l10n.themeInstallUnavailable, - type: 'info', - dismissible: true - } ) ); - } - - function toggleDisabledNotifications() { - if ( panel.canSwitchTheme() ) { - panel.notifications.remove( 'theme_switch_unavailable' ); - } else { - panel.notifications.add( new api.Notification( 'theme_switch_unavailable', { - message: api.l10n.themePreviewUnavailable, - type: 'warning' - } ) ); - } - } - toggleDisabledNotifications(); - api.state( 'selectedChangesetStatus' ).bind( toggleDisabledNotifications ); - api.state( 'changesetStatus' ).bind( toggleDisabledNotifications ); - - // Collapse panel to customize the current theme. - panel.contentContainer.on( 'click', '.customize-theme', function() { - panel.collapse(); - }); - - // Toggle between filtering and browsing themes on mobile. - panel.contentContainer.on( 'click', '.customize-themes-section-title, .customize-themes-mobile-back', function() { - $( '.wp-full-overlay' ).toggleClass( 'showing-themes' ); - }); - - // Install (and maybe preview) a theme. - panel.contentContainer.on( 'click', '.theme-install', function( event ) { - panel.installTheme( event ); - }); - - // Update a theme. Theme cards have the class, the details modal has the id. - panel.contentContainer.on( 'click', '.update-theme, #update-theme', function( event ) { - - // #update-theme is a link. - event.preventDefault(); - event.stopPropagation(); - - panel.updateTheme( event ); - }); - - // Delete a theme. - panel.contentContainer.on( 'click', '.delete-theme', function( event ) { - panel.deleteTheme( event ); - }); - - _.bindAll( panel, 'installTheme', 'updateTheme' ); - }, - - /** - * Update UI to reflect expanded state - * - * @since 4.9.0 - * - * @param {Boolean} expanded - Expanded state. - * @param {Object} args - Args. - * @param {Boolean} args.unchanged - Whether or not the state changed. - * @param {Function} args.completeCallback - Callback to execute when the animation completes. - * @returns {void} - */ - onChangeExpanded: function( expanded, args ) { - var panel = this, overlay, sections, hasExpandedSection = false; - - // Expand/collapse the panel normally. - api.Panel.prototype.onChangeExpanded.apply( this, [ expanded, args ] ); - - // Immediately call the complete callback if there were no changes - if ( args.unchanged ) { - if ( args.completeCallback ) { - args.completeCallback(); - } - return; - } - - overlay = panel.headContainer.closest( '.wp-full-overlay' ); - - if ( expanded ) { - overlay - .addClass( 'in-themes-panel' ) - .delay( 200 ).find( '.customize-themes-full-container' ).addClass( 'animate' ); - - _.delay( function() { - overlay.addClass( 'themes-panel-expanded' ); - }, 200 ); - - // Automatically open the first section (except on small screens), if one isn't already expanded. - if ( 600 < window.innerWidth ) { - sections = panel.sections(); - _.each( sections, function( section ) { - if ( section.expanded() ) { - hasExpandedSection = true; - } - } ); - if ( ! hasExpandedSection && sections.length > 0 ) { - sections[0].expand(); - } - } - } else { - overlay - .removeClass( 'in-themes-panel themes-panel-expanded' ) - .find( '.customize-themes-full-container' ).removeClass( 'animate' ); - } - }, - - /** - * Install a theme via wp.updates. - * - * @since 4.9.0 - * - * @param {jQuery.Event} event - Event. - * @returns {jQuery.promise} Promise. - */ - installTheme: function( event ) { - var panel = this, preview, onInstallSuccess, slug = $( event.target ).data( 'slug' ), deferred = $.Deferred(), request; - preview = $( event.target ).hasClass( 'preview' ); - - // Temporary since supplying SFTP credentials does not work yet. See #42184. - if ( api.settings.theme._filesystemCredentialsNeeded ) { - deferred.reject({ - errorCode: 'theme_install_unavailable' - }); - return deferred.promise(); - } - - // Prevent loading a non-active theme preview when there is a drafted/scheduled changeset. - if ( ! panel.canSwitchTheme( slug ) ) { - deferred.reject({ - errorCode: 'theme_switch_unavailable' - }); - return deferred.promise(); - } - - // Theme is already being installed. - if ( _.contains( panel.installingThemes, slug ) ) { - deferred.reject({ - errorCode: 'theme_already_installing' - }); - return deferred.promise(); - } - - wp.updates.maybeRequestFilesystemCredentials( event ); - - onInstallSuccess = function( response ) { - var theme = false, themeControl; - if ( preview ) { - api.notifications.remove( 'theme_installing' ); - - panel.loadThemePreview( slug ); - - } else { - api.control.each( function( control ) { - if ( 'theme' === control.params.type && control.params.theme.id === response.slug ) { - theme = control.params.theme; // Used below to add theme control. - control.rerenderAsInstalled( true ); - } - }); - - // Don't add the same theme more than once. - if ( ! theme || api.control.has( 'installed_theme_' + theme.id ) ) { - deferred.resolve( response ); - return; - } - - // Add theme control to installed section. - theme.type = 'installed'; - themeControl = new api.controlConstructor.theme( 'installed_theme_' + theme.id, { - type: 'theme', - section: 'installed_themes', - theme: theme, - priority: 0 // Add all newly-installed themes to the top. - } ); - - api.control.add( themeControl ); - api.control( themeControl.id ).container.trigger( 'render-screenshot' ); - - // Close the details modal if it's open to the installed theme. - api.section.each( function( section ) { - if ( 'themes' === section.params.type ) { - if ( theme.id === section.currentTheme ) { // Don't close the modal if the user has navigated elsewhere. - section.closeDetails(); - } - } - }); - } - deferred.resolve( response ); - }; - - panel.installingThemes.push( slug ); // Note: we don't remove elements from installingThemes, since they shouldn't be installed again. - request = wp.updates.installTheme( { - slug: slug - } ); - - // Also preview the theme as the event is triggered on Install & Preview. - if ( preview ) { - api.notifications.add( new api.OverlayNotification( 'theme_installing', { - message: api.l10n.themeDownloading, - type: 'info', - loading: true - } ) ); - } - - request.done( onInstallSuccess ); - request.fail( function() { - api.notifications.remove( 'theme_installing' ); - } ); - - return deferred.promise(); - }, - - /** - * Load theme preview. - * - * @since 4.9.0 - * - * @param {string} themeId Theme ID. - * @returns {jQuery.promise} Promise. - */ - loadThemePreview: function( themeId ) { - var panel = this, deferred = $.Deferred(), onceProcessingComplete, urlParser, queryParams; - - // Prevent loading a non-active theme preview when there is a drafted/scheduled changeset. - if ( ! panel.canSwitchTheme( themeId ) ) { - deferred.reject({ - errorCode: 'theme_switch_unavailable' - }); - return deferred.promise(); - } - - urlParser = document.createElement( 'a' ); - urlParser.href = location.href; - queryParams = _.extend( - api.utils.parseQueryString( urlParser.search.substr( 1 ) ), - { - theme: themeId, - changeset_uuid: api.settings.changeset.uuid, - 'return': api.settings.url['return'] - } - ); - - // Include autosaved param to load autosave revision without prompting user to restore it. - if ( ! api.state( 'saved' ).get() ) { - queryParams.customize_autosaved = 'on'; - } - - urlParser.search = $.param( queryParams ); - - // Update loading message. Everything else is handled by reloading the page. - api.notifications.add( new api.OverlayNotification( 'theme_previewing', { - message: api.l10n.themePreviewWait, - type: 'info', - loading: true - } ) ); - - onceProcessingComplete = function() { - var request; - if ( api.state( 'processing' ).get() > 0 ) { - return; - } - - api.state( 'processing' ).unbind( onceProcessingComplete ); - - request = api.requestChangesetUpdate( {}, { autosave: true } ); - request.done( function() { - deferred.resolve(); - $( window ).off( 'beforeunload.customize-confirm' ); - location.replace( urlParser.href ); - } ); - request.fail( function() { - - // @todo Show notification regarding failure. - api.notifications.remove( 'theme_previewing' ); - - deferred.reject(); - } ); - }; - - if ( 0 === api.state( 'processing' ).get() ) { - onceProcessingComplete(); - } else { - api.state( 'processing' ).bind( onceProcessingComplete ); - } - - return deferred.promise(); - }, - - /** - * Update a theme via wp.updates. - * - * @since 4.9.0 - * - * @param {jQuery.Event} event - Event. - * @returns {void} - */ - updateTheme: function( event ) { - wp.updates.maybeRequestFilesystemCredentials( event ); - - $( document ).one( 'wp-theme-update-success', function( e, response ) { - - // Rerender the control to reflect the update. - api.control.each( function( control ) { - if ( 'theme' === control.params.type && control.params.theme.id === response.slug ) { - control.params.theme.hasUpdate = false; - control.params.theme.version = response.newVersion; - setTimeout( function() { - control.rerenderAsInstalled( true ); - }, 2000 ); - } - }); - } ); - - wp.updates.updateTheme( { - slug: $( event.target ).closest( '.notice' ).data( 'slug' ) - } ); - }, - - /** - * Delete a theme via wp.updates. - * - * @since 4.9.0 - * - * @param {jQuery.Event} event - Event. - * @returns {void} - */ - deleteTheme: function( event ) { - var theme, section; - theme = $( event.target ).data( 'slug' ); - section = api.section( 'installed_themes' ); - - event.preventDefault(); - - // Temporary since supplying SFTP credentials does not work yet. See #42184. - if ( api.settings.theme._filesystemCredentialsNeeded ) { - return; - } - - // Confirmation dialog for deleting a theme. - if ( ! window.confirm( api.settings.l10n.confirmDeleteTheme ) ) { - return; - } - - wp.updates.maybeRequestFilesystemCredentials( event ); - - $( document ).one( 'wp-theme-delete-success', function() { - var control = api.control( 'installed_theme_' + theme ); - - // Remove theme control. - control.container.remove(); - api.control.remove( control.id ); - - // Update installed count. - section.loaded = section.loaded - 1; - section.updateCount(); - - // Rerender any other theme controls as uninstalled. - api.control.each( function( control ) { - if ( 'theme' === control.params.type && control.params.theme.id === theme ) { - control.rerenderAsInstalled( false ); - } - }); - } ); - - wp.updates.deleteTheme( { - slug: theme - } ); - - // Close modal and focus the section. - section.closeDetails(); - section.focus(); - } - }); - - api.Control = api.Class.extend(/** @lends wp.customize.Control.prototype */{ - defaultActiveArguments: { duration: 'fast', completeCallback: $.noop }, - - /** - * Default params. - * - * @since 4.9.0 - * @var {object} - */ - defaults: { - label: '', - description: '', - active: true, - priority: 10 - }, - - /** - * A Customizer Control. - * - * A control provides a UI element that allows a user to modify a Customizer Setting. - * - * @see PHP class WP_Customize_Control. - * - * @constructs wp.customize.Control - * @augments wp.customize.Class - * - * @borrows wp.customize~focus as this#focus - * @borrows wp.customize~Container#activate as this#activate - * @borrows wp.customize~Container#deactivate as this#deactivate - * @borrows wp.customize~Container#_toggleActive as this#_toggleActive - * - * @param {string} id - Unique identifier for the control instance. - * @param {object} options - Options hash for the control instance. - * @param {object} options.type - Type of control (e.g. text, radio, dropdown-pages, etc.) - * @param {string} [options.content] - The HTML content for the control or at least its container. This should normally be left blank and instead supplying a templateId. - * @param {string} [options.templateId] - Template ID for control's content. - * @param {string} [options.priority=10] - Order of priority to show the control within the section. - * @param {string} [options.active=true] - Whether the control is active. - * @param {string} options.section - The ID of the section the control belongs to. - * @param {mixed} [options.setting] - The ID of the main setting or an instance of this setting. - * @param {mixed} options.settings - An object with keys (e.g. default) that maps to setting IDs or Setting/Value objects, or an array of setting IDs or Setting/Value objects. - * @param {mixed} options.settings.default - The ID of the setting the control relates to. - * @param {string} options.settings.data - @todo Is this used? - * @param {string} options.label - Label. - * @param {string} options.description - Description. - * @param {number} [options.instanceNumber] - Order in which this instance was created in relation to other instances. - * @param {object} [options.params] - Deprecated wrapper for the above properties. - * @returns {void} - */ - initialize: function( id, options ) { - var control = this, deferredSettingIds = [], settings, gatherSettings; - - control.params = _.extend( - {}, - control.defaults, - control.params || {}, // In case sub-class already defines. - options.params || options || {} // The options.params property is deprecated, but it is checked first for back-compat. - ); - - if ( ! api.Control.instanceCounter ) { - api.Control.instanceCounter = 0; - } - api.Control.instanceCounter++; - if ( ! control.params.instanceNumber ) { - control.params.instanceNumber = api.Control.instanceCounter; - } - - // Look up the type if one was not supplied. - if ( ! control.params.type ) { - _.find( api.controlConstructor, function( Constructor, type ) { - if ( Constructor === control.constructor ) { - control.params.type = type; - return true; - } - return false; - } ); - } - - if ( ! control.params.content ) { - control.params.content = $( '<li></li>', { - id: 'customize-control-' + id.replace( /]/g, '' ).replace( /\[/g, '-' ), - 'class': 'customize-control customize-control-' + control.params.type - } ); - } - - control.id = id; - control.selector = '#customize-control-' + id.replace( /\]/g, '' ).replace( /\[/g, '-' ); // Deprecated, likely dead code from time before #28709. - if ( control.params.content ) { - control.container = $( control.params.content ); - } else { - control.container = $( control.selector ); // Likely dead, per above. See #28709. - } - - if ( control.params.templateId ) { - control.templateSelector = control.params.templateId; - } else { - control.templateSelector = 'customize-control-' + control.params.type + '-content'; - } - - control.deferred = _.extend( control.deferred || {}, { - embedded: new $.Deferred() - } ); - control.section = new api.Value(); - control.priority = new api.Value(); - control.active = new api.Value(); - control.activeArgumentsQueue = []; - control.notifications = new api.Notifications({ - alt: control.altNotice - }); - - control.elements = []; - - control.active.bind( function ( active ) { - var args = control.activeArgumentsQueue.shift(); - args = $.extend( {}, control.defaultActiveArguments, args ); - control.onChangeActive( active, args ); - } ); - - control.section.set( control.params.section ); - control.priority.set( isNaN( control.params.priority ) ? 10 : control.params.priority ); - control.active.set( control.params.active ); - - api.utils.bubbleChildValueChanges( control, [ 'section', 'priority', 'active' ] ); - - control.settings = {}; - - settings = {}; - if ( control.params.setting ) { - settings['default'] = control.params.setting; - } - _.extend( settings, control.params.settings ); - - // Note: Settings can be an array or an object, with values being either setting IDs or Setting (or Value) objects. - _.each( settings, function( value, key ) { - var setting; - if ( _.isObject( value ) && _.isFunction( value.extended ) && value.extended( api.Value ) ) { - control.settings[ key ] = value; - } else if ( _.isString( value ) ) { - setting = api( value ); - if ( setting ) { - control.settings[ key ] = setting; - } else { - deferredSettingIds.push( value ); - } - } - } ); - - gatherSettings = function() { - - // Fill-in all resolved settings. - _.each( settings, function ( settingId, key ) { - if ( ! control.settings[ key ] && _.isString( settingId ) ) { - control.settings[ key ] = api( settingId ); - } - } ); - - // Make sure settings passed as array gets associated with default. - if ( control.settings[0] && ! control.settings['default'] ) { - control.settings['default'] = control.settings[0]; - } - - // Identify the main setting. - control.setting = control.settings['default'] || null; - - control.linkElements(); // Link initial elements present in server-rendered content. - control.embed(); - }; - - if ( 0 === deferredSettingIds.length ) { - gatherSettings(); - } else { - api.apply( api, deferredSettingIds.concat( gatherSettings ) ); - } - - // After the control is embedded on the page, invoke the "ready" method. - control.deferred.embedded.done( function () { - control.linkElements(); // Link any additional elements after template is rendered by renderContent(). - control.setupNotifications(); - control.ready(); - }); - }, - - /** - * Link elements between settings and inputs. - * - * @since 4.7.0 - * @access public - * - * @returns {void} - */ - linkElements: function () { - var control = this, nodes, radios, element; - - nodes = control.container.find( '[data-customize-setting-link], [data-customize-setting-key-link]' ); - radios = {}; - - nodes.each( function () { - var node = $( this ), name, setting; - - if ( node.data( 'customizeSettingLinked' ) ) { - return; - } - node.data( 'customizeSettingLinked', true ); // Prevent re-linking element. - - if ( node.is( ':radio' ) ) { - name = node.prop( 'name' ); - if ( radios[name] ) { - return; - } - - radios[name] = true; - node = nodes.filter( '[name="' + name + '"]' ); - } - - // Let link by default refer to setting ID. If it doesn't exist, fallback to looking up by setting key. - if ( node.data( 'customizeSettingLink' ) ) { - setting = api( node.data( 'customizeSettingLink' ) ); - } else if ( node.data( 'customizeSettingKeyLink' ) ) { - setting = control.settings[ node.data( 'customizeSettingKeyLink' ) ]; - } - - if ( setting ) { - element = new api.Element( node ); - control.elements.push( element ); - element.sync( setting ); - element.set( setting() ); - } - } ); - }, - - /** - * Embed the control into the page. - */ - embed: function () { - var control = this, - inject; - - // Watch for changes to the section state - inject = function ( sectionId ) { - var parentContainer; - if ( ! sectionId ) { // @todo allow a control to be embedded without a section, for instance a control embedded in the front end. - return; - } - // Wait for the section to be registered - api.section( sectionId, function ( section ) { - // Wait for the section to be ready/initialized - section.deferred.embedded.done( function () { - parentContainer = ( section.contentContainer.is( 'ul' ) ) ? section.contentContainer : section.contentContainer.find( 'ul:first' ); - if ( ! control.container.parent().is( parentContainer ) ) { - parentContainer.append( control.container ); - control.renderContent(); - } - control.deferred.embedded.resolve(); - }); - }); - }; - control.section.bind( inject ); - inject( control.section.get() ); - }, - - /** - * Triggered when the control's markup has been injected into the DOM. - * - * @returns {void} - */ - ready: function() { - var control = this, newItem; - if ( 'dropdown-pages' === control.params.type && control.params.allow_addition ) { - newItem = control.container.find( '.new-content-item' ); - newItem.hide(); // Hide in JS to preserve flex display when showing. - control.container.on( 'click', '.add-new-toggle', function( e ) { - $( e.currentTarget ).slideUp( 180 ); - newItem.slideDown( 180 ); - newItem.find( '.create-item-input' ).focus(); - }); - control.container.on( 'click', '.add-content', function() { - control.addNewPage(); - }); - control.container.on( 'keydown', '.create-item-input', function( e ) { - if ( 13 === e.which ) { // Enter - control.addNewPage(); - } - }); - } - }, - - /** - * Get the element inside of a control's container that contains the validation error message. - * - * Control subclasses may override this to return the proper container to render notifications into. - * Injects the notification container for existing controls that lack the necessary container, - * including special handling for nav menu items and widgets. - * - * @since 4.6.0 - * @returns {jQuery} Setting validation message element. - */ - getNotificationsContainerElement: function() { - var control = this, controlTitle, notificationsContainer; - - notificationsContainer = control.container.find( '.customize-control-notifications-container:first' ); - if ( notificationsContainer.length ) { - return notificationsContainer; - } - - notificationsContainer = $( '<div class="customize-control-notifications-container"></div>' ); - - if ( control.container.hasClass( 'customize-control-nav_menu_item' ) ) { - control.container.find( '.menu-item-settings:first' ).prepend( notificationsContainer ); - } else if ( control.container.hasClass( 'customize-control-widget_form' ) ) { - control.container.find( '.widget-inside:first' ).prepend( notificationsContainer ); - } else { - controlTitle = control.container.find( '.customize-control-title' ); - if ( controlTitle.length ) { - controlTitle.after( notificationsContainer ); - } else { - control.container.prepend( notificationsContainer ); - } - } - return notificationsContainer; - }, - - /** - * Set up notifications. - * - * @since 4.9.0 - * @returns {void} - */ - setupNotifications: function() { - var control = this, renderNotificationsIfVisible, onSectionAssigned; - - // Add setting notifications to the control notification. - _.each( control.settings, function( setting ) { - if ( ! setting.notifications ) { - return; - } - setting.notifications.bind( 'add', function( settingNotification ) { - var params = _.extend( - {}, - settingNotification, - { - setting: setting.id - } - ); - control.notifications.add( new api.Notification( setting.id + ':' + settingNotification.code, params ) ); - } ); - setting.notifications.bind( 'remove', function( settingNotification ) { - control.notifications.remove( setting.id + ':' + settingNotification.code ); - } ); - } ); - - renderNotificationsIfVisible = function() { - var sectionId = control.section(); - if ( ! sectionId || ( api.section.has( sectionId ) && api.section( sectionId ).expanded() ) ) { - control.notifications.render(); - } - }; - - control.notifications.bind( 'rendered', function() { - var notifications = control.notifications.get(); - control.container.toggleClass( 'has-notifications', 0 !== notifications.length ); - control.container.toggleClass( 'has-error', 0 !== _.where( notifications, { type: 'error' } ).length ); - } ); - - onSectionAssigned = function( newSectionId, oldSectionId ) { - if ( oldSectionId && api.section.has( oldSectionId ) ) { - api.section( oldSectionId ).expanded.unbind( renderNotificationsIfVisible ); - } - if ( newSectionId ) { - api.section( newSectionId, function( section ) { - section.expanded.bind( renderNotificationsIfVisible ); - renderNotificationsIfVisible(); - }); - } - }; - - control.section.bind( onSectionAssigned ); - onSectionAssigned( control.section.get() ); - control.notifications.bind( 'change', _.debounce( renderNotificationsIfVisible ) ); - }, - - /** - * Render notifications. - * - * Renders the `control.notifications` into the control's container. - * Control subclasses may override this method to do their own handling - * of rendering notifications. - * - * @deprecated in favor of `control.notifications.render()` - * @since 4.6.0 - * @this {wp.customize.Control} - */ - renderNotifications: function() { - var control = this, container, notifications, hasError = false; - - if ( 'undefined' !== typeof console && console.warn ) { - console.warn( '[DEPRECATED] wp.customize.Control.prototype.renderNotifications() is deprecated in favor of instantating a wp.customize.Notifications and calling its render() method.' ); - } - - container = control.getNotificationsContainerElement(); - if ( ! container || ! container.length ) { - return; - } - notifications = []; - control.notifications.each( function( notification ) { - notifications.push( notification ); - if ( 'error' === notification.type ) { - hasError = true; - } - } ); - - if ( 0 === notifications.length ) { - container.stop().slideUp( 'fast' ); - } else { - container.stop().slideDown( 'fast', null, function() { - $( this ).css( 'height', 'auto' ); - } ); - } - - if ( ! control.notificationsTemplate ) { - control.notificationsTemplate = wp.template( 'customize-control-notifications' ); - } - - control.container.toggleClass( 'has-notifications', 0 !== notifications.length ); - control.container.toggleClass( 'has-error', hasError ); - container.empty().append( $.trim( - control.notificationsTemplate( { notifications: notifications, altNotice: Boolean( control.altNotice ) } ) - ) ); - }, - - /** - * Normal controls do not expand, so just expand its parent - * - * @param {Object} [params] - */ - expand: function ( params ) { - api.section( this.section() ).expand( params ); - }, - - /* - * Documented using @borrows in the constructor. - */ - focus: focus, - - /** - * Update UI in response to a change in the control's active state. - * This does not change the active state, it merely handles the behavior - * for when it does change. - * - * @since 4.1.0 - * - * @param {Boolean} active - * @param {Object} args - * @param {Number} args.duration - * @param {Function} args.completeCallback - */ - onChangeActive: function ( active, args ) { - if ( args.unchanged ) { - if ( args.completeCallback ) { - args.completeCallback(); - } - return; - } - - if ( ! $.contains( document, this.container[0] ) ) { - // jQuery.fn.slideUp is not hiding an element if it is not in the DOM - this.container.toggle( active ); - if ( args.completeCallback ) { - args.completeCallback(); - } - } else if ( active ) { - this.container.slideDown( args.duration, args.completeCallback ); - } else { - this.container.slideUp( args.duration, args.completeCallback ); - } - }, - - /** - * @deprecated 4.1.0 Use this.onChangeActive() instead. - */ - toggle: function ( active ) { - return this.onChangeActive( active, this.defaultActiveArguments ); - }, - - /* - * Documented using @borrows in the constructor - */ - activate: Container.prototype.activate, - - /* - * Documented using @borrows in the constructor - */ - deactivate: Container.prototype.deactivate, - - /* - * Documented using @borrows in the constructor - */ - _toggleActive: Container.prototype._toggleActive, - - // @todo This function appears to be dead code and can be removed. - dropdownInit: function() { - var control = this, - statuses = this.container.find('.dropdown-status'), - params = this.params, - toggleFreeze = false, - update = function( to ) { - if ( 'string' === typeof to && params.statuses && params.statuses[ to ] ) { - statuses.html( params.statuses[ to ] ).show(); - } else { - statuses.hide(); - } - }; - - // Support the .dropdown class to open/close complex elements - this.container.on( 'click keydown', '.dropdown', function( event ) { - if ( api.utils.isKeydownButNotEnterEvent( event ) ) { - return; - } - - event.preventDefault(); - - if ( ! toggleFreeze ) { - control.container.toggleClass( 'open' ); - } - - if ( control.container.hasClass( 'open' ) ) { - control.container.parent().parent().find( 'li.library-selected' ).focus(); - } - - // Don't want to fire focus and click at same time - toggleFreeze = true; - setTimeout(function () { - toggleFreeze = false; - }, 400); - }); - - this.setting.bind( update ); - update( this.setting() ); - }, - - /** - * Render the control from its JS template, if it exists. - * - * The control's container must already exist in the DOM. - * - * @since 4.1.0 - */ - renderContent: function () { - var control = this, template, standardTypes, templateId, sectionId; - - standardTypes = [ - 'button', - 'checkbox', - 'date', - 'datetime-local', - 'email', - 'month', - 'number', - 'password', - 'radio', - 'range', - 'search', - 'select', - 'tel', - 'time', - 'text', - 'textarea', - 'week', - 'url' - ]; - - templateId = control.templateSelector; - - // Use default content template when a standard HTML type is used, there isn't a more specific template existing, and the control container is empty. - if ( templateId === 'customize-control-' + control.params.type + '-content' && - _.contains( standardTypes, control.params.type ) && - ! document.getElementById( 'tmpl-' + templateId ) && - 0 === control.container.children().length ) - { - templateId = 'customize-control-default-content'; - } - - // Replace the container element's content with the control. - if ( document.getElementById( 'tmpl-' + templateId ) ) { - template = wp.template( templateId ); - if ( template && control.container ) { - control.container.html( template( control.params ) ); - } - } - - // Re-render notifications after content has been re-rendered. - control.notifications.container = control.getNotificationsContainerElement(); - sectionId = control.section(); - if ( ! sectionId || ( api.section.has( sectionId ) && api.section( sectionId ).expanded() ) ) { - control.notifications.render(); - } - }, - - /** - * Add a new page to a dropdown-pages control reusing menus code for this. - * - * @since 4.7.0 - * @access private - * @returns {void} - */ - addNewPage: function () { - var control = this, promise, toggle, container, input, title, select; - - if ( 'dropdown-pages' !== control.params.type || ! control.params.allow_addition || ! api.Menus ) { - return; - } - - toggle = control.container.find( '.add-new-toggle' ); - container = control.container.find( '.new-content-item' ); - input = control.container.find( '.create-item-input' ); - title = input.val(); - select = control.container.find( 'select' ); - - if ( ! title ) { - input.addClass( 'invalid' ); - return; - } - - input.removeClass( 'invalid' ); - input.attr( 'disabled', 'disabled' ); - - // The menus functions add the page, publish when appropriate, and also add the new page to the dropdown-pages controls. - promise = api.Menus.insertAutoDraftPost( { - post_title: title, - post_type: 'page' - } ); - promise.done( function( data ) { - var availableItem, $content, itemTemplate; - - // Prepare the new page as an available menu item. - // See api.Menus.submitNew(). - availableItem = new api.Menus.AvailableItemModel( { - 'id': 'post-' + data.post_id, // Used for available menu item Backbone models. - 'title': title, - 'type': 'post_type', - 'type_label': api.Menus.data.l10n.page_label, - 'object': 'page', - 'object_id': data.post_id, - 'url': data.url - } ); - - // Add the new item to the list of available menu items. - api.Menus.availableMenuItemsPanel.collection.add( availableItem ); - $content = $( '#available-menu-items-post_type-page' ).find( '.available-menu-items-list' ); - itemTemplate = wp.template( 'available-menu-item' ); - $content.prepend( itemTemplate( availableItem.attributes ) ); - - // Focus the select control. - select.focus(); - control.setting.set( String( data.post_id ) ); // Triggers a preview refresh and updates the setting. - - // Reset the create page form. - container.slideUp( 180 ); - toggle.slideDown( 180 ); - } ); - promise.always( function() { - input.val( '' ).removeAttr( 'disabled' ); - } ); - } - }); - - /** - * A colorpicker control. - * - * @class wp.customize.ColorControl - * @augments wp.customize.Control - */ - api.ColorControl = api.Control.extend(/** @lends wp.customize.ColorControl.prototype */{ - ready: function() { - var control = this, - isHueSlider = this.params.mode === 'hue', - updating = false, - picker; - - if ( isHueSlider ) { - picker = this.container.find( '.color-picker-hue' ); - picker.val( control.setting() ).wpColorPicker({ - change: function( event, ui ) { - updating = true; - control.setting( ui.color.h() ); - updating = false; - } - }); - } else { - picker = this.container.find( '.color-picker-hex' ); - picker.val( control.setting() ).wpColorPicker({ - change: function() { - updating = true; - control.setting.set( picker.wpColorPicker( 'color' ) ); - updating = false; - }, - clear: function() { - updating = true; - control.setting.set( '' ); - updating = false; - } - }); - } - - control.setting.bind( function ( value ) { - // Bail if the update came from the control itself. - if ( updating ) { - return; - } - picker.val( value ); - picker.wpColorPicker( 'color', value ); - } ); - - // Collapse color picker when hitting Esc instead of collapsing the current section. - control.container.on( 'keydown', function( event ) { - var pickerContainer; - if ( 27 !== event.which ) { // Esc. - return; - } - pickerContainer = control.container.find( '.wp-picker-container' ); - if ( pickerContainer.hasClass( 'wp-picker-active' ) ) { - picker.wpColorPicker( 'close' ); - control.container.find( '.wp-color-result' ).focus(); - event.stopPropagation(); // Prevent section from being collapsed. - } - } ); - } - }); - - /** - * A control that implements the media modal. - * - * @class wp.customize.MediaControl - * @augments wp.customize.Control - */ - api.MediaControl = api.Control.extend(/** @lends wp.customize.MediaControl.prototype */{ - - /** - * When the control's DOM structure is ready, - * set up internal event bindings. - */ - ready: function() { - var control = this; - // Shortcut so that we don't have to use _.bind every time we add a callback. - _.bindAll( control, 'restoreDefault', 'removeFile', 'openFrame', 'select', 'pausePlayer' ); - - // Bind events, with delegation to facilitate re-rendering. - control.container.on( 'click keydown', '.upload-button', control.openFrame ); - control.container.on( 'click keydown', '.upload-button', control.pausePlayer ); - control.container.on( 'click keydown', '.thumbnail-image img', control.openFrame ); - control.container.on( 'click keydown', '.default-button', control.restoreDefault ); - control.container.on( 'click keydown', '.remove-button', control.pausePlayer ); - control.container.on( 'click keydown', '.remove-button', control.removeFile ); - control.container.on( 'click keydown', '.remove-button', control.cleanupPlayer ); - - // Resize the player controls when it becomes visible (ie when section is expanded) - api.section( control.section() ).container - .on( 'expanded', function() { - if ( control.player ) { - control.player.setControlsSize(); - } - }) - .on( 'collapsed', function() { - control.pausePlayer(); - }); - - /** - * Set attachment data and render content. - * - * Note that BackgroundImage.prototype.ready applies this ready method - * to itself. Since BackgroundImage is an UploadControl, the value - * is the attachment URL instead of the attachment ID. In this case - * we skip fetching the attachment data because we have no ID available, - * and it is the responsibility of the UploadControl to set the control's - * attachmentData before calling the renderContent method. - * - * @param {number|string} value Attachment - */ - function setAttachmentDataAndRenderContent( value ) { - var hasAttachmentData = $.Deferred(); - - if ( control.extended( api.UploadControl ) ) { - hasAttachmentData.resolve(); - } else { - value = parseInt( value, 10 ); - if ( _.isNaN( value ) || value <= 0 ) { - delete control.params.attachment; - hasAttachmentData.resolve(); - } else if ( control.params.attachment && control.params.attachment.id === value ) { - hasAttachmentData.resolve(); - } - } - - // Fetch the attachment data. - if ( 'pending' === hasAttachmentData.state() ) { - wp.media.attachment( value ).fetch().done( function() { - control.params.attachment = this.attributes; - hasAttachmentData.resolve(); - - // Send attachment information to the preview for possible use in `postMessage` transport. - wp.customize.previewer.send( control.setting.id + '-attachment-data', this.attributes ); - } ); - } - - hasAttachmentData.done( function() { - control.renderContent(); - } ); - } - - // Ensure attachment data is initially set (for dynamically-instantiated controls). - setAttachmentDataAndRenderContent( control.setting() ); - - // Update the attachment data and re-render the control when the setting changes. - control.setting.bind( setAttachmentDataAndRenderContent ); - }, - - pausePlayer: function () { - this.player && this.player.pause(); - }, - - cleanupPlayer: function () { - this.player && wp.media.mixin.removePlayer( this.player ); - }, - - /** - * Open the media modal. - */ - openFrame: function( event ) { - if ( api.utils.isKeydownButNotEnterEvent( event ) ) { - return; - } - - event.preventDefault(); - - if ( ! this.frame ) { - this.initFrame(); - } - - this.frame.open(); - }, - - /** - * Create a media modal select frame, and store it so the instance can be reused when needed. - */ - initFrame: function() { - this.frame = wp.media({ - button: { - text: this.params.button_labels.frame_button - }, - states: [ - new wp.media.controller.Library({ - title: this.params.button_labels.frame_title, - library: wp.media.query({ type: this.params.mime_type }), - multiple: false, - date: false - }) - ] - }); - - // When a file is selected, run a callback. - this.frame.on( 'select', this.select ); - }, - - /** - * Callback handler for when an attachment is selected in the media modal. - * Gets the selected image information, and sets it within the control. - */ - select: function() { - // Get the attachment from the modal frame. - var node, - attachment = this.frame.state().get( 'selection' ).first().toJSON(), - mejsSettings = window._wpmejsSettings || {}; - - this.params.attachment = attachment; - - // Set the Customizer setting; the callback takes care of rendering. - this.setting( attachment.id ); - node = this.container.find( 'audio, video' ).get(0); - - // Initialize audio/video previews. - if ( node ) { - this.player = new MediaElementPlayer( node, mejsSettings ); - } else { - this.cleanupPlayer(); - } - }, - - /** - * Reset the setting to the default value. - */ - restoreDefault: function( event ) { - if ( api.utils.isKeydownButNotEnterEvent( event ) ) { - return; - } - event.preventDefault(); - - this.params.attachment = this.params.defaultAttachment; - this.setting( this.params.defaultAttachment.url ); - }, - - /** - * Called when the "Remove" link is clicked. Empties the setting. - * - * @param {object} event jQuery Event object - */ - removeFile: function( event ) { - if ( api.utils.isKeydownButNotEnterEvent( event ) ) { - return; - } - event.preventDefault(); - - this.params.attachment = {}; - this.setting( '' ); - this.renderContent(); // Not bound to setting change when emptying. - } - }); - - /** - * An upload control, which utilizes the media modal. - * - * @class wp.customize.UploadControl - * @augments wp.customize.MediaControl - */ - api.UploadControl = api.MediaControl.extend(/** @lends wp.customize.UploadControl.prototype */{ - - /** - * Callback handler for when an attachment is selected in the media modal. - * Gets the selected image information, and sets it within the control. - */ - select: function() { - // Get the attachment from the modal frame. - var node, - attachment = this.frame.state().get( 'selection' ).first().toJSON(), - mejsSettings = window._wpmejsSettings || {}; - - this.params.attachment = attachment; - - // Set the Customizer setting; the callback takes care of rendering. - this.setting( attachment.url ); - node = this.container.find( 'audio, video' ).get(0); - - // Initialize audio/video previews. - if ( node ) { - this.player = new MediaElementPlayer( node, mejsSettings ); - } else { - this.cleanupPlayer(); - } - }, - - // @deprecated - success: function() {}, - - // @deprecated - removerVisibility: function() {} - }); - - /** - * A control for uploading images. - * - * This control no longer needs to do anything more - * than what the upload control does in JS. - * - * @class wp.customize.ImageControl - * @augments wp.customize.UploadControl - */ - api.ImageControl = api.UploadControl.extend(/** @lends wp.customize.ImageControl.prototype */{ - // @deprecated - thumbnailSrc: function() {} - }); - - /** - * A control for uploading background images. - * - * @class wp.customize.BackgroundControl - * @augments wp.customize.UploadControl - */ - api.BackgroundControl = api.UploadControl.extend(/** @lends wp.customize.BackgroundControl.prototype */{ - - /** - * When the control's DOM structure is ready, - * set up internal event bindings. - */ - ready: function() { - api.UploadControl.prototype.ready.apply( this, arguments ); - }, - - /** - * Callback handler for when an attachment is selected in the media modal. - * Does an additional AJAX request for setting the background context. - */ - select: function() { - api.UploadControl.prototype.select.apply( this, arguments ); - - wp.ajax.post( 'custom-background-add', { - nonce: _wpCustomizeBackground.nonces.add, - wp_customize: 'on', - customize_theme: api.settings.theme.stylesheet, - attachment_id: this.params.attachment.id - } ); - } - }); - - /** - * A control for positioning a background image. - * - * @since 4.7.0 - * - * @class wp.customize.BackgroundPositionControl - * @augments wp.customize.Control - */ - api.BackgroundPositionControl = api.Control.extend(/** @lends wp.customize.BackgroundPositionControl.prototype */{ - - /** - * Set up control UI once embedded in DOM and settings are created. - * - * @since 4.7.0 - * @access public - */ - ready: function() { - var control = this, updateRadios; - - control.container.on( 'change', 'input[name="background-position"]', function() { - var position = $( this ).val().split( ' ' ); - control.settings.x( position[0] ); - control.settings.y( position[1] ); - } ); - - updateRadios = _.debounce( function() { - var x, y, radioInput, inputValue; - x = control.settings.x.get(); - y = control.settings.y.get(); - inputValue = String( x ) + ' ' + String( y ); - radioInput = control.container.find( 'input[name="background-position"][value="' + inputValue + '"]' ); - radioInput.click(); - } ); - control.settings.x.bind( updateRadios ); - control.settings.y.bind( updateRadios ); - - updateRadios(); // Set initial UI. - } - } ); - - /** - * A control for selecting and cropping an image. - * - * @class wp.customize.CroppedImageControl - * @augments wp.customize.MediaControl - */ - api.CroppedImageControl = api.MediaControl.extend(/** @lends wp.customize.CroppedImageControl.prototype */{ - - /** - * Open the media modal to the library state. - */ - openFrame: function( event ) { - if ( api.utils.isKeydownButNotEnterEvent( event ) ) { - return; - } - - this.initFrame(); - this.frame.setState( 'library' ).open(); - }, - - /** - * Create a media modal select frame, and store it so the instance can be reused when needed. - */ - initFrame: function() { - var l10n = _wpMediaViewsL10n; - - this.frame = wp.media({ - button: { - text: l10n.select, - close: false - }, - states: [ - new wp.media.controller.Library({ - title: this.params.button_labels.frame_title, - library: wp.media.query({ type: 'image' }), - multiple: false, - date: false, - priority: 20, - suggestedWidth: this.params.width, - suggestedHeight: this.params.height - }), - new wp.media.controller.CustomizeImageCropper({ - imgSelectOptions: this.calculateImageSelectOptions, - control: this - }) - ] - }); - - this.frame.on( 'select', this.onSelect, this ); - this.frame.on( 'cropped', this.onCropped, this ); - this.frame.on( 'skippedcrop', this.onSkippedCrop, this ); - }, - - /** - * After an image is selected in the media modal, switch to the cropper - * state if the image isn't the right size. - */ - onSelect: function() { - var attachment = this.frame.state().get( 'selection' ).first().toJSON(); - - if ( this.params.width === attachment.width && this.params.height === attachment.height && ! this.params.flex_width && ! this.params.flex_height ) { - this.setImageFromAttachment( attachment ); - this.frame.close(); - } else { - this.frame.setState( 'cropper' ); - } - }, - - /** - * After the image has been cropped, apply the cropped image data to the setting. - * - * @param {object} croppedImage Cropped attachment data. - */ - onCropped: function( croppedImage ) { - this.setImageFromAttachment( croppedImage ); - }, - - /** - * Returns a set of options, computed from the attached image data and - * control-specific data, to be fed to the imgAreaSelect plugin in - * wp.media.view.Cropper. - * - * @param {wp.media.model.Attachment} attachment - * @param {wp.media.controller.Cropper} controller - * @returns {Object} Options - */ - calculateImageSelectOptions: function( attachment, controller ) { - var control = controller.get( 'control' ), - flexWidth = !! parseInt( control.params.flex_width, 10 ), - flexHeight = !! parseInt( control.params.flex_height, 10 ), - realWidth = attachment.get( 'width' ), - realHeight = attachment.get( 'height' ), - xInit = parseInt( control.params.width, 10 ), - yInit = parseInt( control.params.height, 10 ), - ratio = xInit / yInit, - xImg = xInit, - yImg = yInit, - x1, y1, imgSelectOptions; - - controller.set( 'canSkipCrop', ! control.mustBeCropped( flexWidth, flexHeight, xInit, yInit, realWidth, realHeight ) ); - - if ( realWidth / realHeight > ratio ) { - yInit = realHeight; - xInit = yInit * ratio; - } else { - xInit = realWidth; - yInit = xInit / ratio; - } - - x1 = ( realWidth - xInit ) / 2; - y1 = ( realHeight - yInit ) / 2; - - imgSelectOptions = { - handles: true, - keys: true, - instance: true, - persistent: true, - imageWidth: realWidth, - imageHeight: realHeight, - minWidth: xImg > xInit ? xInit : xImg, - minHeight: yImg > yInit ? yInit : yImg, - x1: x1, - y1: y1, - x2: xInit + x1, - y2: yInit + y1 - }; - - if ( flexHeight === false && flexWidth === false ) { - imgSelectOptions.aspectRatio = xInit + ':' + yInit; - } - - if ( true === flexHeight ) { - delete imgSelectOptions.minHeight; - imgSelectOptions.maxWidth = realWidth; - } - - if ( true === flexWidth ) { - delete imgSelectOptions.minWidth; - imgSelectOptions.maxHeight = realHeight; - } - - return imgSelectOptions; - }, - - /** - * Return whether the image must be cropped, based on required dimensions. - * - * @param {bool} flexW - * @param {bool} flexH - * @param {int} dstW - * @param {int} dstH - * @param {int} imgW - * @param {int} imgH - * @return {bool} - */ - mustBeCropped: function( flexW, flexH, dstW, dstH, imgW, imgH ) { - if ( true === flexW && true === flexH ) { - return false; - } - - if ( true === flexW && dstH === imgH ) { - return false; - } - - if ( true === flexH && dstW === imgW ) { - return false; - } - - if ( dstW === imgW && dstH === imgH ) { - return false; - } - - if ( imgW <= dstW ) { - return false; - } - - return true; - }, - - /** - * If cropping was skipped, apply the image data directly to the setting. - */ - onSkippedCrop: function() { - var attachment = this.frame.state().get( 'selection' ).first().toJSON(); - this.setImageFromAttachment( attachment ); - }, - - /** - * Updates the setting and re-renders the control UI. - * - * @param {object} attachment - */ - setImageFromAttachment: function( attachment ) { - this.params.attachment = attachment; - - // Set the Customizer setting; the callback takes care of rendering. - this.setting( attachment.id ); - } - }); - - /** - * A control for selecting and cropping Site Icons. - * - * @class wp.customize.SiteIconControl - * @augments wp.customize.CroppedImageControl - */ - api.SiteIconControl = api.CroppedImageControl.extend(/** @lends wp.customize.SiteIconControl.prototype */{ - - /** - * Create a media modal select frame, and store it so the instance can be reused when needed. - */ - initFrame: function() { - var l10n = _wpMediaViewsL10n; - - this.frame = wp.media({ - button: { - text: l10n.select, - close: false - }, - states: [ - new wp.media.controller.Library({ - title: this.params.button_labels.frame_title, - library: wp.media.query({ type: 'image' }), - multiple: false, - date: false, - priority: 20, - suggestedWidth: this.params.width, - suggestedHeight: this.params.height - }), - new wp.media.controller.SiteIconCropper({ - imgSelectOptions: this.calculateImageSelectOptions, - control: this - }) - ] - }); - - this.frame.on( 'select', this.onSelect, this ); - this.frame.on( 'cropped', this.onCropped, this ); - this.frame.on( 'skippedcrop', this.onSkippedCrop, this ); - }, - - /** - * After an image is selected in the media modal, switch to the cropper - * state if the image isn't the right size. - */ - onSelect: function() { - var attachment = this.frame.state().get( 'selection' ).first().toJSON(), - controller = this; - - if ( this.params.width === attachment.width && this.params.height === attachment.height && ! this.params.flex_width && ! this.params.flex_height ) { - wp.ajax.post( 'crop-image', { - nonce: attachment.nonces.edit, - id: attachment.id, - context: 'site-icon', - cropDetails: { - x1: 0, - y1: 0, - width: this.params.width, - height: this.params.height, - dst_width: this.params.width, - dst_height: this.params.height - } - } ).done( function( croppedImage ) { - controller.setImageFromAttachment( croppedImage ); - controller.frame.close(); - } ).fail( function() { - controller.frame.trigger('content:error:crop'); - } ); - } else { - this.frame.setState( 'cropper' ); - } - }, - - /** - * Updates the setting and re-renders the control UI. - * - * @param {object} attachment - */ - setImageFromAttachment: function( attachment ) { - var sizes = [ 'site_icon-32', 'thumbnail', 'full' ], link, - icon; - - _.each( sizes, function( size ) { - if ( ! icon && ! _.isUndefined ( attachment.sizes[ size ] ) ) { - icon = attachment.sizes[ size ]; - } - } ); - - this.params.attachment = attachment; - - // Set the Customizer setting; the callback takes care of rendering. - this.setting( attachment.id ); - - if ( ! icon ) { - return; - } - - // Update the icon in-browser. - link = $( 'link[rel="icon"][sizes="32x32"]' ); - link.attr( 'href', icon.url ); - }, - - /** - * Called when the "Remove" link is clicked. Empties the setting. - * - * @param {object} event jQuery Event object - */ - removeFile: function( event ) { - if ( api.utils.isKeydownButNotEnterEvent( event ) ) { - return; - } - event.preventDefault(); - - this.params.attachment = {}; - this.setting( '' ); - this.renderContent(); // Not bound to setting change when emptying. - $( 'link[rel="icon"][sizes="32x32"]' ).attr( 'href', '/favicon.ico' ); // Set to default. - } - }); - - /** - * @class wp.customize.HeaderControl - * @augments wp.customize.Control - */ - api.HeaderControl = api.Control.extend(/** @lends wp.customize.HeaderControl.prototype */{ - ready: function() { - this.btnRemove = $('#customize-control-header_image .actions .remove'); - this.btnNew = $('#customize-control-header_image .actions .new'); - - _.bindAll(this, 'openMedia', 'removeImage'); - - this.btnNew.on( 'click', this.openMedia ); - this.btnRemove.on( 'click', this.removeImage ); - - api.HeaderTool.currentHeader = this.getInitialHeaderImage(); - - new api.HeaderTool.CurrentView({ - model: api.HeaderTool.currentHeader, - el: '#customize-control-header_image .current .container' - }); - - new api.HeaderTool.ChoiceListView({ - collection: api.HeaderTool.UploadsList = new api.HeaderTool.ChoiceList(), - el: '#customize-control-header_image .choices .uploaded .list' - }); - - new api.HeaderTool.ChoiceListView({ - collection: api.HeaderTool.DefaultsList = new api.HeaderTool.DefaultsList(), - el: '#customize-control-header_image .choices .default .list' - }); - - api.HeaderTool.combinedList = api.HeaderTool.CombinedList = new api.HeaderTool.CombinedList([ - api.HeaderTool.UploadsList, - api.HeaderTool.DefaultsList - ]); - - // Ensure custom-header-crop Ajax requests bootstrap the Customizer to activate the previewed theme. - wp.media.controller.Cropper.prototype.defaults.doCropArgs.wp_customize = 'on'; - wp.media.controller.Cropper.prototype.defaults.doCropArgs.customize_theme = api.settings.theme.stylesheet; - }, - - /** - * Returns a new instance of api.HeaderTool.ImageModel based on the currently - * saved header image (if any). - * - * @since 4.2.0 - * - * @returns {Object} Options - */ - getInitialHeaderImage: function() { - if ( ! api.get().header_image || ! api.get().header_image_data || _.contains( [ 'remove-header', 'random-default-image', 'random-uploaded-image' ], api.get().header_image ) ) { - return new api.HeaderTool.ImageModel(); - } - - // Get the matching uploaded image object. - var currentHeaderObject = _.find( _wpCustomizeHeader.uploads, function( imageObj ) { - return ( imageObj.attachment_id === api.get().header_image_data.attachment_id ); - } ); - // Fall back to raw current header image. - if ( ! currentHeaderObject ) { - currentHeaderObject = { - url: api.get().header_image, - thumbnail_url: api.get().header_image, - attachment_id: api.get().header_image_data.attachment_id - }; - } - - return new api.HeaderTool.ImageModel({ - header: currentHeaderObject, - choice: currentHeaderObject.url.split( '/' ).pop() - }); - }, - - /** - * Returns a set of options, computed from the attached image data and - * theme-specific data, to be fed to the imgAreaSelect plugin in - * wp.media.view.Cropper. - * - * @param {wp.media.model.Attachment} attachment - * @param {wp.media.controller.Cropper} controller - * @returns {Object} Options - */ - calculateImageSelectOptions: function(attachment, controller) { - var xInit = parseInt(_wpCustomizeHeader.data.width, 10), - yInit = parseInt(_wpCustomizeHeader.data.height, 10), - flexWidth = !! parseInt(_wpCustomizeHeader.data['flex-width'], 10), - flexHeight = !! parseInt(_wpCustomizeHeader.data['flex-height'], 10), - ratio, xImg, yImg, realHeight, realWidth, - imgSelectOptions; - - realWidth = attachment.get('width'); - realHeight = attachment.get('height'); - - this.headerImage = new api.HeaderTool.ImageModel(); - this.headerImage.set({ - themeWidth: xInit, - themeHeight: yInit, - themeFlexWidth: flexWidth, - themeFlexHeight: flexHeight, - imageWidth: realWidth, - imageHeight: realHeight - }); - - controller.set( 'canSkipCrop', ! this.headerImage.shouldBeCropped() ); - - ratio = xInit / yInit; - xImg = realWidth; - yImg = realHeight; - - if ( xImg / yImg > ratio ) { - yInit = yImg; - xInit = yInit * ratio; - } else { - xInit = xImg; - yInit = xInit / ratio; - } - - imgSelectOptions = { - handles: true, - keys: true, - instance: true, - persistent: true, - imageWidth: realWidth, - imageHeight: realHeight, - x1: 0, - y1: 0, - x2: xInit, - y2: yInit - }; - - if (flexHeight === false && flexWidth === false) { - imgSelectOptions.aspectRatio = xInit + ':' + yInit; - } - if (flexHeight === false ) { - imgSelectOptions.maxHeight = yInit; - } - if (flexWidth === false ) { - imgSelectOptions.maxWidth = xInit; - } - - return imgSelectOptions; - }, - - /** - * Sets up and opens the Media Manager in order to select an image. - * Depending on both the size of the image and the properties of the - * current theme, a cropping step after selection may be required or - * skippable. - * - * @param {event} event - */ - openMedia: function(event) { - var l10n = _wpMediaViewsL10n; - - event.preventDefault(); - - this.frame = wp.media({ - button: { - text: l10n.selectAndCrop, - close: false - }, - states: [ - new wp.media.controller.Library({ - title: l10n.chooseImage, - library: wp.media.query({ type: 'image' }), - multiple: false, - date: false, - priority: 20, - suggestedWidth: _wpCustomizeHeader.data.width, - suggestedHeight: _wpCustomizeHeader.data.height - }), - new wp.media.controller.Cropper({ - imgSelectOptions: this.calculateImageSelectOptions - }) - ] - }); - - this.frame.on('select', this.onSelect, this); - this.frame.on('cropped', this.onCropped, this); - this.frame.on('skippedcrop', this.onSkippedCrop, this); - - this.frame.open(); - }, - - /** - * After an image is selected in the media modal, - * switch to the cropper state. - */ - onSelect: function() { - this.frame.setState('cropper'); - }, - - /** - * After the image has been cropped, apply the cropped image data to the setting. - * - * @param {object} croppedImage Cropped attachment data. - */ - onCropped: function(croppedImage) { - var url = croppedImage.url, - attachmentId = croppedImage.attachment_id, - w = croppedImage.width, - h = croppedImage.height; - this.setImageFromURL(url, attachmentId, w, h); - }, - - /** - * If cropping was skipped, apply the image data directly to the setting. - * - * @param {object} selection - */ - onSkippedCrop: function(selection) { - var url = selection.get('url'), - w = selection.get('width'), - h = selection.get('height'); - this.setImageFromURL(url, selection.id, w, h); - }, - - /** - * Creates a new wp.customize.HeaderTool.ImageModel from provided - * header image data and inserts it into the user-uploaded headers - * collection. - * - * @param {String} url - * @param {Number} attachmentId - * @param {Number} width - * @param {Number} height - */ - setImageFromURL: function(url, attachmentId, width, height) { - var choice, data = {}; - - data.url = url; - data.thumbnail_url = url; - data.timestamp = _.now(); - - if (attachmentId) { - data.attachment_id = attachmentId; - } - - if (width) { - data.width = width; - } - - if (height) { - data.height = height; - } - - choice = new api.HeaderTool.ImageModel({ - header: data, - choice: url.split('/').pop() - }); - api.HeaderTool.UploadsList.add(choice); - api.HeaderTool.currentHeader.set(choice.toJSON()); - choice.save(); - choice.importImage(); - }, - - /** - * Triggers the necessary events to deselect an image which was set as - * the currently selected one. - */ - removeImage: function() { - api.HeaderTool.currentHeader.trigger('hide'); - api.HeaderTool.CombinedList.trigger('control:removeImage'); - } - - }); - - /** - * wp.customize.ThemeControl - * - * @class wp.customize.ThemeControl - * @augments wp.customize.Control - */ - api.ThemeControl = api.Control.extend(/** @lends wp.customize.ThemeControl.prototype */{ - - touchDrag: false, - screenshotRendered: false, - - /** - * @since 4.2.0 - */ - ready: function() { - var control = this, panel = api.panel( 'themes' ); - - function disableSwitchButtons() { - return ! panel.canSwitchTheme( control.params.theme.id ); - } - - // Temporary special function since supplying SFTP credentials does not work yet. See #42184. - function disableInstallButtons() { - return disableSwitchButtons() || false === api.settings.theme._canInstall || true === api.settings.theme._filesystemCredentialsNeeded; - } - function updateButtons() { - control.container.find( 'button.preview, button.preview-theme' ).toggleClass( 'disabled', disableSwitchButtons() ); - control.container.find( 'button.theme-install' ).toggleClass( 'disabled', disableInstallButtons() ); - } - - api.state( 'selectedChangesetStatus' ).bind( updateButtons ); - api.state( 'changesetStatus' ).bind( updateButtons ); - updateButtons(); - - control.container.on( 'touchmove', '.theme', function() { - control.touchDrag = true; - }); - - // Bind details view trigger. - control.container.on( 'click keydown touchend', '.theme', function( event ) { - var section; - if ( api.utils.isKeydownButNotEnterEvent( event ) ) { - return; - } - - // Bail if the user scrolled on a touch device. - if ( control.touchDrag === true ) { - return control.touchDrag = false; - } - - // Prevent the modal from showing when the user clicks the action button. - if ( $( event.target ).is( '.theme-actions .button, .update-theme' ) ) { - return; - } - - event.preventDefault(); // Keep this AFTER the key filter above - section = api.section( control.section() ); - section.showDetails( control.params.theme, function() { - - // Temporary special function since supplying SFTP credentials does not work yet. See #42184. - if ( api.settings.theme._filesystemCredentialsNeeded ) { - section.overlay.find( '.theme-actions .delete-theme' ).remove(); - } - } ); - }); - - control.container.on( 'render-screenshot', function() { - var $screenshot = $( this ).find( 'img' ), - source = $screenshot.data( 'src' ); - - if ( source ) { - $screenshot.attr( 'src', source ); - } - control.screenshotRendered = true; - }); - }, - - /** - * Show or hide the theme based on the presence of the term in the title, description, tags, and author. - * - * @since 4.2.0 - * @param {Array} terms - An array of terms to search for. - * @returns {boolean} Whether a theme control was activated or not. - */ - filter: function( terms ) { - var control = this, - matchCount = 0, - haystack = control.params.theme.name + ' ' + - control.params.theme.description + ' ' + - control.params.theme.tags + ' ' + - control.params.theme.author + ' '; - haystack = haystack.toLowerCase().replace( '-', ' ' ); - - // Back-compat for behavior in WordPress 4.2.0 to 4.8.X. - if ( ! _.isArray( terms ) ) { - terms = [ terms ]; - } - - // Always give exact name matches highest ranking. - if ( control.params.theme.name.toLowerCase() === terms.join( ' ' ) ) { - matchCount = 100; - } else { - - // Search for and weight (by 10) complete term matches. - matchCount = matchCount + 10 * ( haystack.split( terms.join( ' ' ) ).length - 1 ); - - // Search for each term individually (as whole-word and partial match) and sum weighted match counts. - _.each( terms, function( term ) { - matchCount = matchCount + 2 * ( haystack.split( term + ' ' ).length - 1 ); // Whole-word, double-weighted. - matchCount = matchCount + haystack.split( term ).length - 1; // Partial word, to minimize empty intermediate searches while typing. - }); - - // Upper limit on match ranking. - if ( matchCount > 99 ) { - matchCount = 99; - } - } - - if ( 0 !== matchCount ) { - control.activate(); - control.params.priority = 101 - matchCount; // Sort results by match count. - return true; - } else { - control.deactivate(); // Hide control - control.params.priority = 101; - return false; - } - }, - - /** - * Rerender the theme from its JS template with the installed type. - * - * @since 4.9.0 - * - * @returns {void} - */ - rerenderAsInstalled: function( installed ) { - var control = this, section; - if ( installed ) { - control.params.theme.type = 'installed'; - } else { - section = api.section( control.params.section ); - control.params.theme.type = section.params.action; - } - control.renderContent(); // Replaces existing content. - control.container.trigger( 'render-screenshot' ); - } - }); - - /** - * Class wp.customize.CodeEditorControl - * - * @since 4.9.0 - * - * @class wp.customize.CodeEditorControl - * @augments wp.customize.Control - */ - api.CodeEditorControl = api.Control.extend(/** @lends wp.customize.CodeEditorControl.prototype */{ - - /** - * Initialize. - * - * @since 4.9.0 - * @param {string} id - Unique identifier for the control instance. - * @param {object} options - Options hash for the control instance. - * @returns {void} - */ - initialize: function( id, options ) { - var control = this; - control.deferred = _.extend( control.deferred || {}, { - codemirror: $.Deferred() - } ); - api.Control.prototype.initialize.call( control, id, options ); - - // Note that rendering is debounced so the props will be used when rendering happens after add event. - control.notifications.bind( 'add', function( notification ) { - - // Skip if control notification is not from setting csslint_error notification. - if ( notification.code !== control.setting.id + ':csslint_error' ) { - return; - } - - // Customize the template and behavior of csslint_error notifications. - notification.templateId = 'customize-code-editor-lint-error-notification'; - notification.render = (function( render ) { - return function() { - var li = render.call( this ); - li.find( 'input[type=checkbox]' ).on( 'click', function() { - control.setting.notifications.remove( 'csslint_error' ); - } ); - return li; - }; - })( notification.render ); - } ); - }, - - /** - * Initialize the editor when the containing section is ready and expanded. - * - * @since 4.9.0 - * @returns {void} - */ - ready: function() { - var control = this; - if ( ! control.section() ) { - control.initEditor(); - return; - } - - // Wait to initialize editor until section is embedded and expanded. - api.section( control.section(), function( section ) { - section.deferred.embedded.done( function() { - var onceExpanded; - if ( section.expanded() ) { - control.initEditor(); - } else { - onceExpanded = function( isExpanded ) { - if ( isExpanded ) { - control.initEditor(); - section.expanded.unbind( onceExpanded ); - } - }; - section.expanded.bind( onceExpanded ); - } - } ); - } ); - }, - - /** - * Initialize editor. - * - * @since 4.9.0 - * @returns {void} - */ - initEditor: function() { - var control = this, element, editorSettings = false; - - // Obtain editorSettings for instantiation. - if ( wp.codeEditor && ( _.isUndefined( control.params.editor_settings ) || false !== control.params.editor_settings ) ) { - - // Obtain default editor settings. - editorSettings = wp.codeEditor.defaultSettings ? _.clone( wp.codeEditor.defaultSettings ) : {}; - editorSettings.codemirror = _.extend( - {}, - editorSettings.codemirror, - { - indentUnit: 2, - tabSize: 2 - } - ); - - // Merge editor_settings param on top of defaults. - if ( _.isObject( control.params.editor_settings ) ) { - _.each( control.params.editor_settings, function( value, key ) { - if ( _.isObject( value ) ) { - editorSettings[ key ] = _.extend( - {}, - editorSettings[ key ], - value - ); - } - } ); - } - } - - element = new api.Element( control.container.find( 'textarea' ) ); - control.elements.push( element ); - element.sync( control.setting ); - element.set( control.setting() ); - - if ( editorSettings ) { - control.initSyntaxHighlightingEditor( editorSettings ); - } else { - control.initPlainTextareaEditor(); - } - }, - - /** - * Make sure editor gets focused when control is focused. - * - * @since 4.9.0 - * @param {Object} [params] - Focus params. - * @param {Function} [params.completeCallback] - Function to call when expansion is complete. - * @returns {void} - */ - focus: function( params ) { - var control = this, extendedParams = _.extend( {}, params ), originalCompleteCallback; - originalCompleteCallback = extendedParams.completeCallback; - extendedParams.completeCallback = function() { - if ( originalCompleteCallback ) { - originalCompleteCallback(); - } - if ( control.editor ) { - control.editor.codemirror.focus(); - } - }; - api.Control.prototype.focus.call( control, extendedParams ); - }, - - /** - * Initialize syntax-highlighting editor. - * - * @since 4.9.0 - * @param {object} codeEditorSettings - Code editor settings. - * @returns {void} - */ - initSyntaxHighlightingEditor: function( codeEditorSettings ) { - var control = this, $textarea = control.container.find( 'textarea' ), settings, suspendEditorUpdate = false; - - settings = _.extend( {}, codeEditorSettings, { - onTabNext: _.bind( control.onTabNext, control ), - onTabPrevious: _.bind( control.onTabPrevious, control ), - onUpdateErrorNotice: _.bind( control.onUpdateErrorNotice, control ) - }); - - control.editor = wp.codeEditor.initialize( $textarea, settings ); - - // Improve the editor accessibility. - $( control.editor.codemirror.display.lineDiv ) - .attr({ - role: 'textbox', - 'aria-multiline': 'true', - 'aria-label': control.params.label, - 'aria-describedby': 'editor-keyboard-trap-help-1 editor-keyboard-trap-help-2 editor-keyboard-trap-help-3 editor-keyboard-trap-help-4' - }); - - // Focus the editor when clicking on its label. - control.container.find( 'label' ).on( 'click', function() { - control.editor.codemirror.focus(); - }); - - /* - * When the CodeMirror instance changes, mirror to the textarea, - * where we have our "true" change event handler bound. - */ - control.editor.codemirror.on( 'change', function( codemirror ) { - suspendEditorUpdate = true; - $textarea.val( codemirror.getValue() ).trigger( 'change' ); - suspendEditorUpdate = false; - }); - - // Update CodeMirror when the setting is changed by another plugin. - control.setting.bind( function( value ) { - if ( ! suspendEditorUpdate ) { - control.editor.codemirror.setValue( value ); - } - }); - - // Prevent collapsing section when hitting Esc to tab out of editor. - control.editor.codemirror.on( 'keydown', function onKeydown( codemirror, event ) { - var escKeyCode = 27; - if ( escKeyCode === event.keyCode ) { - event.stopPropagation(); - } - }); - - control.deferred.codemirror.resolveWith( control, [ control.editor.codemirror ] ); - }, - - /** - * Handle tabbing to the field after the editor. - * - * @since 4.9.0 - * @returns {void} - */ - onTabNext: function onTabNext() { - var control = this, controls, controlIndex, section; - section = api.section( control.section() ); - controls = section.controls(); - controlIndex = controls.indexOf( control ); - if ( controls.length === controlIndex + 1 ) { - $( '#customize-footer-actions .collapse-sidebar' ).focus(); - } else { - controls[ controlIndex + 1 ].container.find( ':focusable:first' ).focus(); - } - }, - - /** - * Handle tabbing to the field before the editor. - * - * @since 4.9.0 - * @returns {void} - */ - onTabPrevious: function onTabPrevious() { - var control = this, controls, controlIndex, section; - section = api.section( control.section() ); - controls = section.controls(); - controlIndex = controls.indexOf( control ); - if ( 0 === controlIndex ) { - section.contentContainer.find( '.customize-section-title .customize-help-toggle, .customize-section-title .customize-section-description.open .section-description-close' ).last().focus(); - } else { - controls[ controlIndex - 1 ].contentContainer.find( ':focusable:first' ).focus(); - } - }, - - /** - * Update error notice. - * - * @since 4.9.0 - * @param {Array} errorAnnotations - Error annotations. - * @returns {void} - */ - onUpdateErrorNotice: function onUpdateErrorNotice( errorAnnotations ) { - var control = this, message; - control.setting.notifications.remove( 'csslint_error' ); - - if ( 0 !== errorAnnotations.length ) { - if ( 1 === errorAnnotations.length ) { - message = api.l10n.customCssError.singular.replace( '%d', '1' ); - } else { - message = api.l10n.customCssError.plural.replace( '%d', String( errorAnnotations.length ) ); - } - control.setting.notifications.add( new api.Notification( 'csslint_error', { - message: message, - type: 'error' - } ) ); - } - }, - - /** - * Initialize plain-textarea editor when syntax highlighting is disabled. - * - * @since 4.9.0 - * @returns {void} - */ - initPlainTextareaEditor: function() { - var control = this, $textarea = control.container.find( 'textarea' ), textarea = $textarea[0]; - - $textarea.on( 'blur', function onBlur() { - $textarea.data( 'next-tab-blurs', false ); - } ); - - $textarea.on( 'keydown', function onKeydown( event ) { - var selectionStart, selectionEnd, value, tabKeyCode = 9, escKeyCode = 27; - - if ( escKeyCode === event.keyCode ) { - if ( ! $textarea.data( 'next-tab-blurs' ) ) { - $textarea.data( 'next-tab-blurs', true ); - event.stopPropagation(); // Prevent collapsing the section. - } - return; - } - - // Short-circuit if tab key is not being pressed or if a modifier key *is* being pressed. - if ( tabKeyCode !== event.keyCode || event.ctrlKey || event.altKey || event.shiftKey ) { - return; - } - - // Prevent capturing Tab characters if Esc was pressed. - if ( $textarea.data( 'next-tab-blurs' ) ) { - return; - } - - selectionStart = textarea.selectionStart; - selectionEnd = textarea.selectionEnd; - value = textarea.value; - - if ( selectionStart >= 0 ) { - textarea.value = value.substring( 0, selectionStart ).concat( '\t', value.substring( selectionEnd ) ); - $textarea.selectionStart = textarea.selectionEnd = selectionStart + 1; - } - - event.stopPropagation(); - event.preventDefault(); - }); - - control.deferred.codemirror.rejectWith( control ); - } - }); - - /** - * Class wp.customize.DateTimeControl. - * - * @since 4.9.0 - * @class wp.customize.DateTimeControl - * @augments wp.customize.Control - */ - api.DateTimeControl = api.Control.extend(/** @lends wp.customize.DateTimeControl.prototype */{ - - /** - * Initialize behaviors. - * - * @since 4.9.0 - * @returns {void} - */ - ready: function ready() { - var control = this; - - control.inputElements = {}; - control.invalidDate = false; - - _.bindAll( control, 'populateSetting', 'updateDaysForMonth', 'populateDateInputs' ); - - if ( ! control.setting ) { - throw new Error( 'Missing setting' ); - } - - control.container.find( '.date-input' ).each( function() { - var input = $( this ), component, element; - component = input.data( 'component' ); - element = new api.Element( input ); - control.inputElements[ component ] = element; - control.elements.push( element ); - - // Add invalid date error once user changes (and has blurred the input). - input.on( 'change', function() { - if ( control.invalidDate ) { - control.notifications.add( new api.Notification( 'invalid_date', { - message: api.l10n.invalidDate - } ) ); - } - } ); - - // Remove the error immediately after validity change. - input.on( 'input', _.debounce( function() { - if ( ! control.invalidDate ) { - control.notifications.remove( 'invalid_date' ); - } - } ) ); - - // Add zero-padding when blurring field. - input.on( 'blur', _.debounce( function() { - if ( ! control.invalidDate ) { - control.populateDateInputs(); - } - } ) ); - } ); - - control.inputElements.month.bind( control.updateDaysForMonth ); - control.inputElements.year.bind( control.updateDaysForMonth ); - control.populateDateInputs(); - control.setting.bind( control.populateDateInputs ); - - // Start populating setting after inputs have been populated. - _.each( control.inputElements, function( element ) { - element.bind( control.populateSetting ); - } ); - }, - - /** - * Parse datetime string. - * - * @since 4.9.0 - * - * @param {string} datetime - Date/Time string. Accepts Y-m-d[ H:i[:s]] format. - * @returns {object|null} Returns object containing date components or null if parse error. - */ - parseDateTime: function parseDateTime( datetime ) { - var control = this, matches, date, midDayHour = 12; - - if ( datetime ) { - matches = datetime.match( /^(\d\d\d\d)-(\d\d)-(\d\d)(?: (\d\d):(\d\d)(?::(\d\d))?)?$/ ); - } - - if ( ! matches ) { - return null; - } - - matches.shift(); - - date = { - year: matches.shift(), - month: matches.shift(), - day: matches.shift(), - hour: matches.shift() || '00', - minute: matches.shift() || '00', - second: matches.shift() || '00' - }; - - if ( control.params.includeTime && control.params.twelveHourFormat ) { - date.hour = parseInt( date.hour, 10 ); - date.meridian = date.hour >= midDayHour ? 'pm' : 'am'; - date.hour = date.hour % midDayHour ? String( date.hour % midDayHour ) : String( midDayHour ); - delete date.second; // @todo Why only if twelveHourFormat? - } - - return date; - }, - - /** - * Validates if input components have valid date and time. - * - * @since 4.9.0 - * @return {boolean} If date input fields has error. - */ - validateInputs: function validateInputs() { - var control = this, components, validityInput; - - control.invalidDate = false; - - components = [ 'year', 'day' ]; - if ( control.params.includeTime ) { - components.push( 'hour', 'minute' ); - } - - _.find( components, function( component ) { - var element, max, min, value; - - element = control.inputElements[ component ]; - validityInput = element.element.get( 0 ); - max = parseInt( element.element.attr( 'max' ), 10 ); - min = parseInt( element.element.attr( 'min' ), 10 ); - value = parseInt( element(), 10 ); - control.invalidDate = isNaN( value ) || value > max || value < min; - - if ( ! control.invalidDate ) { - validityInput.setCustomValidity( '' ); - } - - return control.invalidDate; - } ); - - if ( control.inputElements.meridian && ! control.invalidDate ) { - validityInput = control.inputElements.meridian.element.get( 0 ); - if ( 'am' !== control.inputElements.meridian.get() && 'pm' !== control.inputElements.meridian.get() ) { - control.invalidDate = true; - } else { - validityInput.setCustomValidity( '' ); - } - } - - if ( control.invalidDate ) { - validityInput.setCustomValidity( api.l10n.invalidValue ); - } else { - validityInput.setCustomValidity( '' ); - } - if ( ! control.section() || api.section.has( control.section() ) && api.section( control.section() ).expanded() ) { - _.result( validityInput, 'reportValidity' ); - } - - return control.invalidDate; - }, - - /** - * Updates number of days according to the month and year selected. - * - * @since 4.9.0 - * @return {void} - */ - updateDaysForMonth: function updateDaysForMonth() { - var control = this, daysInMonth, year, month, day; - - month = parseInt( control.inputElements.month(), 10 ); - year = parseInt( control.inputElements.year(), 10 ); - day = parseInt( control.inputElements.day(), 10 ); - - if ( month && year ) { - daysInMonth = new Date( year, month, 0 ).getDate(); - control.inputElements.day.element.attr( 'max', daysInMonth ); - - if ( day > daysInMonth ) { - control.inputElements.day( String( daysInMonth ) ); - } - } - }, - - /** - * Populate setting value from the inputs. - * - * @since 4.9.0 - * @returns {boolean} If setting updated. - */ - populateSetting: function populateSetting() { - var control = this, date; - - if ( control.validateInputs() || ! control.params.allowPastDate && ! control.isFutureDate() ) { - return false; - } - - date = control.convertInputDateToString(); - control.setting.set( date ); - return true; - }, - - /** - * Converts input values to string in Y-m-d H:i:s format. - * - * @since 4.9.0 - * @return {string} Date string. - */ - convertInputDateToString: function convertInputDateToString() { - var control = this, date = '', dateFormat, hourInTwentyFourHourFormat, - getElementValue, pad; - - pad = function( number, padding ) { - var zeros; - if ( String( number ).length < padding ) { - zeros = padding - String( number ).length; - number = Math.pow( 10, zeros ).toString().substr( 1 ) + String( number ); - } - return number; - }; - - getElementValue = function( component ) { - var value = parseInt( control.inputElements[ component ].get(), 10 ); - - if ( _.contains( [ 'month', 'day', 'hour', 'minute' ], component ) ) { - value = pad( value, 2 ); - } else if ( 'year' === component ) { - value = pad( value, 4 ); - } - return value; - }; - - dateFormat = [ 'year', '-', 'month', '-', 'day' ]; - if ( control.params.includeTime ) { - hourInTwentyFourHourFormat = control.inputElements.meridian ? control.convertHourToTwentyFourHourFormat( control.inputElements.hour(), control.inputElements.meridian() ) : control.inputElements.hour(); - dateFormat = dateFormat.concat( [ ' ', pad( hourInTwentyFourHourFormat, 2 ), ':', 'minute', ':', '00' ] ); - } - - _.each( dateFormat, function( component ) { - date += control.inputElements[ component ] ? getElementValue( component ) : component; - } ); - - return date; - }, - - /** - * Check if the date is in the future. - * - * @since 4.9.0 - * @returns {boolean} True if future date. - */ - isFutureDate: function isFutureDate() { - var control = this; - return 0 < api.utils.getRemainingTime( control.convertInputDateToString() ); - }, - - /** - * Convert hour in twelve hour format to twenty four hour format. - * - * @since 4.9.0 - * @param {string} hourInTwelveHourFormat - Hour in twelve hour format. - * @param {string} meridian - Either 'am' or 'pm'. - * @returns {string} Hour in twenty four hour format. - */ - convertHourToTwentyFourHourFormat: function convertHour( hourInTwelveHourFormat, meridian ) { - var hourInTwentyFourHourFormat, hour, midDayHour = 12; - - hour = parseInt( hourInTwelveHourFormat, 10 ); - if ( isNaN( hour ) ) { - return ''; - } - - if ( 'pm' === meridian && hour < midDayHour ) { - hourInTwentyFourHourFormat = hour + midDayHour; - } else if ( 'am' === meridian && midDayHour === hour ) { - hourInTwentyFourHourFormat = hour - midDayHour; - } else { - hourInTwentyFourHourFormat = hour; - } - - return String( hourInTwentyFourHourFormat ); - }, - - /** - * Populates date inputs in date fields. - * - * @since 4.9.0 - * @returns {boolean} Whether the inputs were populated. - */ - populateDateInputs: function populateDateInputs() { - var control = this, parsed; - - parsed = control.parseDateTime( control.setting.get() ); - - if ( ! parsed ) { - return false; - } - - _.each( control.inputElements, function( element, component ) { - var value = parsed[ component ]; // This will be zero-padded string. - - // Set month and meridian regardless of focused state since they are dropdowns. - if ( 'month' === component || 'meridian' === component ) { - - // Options in dropdowns are not zero-padded. - value = value.replace( /^0/, '' ); - - element.set( value ); - } else { - - value = parseInt( value, 10 ); - if ( ! element.element.is( document.activeElement ) ) { - - // Populate element with zero-padded value if not focused. - element.set( parsed[ component ] ); - } else if ( value !== parseInt( element(), 10 ) ) { - - // Forcibly update the value if its underlying value changed, regardless of zero-padding. - element.set( String( value ) ); - } - } - } ); - - return true; - }, - - /** - * Toggle future date notification for date control. - * - * @since 4.9.0 - * @param {boolean} notify Add or remove the notification. - * @return {wp.customize.DateTimeControl} - */ - toggleFutureDateNotification: function toggleFutureDateNotification( notify ) { - var control = this, notificationCode, notification; - - notificationCode = 'not_future_date'; - - if ( notify ) { - notification = new api.Notification( notificationCode, { - type: 'error', - message: api.l10n.futureDateError - } ); - control.notifications.add( notification ); - } else { - control.notifications.remove( notificationCode ); - } - - return control; - } - }); - - /** - * Class PreviewLinkControl. - * - * @since 4.9.0 - * @class wp.customize.PreviewLinkControl - * @augments wp.customize.Control - */ - api.PreviewLinkControl = api.Control.extend(/** @lends wp.customize.PreviewLinkControl.prototype */{ - - defaults: _.extend( {}, api.Control.prototype.defaults, { - templateId: 'customize-preview-link-control' - } ), - - /** - * Initialize behaviors. - * - * @since 4.9.0 - * @returns {void} - */ - ready: function ready() { - var control = this, element, component, node, url, input, button; - - _.bindAll( control, 'updatePreviewLink' ); - - if ( ! control.setting ) { - control.setting = new api.Value(); - } - - control.previewElements = {}; - - control.container.find( '.preview-control-element' ).each( function() { - node = $( this ); - component = node.data( 'component' ); - element = new api.Element( node ); - control.previewElements[ component ] = element; - control.elements.push( element ); - } ); - - url = control.previewElements.url; - input = control.previewElements.input; - button = control.previewElements.button; - - input.link( control.setting ); - url.link( control.setting ); - - url.bind( function( value ) { - url.element.parent().attr( { - href: value, - target: api.settings.changeset.uuid - } ); - } ); - - api.bind( 'ready', control.updatePreviewLink ); - api.state( 'saved' ).bind( control.updatePreviewLink ); - api.state( 'changesetStatus' ).bind( control.updatePreviewLink ); - api.state( 'activated' ).bind( control.updatePreviewLink ); - api.previewer.previewUrl.bind( control.updatePreviewLink ); - - button.element.on( 'click', function( event ) { - event.preventDefault(); - if ( control.setting() ) { - input.element.select(); - document.execCommand( 'copy' ); - button( button.element.data( 'copied-text' ) ); - } - } ); - - url.element.parent().on( 'click', function( event ) { - if ( $( this ).hasClass( 'disabled' ) ) { - event.preventDefault(); - } - } ); - - button.element.on( 'mouseenter', function() { - if ( control.setting() ) { - button( button.element.data( 'copy-text' ) ); - } - } ); - }, - - /** - * Updates Preview Link - * - * @since 4.9.0 - * @return {void} - */ - updatePreviewLink: function updatePreviewLink() { - var control = this, unsavedDirtyValues; - - unsavedDirtyValues = ! api.state( 'saved' ).get() || '' === api.state( 'changesetStatus' ).get() || 'auto-draft' === api.state( 'changesetStatus' ).get(); - - control.toggleSaveNotification( unsavedDirtyValues ); - control.previewElements.url.element.parent().toggleClass( 'disabled', unsavedDirtyValues ); - control.previewElements.button.element.prop( 'disabled', unsavedDirtyValues ); - control.setting.set( api.previewer.getFrontendPreviewUrl() ); - }, - - /** - * Toggles save notification. - * - * @since 4.9.0 - * @param {boolean} notify Add or remove notification. - * @return {void} - */ - toggleSaveNotification: function toggleSaveNotification( notify ) { - var control = this, notificationCode, notification; - - notificationCode = 'changes_not_saved'; - - if ( notify ) { - notification = new api.Notification( notificationCode, { - type: 'info', - message: api.l10n.saveBeforeShare - } ); - control.notifications.add( notification ); - } else { - control.notifications.remove( notificationCode ); - } - } - }); - - /** - * Change objects contained within the main customize object to Settings. - * - * @alias wp.customize.defaultConstructor - */ - api.defaultConstructor = api.Setting; - - /** - * Callback for resolved controls. - * - * @callback wp.customize.deferredControlsCallback - * @param {wp.customize.Control[]} controls Resolved controls. - */ - - /** - * Collection of all registered controls. - * - * @alias wp.customize.control - * - * @since 3.4.0 - * - * @type {Function} - * @param {...string} ids - One or more ids for controls to obtain. - * @param {deferredControlsCallback} [callback] - Function called when all supplied controls exist. - * @returns {wp.customize.Control|undefined|jQuery.promise} Control instance or undefined (if function called with one id param), or promise resolving to requested controls. - * - * @example <caption>Loop over all registered controls.</caption> - * wp.customize.control.each( function( control ) { ... } ); - * - * @example <caption>Getting `background_color` control instance.</caption> - * control = wp.customize.control( 'background_color' ); - * - * @example <caption>Check if control exists.</caption> - * hasControl = wp.customize.control.has( 'background_color' ); - * - * @example <caption>Deferred getting of `background_color` control until it exists, using callback.</caption> - * wp.customize.control( 'background_color', function( control ) { ... } ); - * - * @example <caption>Get title and tagline controls when they both exist, using promise (only available when multiple IDs are present).</caption> - * promise = wp.customize.control( 'blogname', 'blogdescription' ); - * promise.done( function( titleControl, taglineControl ) { ... } ); - * - * @example <caption>Get title and tagline controls when they both exist, using callback.</caption> - * wp.customize.control( 'blogname', 'blogdescription', function( titleControl, taglineControl ) { ... } ); - * - * @example <caption>Getting setting value for `background_color` control.</caption> - * value = wp.customize.control( 'background_color ').setting.get(); - * value = wp.customize( 'background_color' ).get(); // Same as above, since setting ID and control ID are the same. - * - * @example <caption>Add new control for site title.</caption> - * wp.customize.control.add( new wp.customize.Control( 'other_blogname', { - * setting: 'blogname', - * type: 'text', - * label: 'Site title', - * section: 'other_site_identify' - * } ) ); - * - * @example <caption>Remove control.</caption> - * wp.customize.control.remove( 'other_blogname' ); - * - * @example <caption>Listen for control being added.</caption> - * wp.customize.control.bind( 'add', function( addedControl ) { ... } ) - * - * @example <caption>Listen for control being removed.</caption> - * wp.customize.control.bind( 'removed', function( removedControl ) { ... } ) - */ - api.control = new api.Values({ defaultConstructor: api.Control }); - - /** - * Callback for resolved sections. - * - * @callback wp.customize.deferredSectionsCallback - * @param {wp.customize.Section[]} sections Resolved sections. - */ - - /** - * Collection of all registered sections. - * - * @alias wp.customize.section - * - * @since 3.4.0 - * - * @type {Function} - * @param {...string} ids - One or more ids for sections to obtain. - * @param {deferredSectionsCallback} [callback] - Function called when all supplied sections exist. - * @returns {wp.customize.Section|undefined|jQuery.promise} Section instance or undefined (if function called with one id param), or promise resolving to requested sections. - * - * @example <caption>Loop over all registered sections.</caption> - * wp.customize.section.each( function( section ) { ... } ) - * - * @example <caption>Getting `title_tagline` section instance.</caption> - * section = wp.customize.section( 'title_tagline' ) - * - * @example <caption>Expand dynamically-created section when it exists.</caption> - * wp.customize.section( 'dynamically_created', function( section ) { - * section.expand(); - * } ); - * - * @see {@link wp.customize.control} for further examples of how to interact with {@link wp.customize.Values} instances. - */ - api.section = new api.Values({ defaultConstructor: api.Section }); - - /** - * Callback for resolved panels. - * - * @callback wp.customize.deferredPanelsCallback - * @param {wp.customize.Panel[]} panels Resolved panels. - */ - - /** - * Collection of all registered panels. - * - * @alias wp.customize.panel - * - * @since 4.0.0 - * - * @type {Function} - * @param {...string} ids - One or more ids for panels to obtain. - * @param {deferredPanelsCallback} [callback] - Function called when all supplied panels exist. - * @returns {wp.customize.Panel|undefined|jQuery.promise} Panel instance or undefined (if function called with one id param), or promise resolving to requested panels. - * - * @example <caption>Loop over all registered panels.</caption> - * wp.customize.panel.each( function( panel ) { ... } ) - * - * @example <caption>Getting nav_menus panel instance.</caption> - * panel = wp.customize.panel( 'nav_menus' ); - * - * @example <caption>Expand dynamically-created panel when it exists.</caption> - * wp.customize.panel( 'dynamically_created', function( panel ) { - * panel.expand(); - * } ); - * - * @see {@link wp.customize.control} for further examples of how to interact with {@link wp.customize.Values} instances. - */ - api.panel = new api.Values({ defaultConstructor: api.Panel }); - - /** - * Callback for resolved notifications. - * - * @callback wp.customize.deferredNotificationsCallback - * @param {wp.customize.Notification[]} notifications Resolved notifications. - */ - - /** - * Collection of all global notifications. - * - * @alias wp.customize.notifications - * - * @since 4.9.0 - * - * @type {Function} - * @param {...string} codes - One or more codes for notifications to obtain. - * @param {deferredNotificationsCallback} [callback] - Function called when all supplied notifications exist. - * @returns {wp.customize.Notification|undefined|jQuery.promise} notification instance or undefined (if function called with one code param), or promise resolving to requested notifications. - * - * @example <caption>Check if existing notification</caption> - * exists = wp.customize.notifications.has( 'a_new_day_arrived' ); - * - * @example <caption>Obtain existing notification</caption> - * notification = wp.customize.notifications( 'a_new_day_arrived' ); - * - * @example <caption>Obtain notification that may not exist yet.</caption> - * wp.customize.notifications( 'a_new_day_arrived', function( notification ) { ... } ); - * - * @example <caption>Add a warning notification.</caption> - * wp.customize.notifications.add( new wp.customize.Notification( 'midnight_almost_here', { - * type: 'warning', - * message: 'Midnight has almost arrived!', - * dismissible: true - * } ) ); - * - * @example <caption>Remove a notification.</caption> - * wp.customize.notifications.remove( 'a_new_day_arrived' ); - * - * @see {@link wp.customize.control} for further examples of how to interact with {@link wp.customize.Values} instances. - */ - api.notifications = new api.Notifications(); - - api.PreviewFrame = api.Messenger.extend(/** @lends wp.customize.PreviewFrame.prototype */{ - sensitivity: null, // Will get set to api.settings.timeouts.previewFrameSensitivity. - - /** - * An object that fetches a preview in the background of the document, which - * allows for seamless replacement of an existing preview. - * - * @constructs wp.customize.PreviewFrame - * @augments wp.customize.Messenger - * - * @param {object} params.container - * @param {object} params.previewUrl - * @param {object} params.query - * @param {object} options - */ - initialize: function( params, options ) { - var deferred = $.Deferred(); - - /* - * Make the instance of the PreviewFrame the promise object - * so other objects can easily interact with it. - */ - deferred.promise( this ); - - this.container = params.container; - - $.extend( params, { channel: api.PreviewFrame.uuid() }); - - api.Messenger.prototype.initialize.call( this, params, options ); - - this.add( 'previewUrl', params.previewUrl ); - - this.query = $.extend( params.query || {}, { customize_messenger_channel: this.channel() }); - - this.run( deferred ); - }, - - /** - * Run the preview request. - * - * @param {object} deferred jQuery Deferred object to be resolved with - * the request. - */ - run: function( deferred ) { - var previewFrame = this, - loaded = false, - ready = false, - readyData = null, - hasPendingChangesetUpdate = '{}' !== previewFrame.query.customized, - urlParser, - params, - form; - - if ( previewFrame._ready ) { - previewFrame.unbind( 'ready', previewFrame._ready ); - } - - previewFrame._ready = function( data ) { - ready = true; - readyData = data; - previewFrame.container.addClass( 'iframe-ready' ); - if ( ! data ) { - return; - } - - if ( loaded ) { - deferred.resolveWith( previewFrame, [ data ] ); - } - }; - - previewFrame.bind( 'ready', previewFrame._ready ); - - urlParser = document.createElement( 'a' ); - urlParser.href = previewFrame.previewUrl(); - - params = _.extend( - api.utils.parseQueryString( urlParser.search.substr( 1 ) ), - { - customize_changeset_uuid: previewFrame.query.customize_changeset_uuid, - customize_theme: previewFrame.query.customize_theme, - customize_messenger_channel: previewFrame.query.customize_messenger_channel - } - ); - if ( api.settings.changeset.autosaved || ! api.state( 'saved' ).get() ) { - params.customize_autosaved = 'on'; - } - - urlParser.search = $.param( params ); - previewFrame.iframe = $( '<iframe />', { - title: api.l10n.previewIframeTitle, - name: 'customize-' + previewFrame.channel() - } ); - previewFrame.iframe.attr( 'onmousewheel', '' ); // Workaround for Safari bug. See WP Trac #38149. - previewFrame.iframe.attr( 'sandbox', 'allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-same-origin allow-scripts' ); - - if ( ! hasPendingChangesetUpdate ) { - previewFrame.iframe.attr( 'src', urlParser.href ); - } else { - previewFrame.iframe.attr( 'data-src', urlParser.href ); // For debugging purposes. - } - - previewFrame.iframe.appendTo( previewFrame.container ); - previewFrame.targetWindow( previewFrame.iframe[0].contentWindow ); - - /* - * Submit customized data in POST request to preview frame window since - * there are setting value changes not yet written to changeset. - */ - if ( hasPendingChangesetUpdate ) { - form = $( '<form>', { - action: urlParser.href, - target: previewFrame.iframe.attr( 'name' ), - method: 'post', - hidden: 'hidden' - } ); - form.append( $( '<input>', { - type: 'hidden', - name: '_method', - value: 'GET' - } ) ); - _.each( previewFrame.query, function( value, key ) { - form.append( $( '<input>', { - type: 'hidden', - name: key, - value: value - } ) ); - } ); - previewFrame.container.append( form ); - form.submit(); - form.remove(); // No need to keep the form around after submitted. - } - - previewFrame.bind( 'iframe-loading-error', function( error ) { - previewFrame.iframe.remove(); - - // Check if the user is not logged in. - if ( 0 === error ) { - previewFrame.login( deferred ); - return; - } - - // Check for cheaters. - if ( -1 === error ) { - deferred.rejectWith( previewFrame, [ 'cheatin' ] ); - return; - } - - deferred.rejectWith( previewFrame, [ 'request failure' ] ); - } ); - - previewFrame.iframe.one( 'load', function() { - loaded = true; - - if ( ready ) { - deferred.resolveWith( previewFrame, [ readyData ] ); - } else { - setTimeout( function() { - deferred.rejectWith( previewFrame, [ 'ready timeout' ] ); - }, previewFrame.sensitivity ); - } - }); - }, - - login: function( deferred ) { - var self = this, - reject; - - reject = function() { - deferred.rejectWith( self, [ 'logged out' ] ); - }; - - if ( this.triedLogin ) { - return reject(); - } - - // Check if we have an admin cookie. - $.get( api.settings.url.ajax, { - action: 'logged-in' - }).fail( reject ).done( function( response ) { - var iframe; - - if ( '1' !== response ) { - reject(); - } - - iframe = $( '<iframe />', { 'src': self.previewUrl(), 'title': api.l10n.previewIframeTitle } ).hide(); - iframe.appendTo( self.container ); - iframe.on( 'load', function() { - self.triedLogin = true; - - iframe.remove(); - self.run( deferred ); - }); - }); - }, - - destroy: function() { - api.Messenger.prototype.destroy.call( this ); - - if ( this.iframe ) { - this.iframe.remove(); - } - - delete this.iframe; - delete this.targetWindow; - } - }); - - (function(){ - var id = 0; - /** - * Return an incremented ID for a preview messenger channel. - * - * This function is named "uuid" for historical reasons, but it is a - * misnomer as it is not an actual UUID, and it is not universally unique. - * This is not to be confused with `api.settings.changeset.uuid`. - * - * @return {string} - */ - api.PreviewFrame.uuid = function() { - return 'preview-' + String( id++ ); - }; - }()); - - /** - * Set the document title of the customizer. - * - * @alias wp.customize.setDocumentTitle - * - * @since 4.1.0 - * - * @param {string} documentTitle - */ - api.setDocumentTitle = function ( documentTitle ) { - var tmpl, title; - tmpl = api.settings.documentTitleTmpl; - title = tmpl.replace( '%s', documentTitle ); - document.title = title; - api.trigger( 'title', title ); - }; - - api.Previewer = api.Messenger.extend(/** @lends wp.customize.Previewer.prototype */{ - refreshBuffer: null, // Will get set to api.settings.timeouts.windowRefresh. - - /** - * @constructs wp.customize.Previewer - * @augments wp.customize.Messenger - * - * @param {array} params.allowedUrls - * @param {string} params.container A selector or jQuery element for the preview - * frame to be placed. - * @param {string} params.form - * @param {string} params.previewUrl The URL to preview. - * @param {object} options - */ - initialize: function( params, options ) { - var previewer = this, - urlParser = document.createElement( 'a' ); - - $.extend( previewer, options || {} ); - previewer.deferred = { - active: $.Deferred() - }; - - // Debounce to prevent hammering server and then wait for any pending update requests. - previewer.refresh = _.debounce( - ( function( originalRefresh ) { - return function() { - var isProcessingComplete, refreshOnceProcessingComplete; - isProcessingComplete = function() { - return 0 === api.state( 'processing' ).get(); - }; - if ( isProcessingComplete() ) { - originalRefresh.call( previewer ); - } else { - refreshOnceProcessingComplete = function() { - if ( isProcessingComplete() ) { - originalRefresh.call( previewer ); - api.state( 'processing' ).unbind( refreshOnceProcessingComplete ); - } - }; - api.state( 'processing' ).bind( refreshOnceProcessingComplete ); - } - }; - }( previewer.refresh ) ), - previewer.refreshBuffer - ); - - previewer.container = api.ensure( params.container ); - previewer.allowedUrls = params.allowedUrls; - - params.url = window.location.href; - - api.Messenger.prototype.initialize.call( previewer, params ); - - urlParser.href = previewer.origin(); - previewer.add( 'scheme', urlParser.protocol.replace( /:$/, '' ) ); - - // Limit the URL to internal, front-end links. - // - // If the front end and the admin are served from the same domain, load the - // preview over ssl if the Customizer is being loaded over ssl. This avoids - // insecure content warnings. This is not attempted if the admin and front end - // are on different domains to avoid the case where the front end doesn't have - // ssl certs. - - previewer.add( 'previewUrl', params.previewUrl ).setter( function( to ) { - var result = null, urlParser, queryParams, parsedAllowedUrl, parsedCandidateUrls = []; - urlParser = document.createElement( 'a' ); - urlParser.href = to; - - // Abort if URL is for admin or (static) files in wp-includes or wp-content. - if ( /\/wp-(admin|includes|content)(\/|$)/.test( urlParser.pathname ) ) { - return null; - } - - // Remove state query params. - if ( urlParser.search.length > 1 ) { - queryParams = api.utils.parseQueryString( urlParser.search.substr( 1 ) ); - delete queryParams.customize_changeset_uuid; - delete queryParams.customize_theme; - delete queryParams.customize_messenger_channel; - delete queryParams.customize_autosaved; - if ( _.isEmpty( queryParams ) ) { - urlParser.search = ''; - } else { - urlParser.search = $.param( queryParams ); - } - } - - parsedCandidateUrls.push( urlParser ); - - // Prepend list with URL that matches the scheme/protocol of the iframe. - if ( previewer.scheme.get() + ':' !== urlParser.protocol ) { - urlParser = document.createElement( 'a' ); - urlParser.href = parsedCandidateUrls[0].href; - urlParser.protocol = previewer.scheme.get() + ':'; - parsedCandidateUrls.unshift( urlParser ); - } - - // Attempt to match the URL to the control frame's scheme and check if it's allowed. If not, try the original URL. - parsedAllowedUrl = document.createElement( 'a' ); - _.find( parsedCandidateUrls, function( parsedCandidateUrl ) { - return ! _.isUndefined( _.find( previewer.allowedUrls, function( allowedUrl ) { - parsedAllowedUrl.href = allowedUrl; - if ( urlParser.protocol === parsedAllowedUrl.protocol && urlParser.host === parsedAllowedUrl.host && 0 === urlParser.pathname.indexOf( parsedAllowedUrl.pathname.replace( /\/$/, '' ) ) ) { - result = parsedCandidateUrl.href; - return true; - } - } ) ); - } ); - - return result; - }); - - previewer.bind( 'ready', previewer.ready ); - - // Start listening for keep-alive messages when iframe first loads. - previewer.deferred.active.done( _.bind( previewer.keepPreviewAlive, previewer ) ); - - previewer.bind( 'synced', function() { - previewer.send( 'active' ); - } ); - - // Refresh the preview when the URL is changed (but not yet). - previewer.previewUrl.bind( previewer.refresh ); - - previewer.scroll = 0; - previewer.bind( 'scroll', function( distance ) { - previewer.scroll = distance; - }); - - // Update the URL when the iframe sends a URL message, resetting scroll position. If URL is unchanged, then refresh. - previewer.bind( 'url', function( url ) { - var onUrlChange, urlChanged = false; - previewer.scroll = 0; - onUrlChange = function() { - urlChanged = true; - }; - previewer.previewUrl.bind( onUrlChange ); - previewer.previewUrl.set( url ); - previewer.previewUrl.unbind( onUrlChange ); - if ( ! urlChanged ) { - previewer.refresh(); - } - } ); - - // Update the document title when the preview changes. - previewer.bind( 'documentTitle', function ( title ) { - api.setDocumentTitle( title ); - } ); - }, - - /** - * Handle the preview receiving the ready message. - * - * @since 4.7.0 - * @access public - * - * @param {object} data - Data from preview. - * @param {string} data.currentUrl - Current URL. - * @param {object} data.activePanels - Active panels. - * @param {object} data.activeSections Active sections. - * @param {object} data.activeControls Active controls. - * @returns {void} - */ - ready: function( data ) { - var previewer = this, synced = {}, constructs; - - synced.settings = api.get(); - synced['settings-modified-while-loading'] = previewer.settingsModifiedWhileLoading; - if ( 'resolved' !== previewer.deferred.active.state() || previewer.loading ) { - synced.scroll = previewer.scroll; - } - synced['edit-shortcut-visibility'] = api.state( 'editShortcutVisibility' ).get(); - previewer.send( 'sync', synced ); - - // Set the previewUrl without causing the url to set the iframe. - if ( data.currentUrl ) { - previewer.previewUrl.unbind( previewer.refresh ); - previewer.previewUrl.set( data.currentUrl ); - previewer.previewUrl.bind( previewer.refresh ); - } - - /* - * Walk over all panels, sections, and controls and set their - * respective active states to true if the preview explicitly - * indicates as such. - */ - constructs = { - panel: data.activePanels, - section: data.activeSections, - control: data.activeControls - }; - _( constructs ).each( function ( activeConstructs, type ) { - api[ type ].each( function ( construct, id ) { - var isDynamicallyCreated = _.isUndefined( api.settings[ type + 's' ][ id ] ); - - /* - * If the construct was created statically in PHP (not dynamically in JS) - * then consider a missing (undefined) value in the activeConstructs to - * mean it should be deactivated (since it is gone). But if it is - * dynamically created then only toggle activation if the value is defined, - * as this means that the construct was also then correspondingly - * created statically in PHP and the active callback is available. - * Otherwise, dynamically-created constructs should normally have - * their active states toggled in JS rather than from PHP. - */ - if ( ! isDynamicallyCreated || ! _.isUndefined( activeConstructs[ id ] ) ) { - if ( activeConstructs[ id ] ) { - construct.activate(); - } else { - construct.deactivate(); - } - } - } ); - } ); - - if ( data.settingValidities ) { - api._handleSettingValidities( { - settingValidities: data.settingValidities, - focusInvalidControl: false - } ); - } - }, - - /** - * Keep the preview alive by listening for ready and keep-alive messages. - * - * If a message is not received in the allotted time then the iframe will be set back to the last known valid URL. - * - * @since 4.7.0 - * @access public - * - * @returns {void} - */ - keepPreviewAlive: function keepPreviewAlive() { - var previewer = this, keepAliveTick, timeoutId, handleMissingKeepAlive, scheduleKeepAliveCheck; - - /** - * Schedule a preview keep-alive check. - * - * Note that if a page load takes longer than keepAliveCheck milliseconds, - * the keep-alive messages will still be getting sent from the previous - * URL. - */ - scheduleKeepAliveCheck = function() { - timeoutId = setTimeout( handleMissingKeepAlive, api.settings.timeouts.keepAliveCheck ); - }; - - /** - * Set the previewerAlive state to true when receiving a message from the preview. - */ - keepAliveTick = function() { - api.state( 'previewerAlive' ).set( true ); - clearTimeout( timeoutId ); - scheduleKeepAliveCheck(); - }; - - /** - * Set the previewerAlive state to false if keepAliveCheck milliseconds have transpired without a message. - * - * This is most likely to happen in the case of a connectivity error, or if the theme causes the browser - * to navigate to a non-allowed URL. Setting this state to false will force settings with a postMessage - * transport to use refresh instead, causing the preview frame also to be replaced with the current - * allowed preview URL. - */ - handleMissingKeepAlive = function() { - api.state( 'previewerAlive' ).set( false ); - }; - scheduleKeepAliveCheck(); - - previewer.bind( 'ready', keepAliveTick ); - previewer.bind( 'keep-alive', keepAliveTick ); - }, - - /** - * Query string data sent with each preview request. - * - * @abstract - */ - query: function() {}, - - abort: function() { - if ( this.loading ) { - this.loading.destroy(); - delete this.loading; - } - }, - - /** - * Refresh the preview seamlessly. - * - * @since 3.4.0 - * @access public - * @returns {void} - */ - refresh: function() { - var previewer = this, onSettingChange; - - // Display loading indicator - previewer.send( 'loading-initiated' ); - - previewer.abort(); - - previewer.loading = new api.PreviewFrame({ - url: previewer.url(), - previewUrl: previewer.previewUrl(), - query: previewer.query( { excludeCustomizedSaved: true } ) || {}, - container: previewer.container - }); - - previewer.settingsModifiedWhileLoading = {}; - onSettingChange = function( setting ) { - previewer.settingsModifiedWhileLoading[ setting.id ] = true; - }; - api.bind( 'change', onSettingChange ); - previewer.loading.always( function() { - api.unbind( 'change', onSettingChange ); - } ); - - previewer.loading.done( function( readyData ) { - var loadingFrame = this, onceSynced; - - previewer.preview = loadingFrame; - previewer.targetWindow( loadingFrame.targetWindow() ); - previewer.channel( loadingFrame.channel() ); - - onceSynced = function() { - loadingFrame.unbind( 'synced', onceSynced ); - if ( previewer._previousPreview ) { - previewer._previousPreview.destroy(); - } - previewer._previousPreview = previewer.preview; - previewer.deferred.active.resolve(); - delete previewer.loading; - }; - loadingFrame.bind( 'synced', onceSynced ); - - // This event will be received directly by the previewer in normal navigation; this is only needed for seamless refresh. - previewer.trigger( 'ready', readyData ); - }); - - previewer.loading.fail( function( reason ) { - previewer.send( 'loading-failed' ); - - if ( 'logged out' === reason ) { - if ( previewer.preview ) { - previewer.preview.destroy(); - delete previewer.preview; - } - - previewer.login().done( previewer.refresh ); - } - - if ( 'cheatin' === reason ) { - previewer.cheatin(); - } - }); - }, - - login: function() { - var previewer = this, - deferred, messenger, iframe; - - if ( this._login ) { - return this._login; - } - - deferred = $.Deferred(); - this._login = deferred.promise(); - - messenger = new api.Messenger({ - channel: 'login', - url: api.settings.url.login - }); - - iframe = $( '<iframe />', { 'src': api.settings.url.login, 'title': api.l10n.loginIframeTitle } ).appendTo( this.container ); - - messenger.targetWindow( iframe[0].contentWindow ); - - messenger.bind( 'login', function () { - var refreshNonces = previewer.refreshNonces(); - - refreshNonces.always( function() { - iframe.remove(); - messenger.destroy(); - delete previewer._login; - }); - - refreshNonces.done( function() { - deferred.resolve(); - }); - - refreshNonces.fail( function() { - previewer.cheatin(); - deferred.reject(); - }); - }); - - return this._login; - }, - - cheatin: function() { - $( document.body ).empty().addClass( 'cheatin' ).append( - '<h1>' + api.l10n.notAllowedHeading + '</h1>' + - '<p>' + api.l10n.notAllowed + '</p>' - ); - }, - - refreshNonces: function() { - var request, deferred = $.Deferred(); - - deferred.promise(); - - request = wp.ajax.post( 'customize_refresh_nonces', { - wp_customize: 'on', - customize_theme: api.settings.theme.stylesheet - }); - - request.done( function( response ) { - api.trigger( 'nonce-refresh', response ); - deferred.resolve(); - }); - - request.fail( function() { - deferred.reject(); - }); - - return deferred; - } - }); - - api.settingConstructor = {}; - api.controlConstructor = { - color: api.ColorControl, - media: api.MediaControl, - upload: api.UploadControl, - image: api.ImageControl, - cropped_image: api.CroppedImageControl, - site_icon: api.SiteIconControl, - header: api.HeaderControl, - background: api.BackgroundControl, - background_position: api.BackgroundPositionControl, - theme: api.ThemeControl, - date_time: api.DateTimeControl, - code_editor: api.CodeEditorControl - }; - api.panelConstructor = { - themes: api.ThemesPanel - }; - api.sectionConstructor = { - themes: api.ThemesSection, - outer: api.OuterSection - }; - - /** - * Handle setting_validities in an error response for the customize-save request. - * - * Add notifications to the settings and focus on the first control that has an invalid setting. - * - * @alias wp.customize._handleSettingValidities - * - * @since 4.6.0 - * @private - * - * @param {object} args - * @param {object} args.settingValidities - * @param {boolean} [args.focusInvalidControl=false] - * @returns {void} - */ - api._handleSettingValidities = function handleSettingValidities( args ) { - var invalidSettingControls, invalidSettings = [], wasFocused = false; - - // Find the controls that correspond to each invalid setting. - _.each( args.settingValidities, function( validity, settingId ) { - var setting = api( settingId ); - if ( setting ) { - - // Add notifications for invalidities. - if ( _.isObject( validity ) ) { - _.each( validity, function( params, code ) { - var notification, existingNotification, needsReplacement = false; - notification = new api.Notification( code, _.extend( { fromServer: true }, params ) ); - - // Remove existing notification if already exists for code but differs in parameters. - existingNotification = setting.notifications( notification.code ); - if ( existingNotification ) { - needsReplacement = notification.type !== existingNotification.type || notification.message !== existingNotification.message || ! _.isEqual( notification.data, existingNotification.data ); - } - if ( needsReplacement ) { - setting.notifications.remove( code ); - } - - if ( ! setting.notifications.has( notification.code ) ) { - setting.notifications.add( notification ); - } - invalidSettings.push( setting.id ); - } ); - } - - // Remove notification errors that are no longer valid. - setting.notifications.each( function( notification ) { - if ( notification.fromServer && 'error' === notification.type && ( true === validity || ! validity[ notification.code ] ) ) { - setting.notifications.remove( notification.code ); - } - } ); - } - } ); - - if ( args.focusInvalidControl ) { - invalidSettingControls = api.findControlsForSettings( invalidSettings ); - - // Focus on the first control that is inside of an expanded section (one that is visible). - _( _.values( invalidSettingControls ) ).find( function( controls ) { - return _( controls ).find( function( control ) { - var isExpanded = control.section() && api.section.has( control.section() ) && api.section( control.section() ).expanded(); - if ( isExpanded && control.expanded ) { - isExpanded = control.expanded(); - } - if ( isExpanded ) { - control.focus(); - wasFocused = true; - } - return wasFocused; - } ); - } ); - - // Focus on the first invalid control. - if ( ! wasFocused && ! _.isEmpty( invalidSettingControls ) ) { - _.values( invalidSettingControls )[0][0].focus(); - } - } - }; - - /** - * Find all controls associated with the given settings. - * - * @alias wp.customize.findControlsForSettings - * - * @since 4.6.0 - * @param {string[]} settingIds Setting IDs. - * @returns {object<string, wp.customize.Control>} Mapping setting ids to arrays of controls. - */ - api.findControlsForSettings = function findControlsForSettings( settingIds ) { - var controls = {}, settingControls; - _.each( _.unique( settingIds ), function( settingId ) { - var setting = api( settingId ); - if ( setting ) { - settingControls = setting.findControls(); - if ( settingControls && settingControls.length > 0 ) { - controls[ settingId ] = settingControls; - } - } - } ); - return controls; - }; - - /** - * Sort panels, sections, controls by priorities. Hide empty sections and panels. - * - * @alias wp.customize.reflowPaneContents - * - * @since 4.1.0 - */ - api.reflowPaneContents = _.bind( function () { - - var appendContainer, activeElement, rootHeadContainers, rootNodes = [], wasReflowed = false; - - if ( document.activeElement ) { - activeElement = $( document.activeElement ); - } - - // Sort the sections within each panel - api.panel.each( function ( panel ) { - if ( 'themes' === panel.id ) { - return; // Don't reflow theme sections, as doing so moves them after the themes container. - } - - var sections = panel.sections(), - sectionHeadContainers = _.pluck( sections, 'headContainer' ); - rootNodes.push( panel ); - appendContainer = ( panel.contentContainer.is( 'ul' ) ) ? panel.contentContainer : panel.contentContainer.find( 'ul:first' ); - if ( ! api.utils.areElementListsEqual( sectionHeadContainers, appendContainer.children( '[id]' ) ) ) { - _( sections ).each( function ( section ) { - appendContainer.append( section.headContainer ); - } ); - wasReflowed = true; - } - } ); - - // Sort the controls within each section - api.section.each( function ( section ) { - var controls = section.controls(), - controlContainers = _.pluck( controls, 'container' ); - if ( ! section.panel() ) { - rootNodes.push( section ); - } - appendContainer = ( section.contentContainer.is( 'ul' ) ) ? section.contentContainer : section.contentContainer.find( 'ul:first' ); - if ( ! api.utils.areElementListsEqual( controlContainers, appendContainer.children( '[id]' ) ) ) { - _( controls ).each( function ( control ) { - appendContainer.append( control.container ); - } ); - wasReflowed = true; - } - } ); - - // Sort the root panels and sections - rootNodes.sort( api.utils.prioritySort ); - rootHeadContainers = _.pluck( rootNodes, 'headContainer' ); - appendContainer = $( '#customize-theme-controls .customize-pane-parent' ); // @todo This should be defined elsewhere, and to be configurable - if ( ! api.utils.areElementListsEqual( rootHeadContainers, appendContainer.children() ) ) { - _( rootNodes ).each( function ( rootNode ) { - appendContainer.append( rootNode.headContainer ); - } ); - wasReflowed = true; - } - - // Now re-trigger the active Value callbacks to that the panels and sections can decide whether they can be rendered - api.panel.each( function ( panel ) { - var value = panel.active(); - panel.active.callbacks.fireWith( panel.active, [ value, value ] ); - } ); - api.section.each( function ( section ) { - var value = section.active(); - section.active.callbacks.fireWith( section.active, [ value, value ] ); - } ); - - // Restore focus if there was a reflow and there was an active (focused) element - if ( wasReflowed && activeElement ) { - activeElement.focus(); - } - api.trigger( 'pane-contents-reflowed' ); - }, api ); - - // Define state values. - api.state = new api.Values(); - _.each( [ - 'saved', - 'saving', - 'trashing', - 'activated', - 'processing', - 'paneVisible', - 'expandedPanel', - 'expandedSection', - 'changesetDate', - 'selectedChangesetDate', - 'changesetStatus', - 'selectedChangesetStatus', - 'remainingTimeToPublish', - 'previewerAlive', - 'editShortcutVisibility', - 'changesetLocked', - 'previewedDevice' - ], function( name ) { - api.state.create( name ); - }); - - $( function() { - api.settings = window._wpCustomizeSettings; - api.l10n = window._wpCustomizeControlsL10n; - - // Check if we can run the Customizer. - if ( ! api.settings ) { - return; - } - - // Bail if any incompatibilities are found. - if ( ! $.support.postMessage || ( ! $.support.cors && api.settings.isCrossDomain ) ) { - return; - } - - if ( null === api.PreviewFrame.prototype.sensitivity ) { - api.PreviewFrame.prototype.sensitivity = api.settings.timeouts.previewFrameSensitivity; - } - if ( null === api.Previewer.prototype.refreshBuffer ) { - api.Previewer.prototype.refreshBuffer = api.settings.timeouts.windowRefresh; - } - - var parent, - body = $( document.body ), - overlay = body.children( '.wp-full-overlay' ), - title = $( '#customize-info .panel-title.site-title' ), - closeBtn = $( '.customize-controls-close' ), - saveBtn = $( '#save' ), - btnWrapper = $( '#customize-save-button-wrapper' ), - publishSettingsBtn = $( '#publish-settings' ), - footerActions = $( '#customize-footer-actions' ); - - // Add publish settings section in JS instead of PHP since the Customizer depends on it to function. - api.bind( 'ready', function() { - api.section.add( new api.OuterSection( 'publish_settings', { - title: api.l10n.publishSettings, - priority: 0, - active: api.settings.theme.active - } ) ); - } ); - - // Set up publish settings section and its controls. - api.section( 'publish_settings', function( section ) { - var updateButtonsState, trashControl, updateSectionActive, isSectionActive, statusControl, dateControl, toggleDateControl, publishWhenTime, pollInterval, updateTimeArrivedPoller, cancelScheduleButtonReminder, timeArrivedPollingInterval = 1000; - - trashControl = new api.Control( 'trash_changeset', { - type: 'button', - section: section.id, - priority: 30, - input_attrs: { - 'class': 'button-link button-link-delete', - value: api.l10n.discardChanges - } - } ); - api.control.add( trashControl ); - trashControl.deferred.embedded.done( function() { - trashControl.container.find( '.button-link' ).on( 'click', function() { - if ( confirm( api.l10n.trashConfirm ) ) { - wp.customize.previewer.trash(); - } - } ); - } ); - - api.control.add( new api.PreviewLinkControl( 'changeset_preview_link', { - section: section.id, - priority: 100 - } ) ); - - /** - * Return whether the pubish settings section should be active. - * - * @return {boolean} Is section active. - */ - isSectionActive = function() { - if ( ! api.state( 'activated' ).get() ) { - return false; - } - if ( api.state( 'trashing' ).get() || 'trash' === api.state( 'changesetStatus' ).get() ) { - return false; - } - if ( '' === api.state( 'changesetStatus' ).get() && api.state( 'saved' ).get() ) { - return false; - } - return true; - }; - - // Make sure publish settings are not available while the theme is not active and the customizer is in a published state. - section.active.validate = isSectionActive; - updateSectionActive = function() { - section.active.set( isSectionActive() ); - }; - api.state( 'activated' ).bind( updateSectionActive ); - api.state( 'trashing' ).bind( updateSectionActive ); - api.state( 'saved' ).bind( updateSectionActive ); - api.state( 'changesetStatus' ).bind( updateSectionActive ); - updateSectionActive(); - - // Bind visibility of the publish settings button to whether the section is active. - updateButtonsState = function() { - publishSettingsBtn.toggle( section.active.get() ); - saveBtn.toggleClass( 'has-next-sibling', section.active.get() ); - }; - updateButtonsState(); - section.active.bind( updateButtonsState ); - - function highlightScheduleButton() { - if ( ! cancelScheduleButtonReminder ) { - cancelScheduleButtonReminder = api.utils.highlightButton( btnWrapper, { - delay: 1000, - - // Only abort the reminder when the save button is focused. - // If the user clicks the settings button to toggle the - // settings closed, we'll still remind them. - focusTarget: saveBtn - } ); - } - } - function cancelHighlightScheduleButton() { - if ( cancelScheduleButtonReminder ) { - cancelScheduleButtonReminder(); - cancelScheduleButtonReminder = null; - } - } - api.state( 'selectedChangesetStatus' ).bind( cancelHighlightScheduleButton ); - - section.contentContainer.find( '.customize-action' ).text( api.l10n.updating ); - section.contentContainer.find( '.customize-section-back' ).removeAttr( 'tabindex' ); - publishSettingsBtn.prop( 'disabled', false ); - - publishSettingsBtn.on( 'click', function( event ) { - event.preventDefault(); - section.expanded.set( ! section.expanded.get() ); - } ); - - section.expanded.bind( function( isExpanded ) { - var defaultChangesetStatus; - publishSettingsBtn.attr( 'aria-expanded', String( isExpanded ) ); - publishSettingsBtn.toggleClass( 'active', isExpanded ); - - if ( isExpanded ) { - cancelHighlightScheduleButton(); - return; - } - - defaultChangesetStatus = api.state( 'changesetStatus' ).get(); - if ( '' === defaultChangesetStatus || 'auto-draft' === defaultChangesetStatus ) { - defaultChangesetStatus = 'publish'; - } - - if ( api.state( 'selectedChangesetStatus' ).get() !== defaultChangesetStatus ) { - highlightScheduleButton(); - } else if ( 'future' === api.state( 'selectedChangesetStatus' ).get() && api.state( 'selectedChangesetDate' ).get() !== api.state( 'changesetDate' ).get() ) { - highlightScheduleButton(); - } - } ); - - statusControl = new api.Control( 'changeset_status', { - priority: 10, - type: 'radio', - section: 'publish_settings', - setting: api.state( 'selectedChangesetStatus' ), - templateId: 'customize-selected-changeset-status-control', - label: api.l10n.action, - choices: api.settings.changeset.statusChoices - } ); - api.control.add( statusControl ); - - dateControl = new api.DateTimeControl( 'changeset_scheduled_date', { - priority: 20, - section: 'publish_settings', - setting: api.state( 'selectedChangesetDate' ), - minYear: ( new Date() ).getFullYear(), - allowPastDate: false, - includeTime: true, - twelveHourFormat: /a/i.test( api.settings.timeFormat ), - description: api.l10n.scheduleDescription - } ); - dateControl.notifications.alt = true; - api.control.add( dateControl ); - - publishWhenTime = function() { - api.state( 'selectedChangesetStatus' ).set( 'publish' ); - api.previewer.save(); - }; - - // Start countdown for when the dateTime arrives, or clear interval when it is . - updateTimeArrivedPoller = function() { - var shouldPoll = ( - 'future' === api.state( 'changesetStatus' ).get() && - 'future' === api.state( 'selectedChangesetStatus' ).get() && - api.state( 'changesetDate' ).get() && - api.state( 'selectedChangesetDate' ).get() === api.state( 'changesetDate' ).get() && - api.utils.getRemainingTime( api.state( 'changesetDate' ).get() ) >= 0 - ); - - if ( shouldPoll && ! pollInterval ) { - pollInterval = setInterval( function() { - var remainingTime = api.utils.getRemainingTime( api.state( 'changesetDate' ).get() ); - api.state( 'remainingTimeToPublish' ).set( remainingTime ); - if ( remainingTime <= 0 ) { - clearInterval( pollInterval ); - pollInterval = 0; - publishWhenTime(); - } - }, timeArrivedPollingInterval ); - } else if ( ! shouldPoll && pollInterval ) { - clearInterval( pollInterval ); - pollInterval = 0; - } - }; - - api.state( 'changesetDate' ).bind( updateTimeArrivedPoller ); - api.state( 'selectedChangesetDate' ).bind( updateTimeArrivedPoller ); - api.state( 'changesetStatus' ).bind( updateTimeArrivedPoller ); - api.state( 'selectedChangesetStatus' ).bind( updateTimeArrivedPoller ); - updateTimeArrivedPoller(); - - // Ensure dateControl only appears when selected status is future. - dateControl.active.validate = function() { - return 'future' === api.state( 'selectedChangesetStatus' ).get(); - }; - toggleDateControl = function( value ) { - dateControl.active.set( 'future' === value ); - }; - toggleDateControl( api.state( 'selectedChangesetStatus' ).get() ); - api.state( 'selectedChangesetStatus' ).bind( toggleDateControl ); - - // Show notification on date control when status is future but it isn't a future date. - api.state( 'saving' ).bind( function( isSaving ) { - if ( isSaving && 'future' === api.state( 'selectedChangesetStatus' ).get() ) { - dateControl.toggleFutureDateNotification( ! dateControl.isFutureDate() ); - } - } ); - } ); - - // Prevent the form from saving when enter is pressed on an input or select element. - $('#customize-controls').on( 'keydown', function( e ) { - var isEnter = ( 13 === e.which ), - $el = $( e.target ); - - if ( isEnter && ( $el.is( 'input:not([type=button])' ) || $el.is( 'select' ) ) ) { - e.preventDefault(); - } - }); - - // Expand/Collapse the main customizer customize info. - $( '.customize-info' ).find( '> .accordion-section-title .customize-help-toggle' ).on( 'click', function() { - var section = $( this ).closest( '.accordion-section' ), - content = section.find( '.customize-panel-description:first' ); - - if ( section.hasClass( 'cannot-expand' ) ) { - return; - } - - if ( section.hasClass( 'open' ) ) { - section.toggleClass( 'open' ); - content.slideUp( api.Panel.prototype.defaultExpandedArguments.duration, function() { - content.trigger( 'toggled' ); - } ); - $( this ).attr( 'aria-expanded', false ); - } else { - content.slideDown( api.Panel.prototype.defaultExpandedArguments.duration, function() { - content.trigger( 'toggled' ); - } ); - section.toggleClass( 'open' ); - $( this ).attr( 'aria-expanded', true ); - } - }); - - /** - * Initialize Previewer - * - * @alias wp.customize.previewer - */ - api.previewer = new api.Previewer({ - container: '#customize-preview', - form: '#customize-controls', - previewUrl: api.settings.url.preview, - allowedUrls: api.settings.url.allowed - },/** @lends wp.customize.previewer */{ - - nonce: api.settings.nonce, - - /** - * Build the query to send along with the Preview request. - * - * @since 3.4.0 - * @since 4.7.0 Added options param. - * @access public - * - * @param {object} [options] Options. - * @param {boolean} [options.excludeCustomizedSaved=false] Exclude saved settings in customized response (values pending writing to changeset). - * @return {object} Query vars. - */ - query: function( options ) { - var queryVars = { - wp_customize: 'on', - customize_theme: api.settings.theme.stylesheet, - nonce: this.nonce.preview, - customize_changeset_uuid: api.settings.changeset.uuid - }; - if ( api.settings.changeset.autosaved || ! api.state( 'saved' ).get() ) { - queryVars.customize_autosaved = 'on'; - } - - /* - * Exclude customized data if requested especially for calls to requestChangesetUpdate. - * Changeset updates are differential and so it is a performance waste to send all of - * the dirty settings with each update. - */ - queryVars.customized = JSON.stringify( api.dirtyValues( { - unsaved: options && options.excludeCustomizedSaved - } ) ); - - return queryVars; - }, - - /** - * Save (and publish) the customizer changeset. - * - * Updates to the changeset are transactional. If any of the settings - * are invalid then none of them will be written into the changeset. - * A revision will be made for the changeset post if revisions support - * has been added to the post type. - * - * @since 3.4.0 - * @since 4.7.0 Added args param and return value. - * - * @param {object} [args] Args. - * @param {string} [args.status=publish] Status. - * @param {string} [args.date] Date, in local time in MySQL format. - * @param {string} [args.title] Title - * @returns {jQuery.promise} Promise. - */ - save: function( args ) { - var previewer = this, - deferred = $.Deferred(), - changesetStatus = api.state( 'selectedChangesetStatus' ).get(), - selectedChangesetDate = api.state( 'selectedChangesetDate' ).get(), - processing = api.state( 'processing' ), - submitWhenDoneProcessing, - submit, - modifiedWhileSaving = {}, - invalidSettings = [], - invalidControls = [], - invalidSettingLessControls = []; - - if ( args && args.status ) { - changesetStatus = args.status; - } - - if ( api.state( 'saving' ).get() ) { - deferred.reject( 'already_saving' ); - deferred.promise(); - } - - api.state( 'saving' ).set( true ); - - function captureSettingModifiedDuringSave( setting ) { - modifiedWhileSaving[ setting.id ] = true; - } - - submit = function () { - var request, query, settingInvalidities = {}, latestRevision = api._latestRevision, errorCode = 'client_side_error'; - - api.bind( 'change', captureSettingModifiedDuringSave ); - api.notifications.remove( errorCode ); - - /* - * Block saving if there are any settings that are marked as - * invalid from the client (not from the server). Focus on - * the control. - */ - api.each( function( setting ) { - setting.notifications.each( function( notification ) { - if ( 'error' === notification.type && ! notification.fromServer ) { - invalidSettings.push( setting.id ); - if ( ! settingInvalidities[ setting.id ] ) { - settingInvalidities[ setting.id ] = {}; - } - settingInvalidities[ setting.id ][ notification.code ] = notification; - } - } ); - } ); - - // Find all invalid setting less controls with notification type error. - api.control.each( function( control ) { - if ( ! control.setting || ! control.setting.id && control.active.get() ) { - control.notifications.each( function( notification ) { - if ( 'error' === notification.type ) { - invalidSettingLessControls.push( [ control ] ); - } - } ); - } - } ); - - invalidControls = _.union( invalidSettingLessControls, _.values( api.findControlsForSettings( invalidSettings ) ) ); - if ( ! _.isEmpty( invalidControls ) ) { - - invalidControls[0][0].focus(); - api.unbind( 'change', captureSettingModifiedDuringSave ); - - if ( invalidSettings.length ) { - api.notifications.add( new api.Notification( errorCode, { - message: ( 1 === invalidSettings.length ? api.l10n.saveBlockedError.singular : api.l10n.saveBlockedError.plural ).replace( /%s/g, String( invalidSettings.length ) ), - type: 'error', - dismissible: true, - saveFailure: true - } ) ); - } - - deferred.rejectWith( previewer, [ - { setting_invalidities: settingInvalidities } - ] ); - api.state( 'saving' ).set( false ); - return deferred.promise(); - } - - /* - * Note that excludeCustomizedSaved is intentionally false so that the entire - * set of customized data will be included if bypassed changeset update. - */ - query = $.extend( previewer.query( { excludeCustomizedSaved: false } ), { - nonce: previewer.nonce.save, - customize_changeset_status: changesetStatus - } ); - - if ( args && args.date ) { - query.customize_changeset_date = args.date; - } else if ( 'future' === changesetStatus && selectedChangesetDate ) { - query.customize_changeset_date = selectedChangesetDate; - } - - if ( args && args.title ) { - query.customize_changeset_title = args.title; - } - - // Allow plugins to modify the params included with the save request. - api.trigger( 'save-request-params', query ); - - /* - * Note that the dirty customized values will have already been set in the - * changeset and so technically query.customized could be deleted. However, - * it is remaining here to make sure that any settings that got updated - * quietly which may have not triggered an update request will also get - * included in the values that get saved to the changeset. This will ensure - * that values that get injected via the saved event will be included in - * the changeset. This also ensures that setting values that were invalid - * will get re-validated, perhaps in the case of settings that are invalid - * due to dependencies on other settings. - */ - request = wp.ajax.post( 'customize_save', query ); - api.state( 'processing' ).set( api.state( 'processing' ).get() + 1 ); - - api.trigger( 'save', request ); - - request.always( function () { - api.state( 'processing' ).set( api.state( 'processing' ).get() - 1 ); - api.state( 'saving' ).set( false ); - api.unbind( 'change', captureSettingModifiedDuringSave ); - } ); - - // Remove notifications that were added due to save failures. - api.notifications.each( function( notification ) { - if ( notification.saveFailure ) { - api.notifications.remove( notification.code ); - } - }); - - request.fail( function ( response ) { - var notification, notificationArgs; - notificationArgs = { - type: 'error', - dismissible: true, - fromServer: true, - saveFailure: true - }; - - if ( '0' === response ) { - response = 'not_logged_in'; - } else if ( '-1' === response ) { - // Back-compat in case any other check_ajax_referer() call is dying - response = 'invalid_nonce'; - } - - if ( 'invalid_nonce' === response ) { - previewer.cheatin(); - } else if ( 'not_logged_in' === response ) { - previewer.preview.iframe.hide(); - previewer.login().done( function() { - previewer.save(); - previewer.preview.iframe.show(); - } ); - } else if ( response.code ) { - if ( 'not_future_date' === response.code && api.section.has( 'publish_settings' ) && api.section( 'publish_settings' ).active.get() && api.control.has( 'changeset_scheduled_date' ) ) { - api.control( 'changeset_scheduled_date' ).toggleFutureDateNotification( true ).focus(); - } else if ( 'changeset_locked' !== response.code ) { - notification = new api.Notification( response.code, _.extend( notificationArgs, { - message: response.message - } ) ); - } - } else { - notification = new api.Notification( 'unknown_error', _.extend( notificationArgs, { - message: api.l10n.unknownRequestFail - } ) ); - } - - if ( notification ) { - api.notifications.add( notification ); - } - - if ( response.setting_validities ) { - api._handleSettingValidities( { - settingValidities: response.setting_validities, - focusInvalidControl: true - } ); - } - - deferred.rejectWith( previewer, [ response ] ); - api.trigger( 'error', response ); - - // Start a new changeset if the underlying changeset was published. - if ( 'changeset_already_published' === response.code && response.next_changeset_uuid ) { - api.settings.changeset.uuid = response.next_changeset_uuid; - api.state( 'changesetStatus' ).set( '' ); - if ( api.settings.changeset.branching ) { - parent.send( 'changeset-uuid', api.settings.changeset.uuid ); - } - api.previewer.send( 'changeset-uuid', api.settings.changeset.uuid ); - } - } ); - - request.done( function( response ) { - - previewer.send( 'saved', response ); - - api.state( 'changesetStatus' ).set( response.changeset_status ); - if ( response.changeset_date ) { - api.state( 'changesetDate' ).set( response.changeset_date ); - } - - if ( 'publish' === response.changeset_status ) { - - // Mark all published as clean if they haven't been modified during the request. - api.each( function( setting ) { - /* - * Note that the setting revision will be undefined in the case of setting - * values that are marked as dirty when the customizer is loaded, such as - * when applying starter content. All other dirty settings will have an - * associated revision due to their modification triggering a change event. - */ - if ( setting._dirty && ( _.isUndefined( api._latestSettingRevisions[ setting.id ] ) || api._latestSettingRevisions[ setting.id ] <= latestRevision ) ) { - setting._dirty = false; - } - } ); - - api.state( 'changesetStatus' ).set( '' ); - api.settings.changeset.uuid = response.next_changeset_uuid; - if ( api.settings.changeset.branching ) { - parent.send( 'changeset-uuid', api.settings.changeset.uuid ); - } - } - - // Prevent subsequent requestChangesetUpdate() calls from including the settings that have been saved. - api._lastSavedRevision = Math.max( latestRevision, api._lastSavedRevision ); - - if ( response.setting_validities ) { - api._handleSettingValidities( { - settingValidities: response.setting_validities, - focusInvalidControl: true - } ); - } - - deferred.resolveWith( previewer, [ response ] ); - api.trigger( 'saved', response ); - - // Restore the global dirty state if any settings were modified during save. - if ( ! _.isEmpty( modifiedWhileSaving ) ) { - api.state( 'saved' ).set( false ); - } - } ); - }; - - if ( 0 === processing() ) { - submit(); - } else { - submitWhenDoneProcessing = function () { - if ( 0 === processing() ) { - api.state.unbind( 'change', submitWhenDoneProcessing ); - submit(); - } - }; - api.state.bind( 'change', submitWhenDoneProcessing ); - } - - return deferred.promise(); - }, - - /** - * Trash the current changes. - * - * Revert the Customizer to it's previously-published state. - * - * @since 4.9.0 - * - * @returns {jQuery.promise} Promise. - */ - trash: function trash() { - var request, success, fail; - - api.state( 'trashing' ).set( true ); - api.state( 'processing' ).set( api.state( 'processing' ).get() + 1 ); - - request = wp.ajax.post( 'customize_trash', { - customize_changeset_uuid: api.settings.changeset.uuid, - nonce: api.settings.nonce.trash - } ); - api.notifications.add( new api.OverlayNotification( 'changeset_trashing', { - type: 'info', - message: api.l10n.revertingChanges, - loading: true - } ) ); - - success = function() { - var urlParser = document.createElement( 'a' ), queryParams; - - api.state( 'changesetStatus' ).set( 'trash' ); - api.each( function( setting ) { - setting._dirty = false; - } ); - api.state( 'saved' ).set( true ); - - // Go back to Customizer without changeset. - urlParser.href = location.href; - queryParams = api.utils.parseQueryString( urlParser.search.substr( 1 ) ); - delete queryParams.changeset_uuid; - queryParams['return'] = api.settings.url['return']; - urlParser.search = $.param( queryParams ); - location.replace( urlParser.href ); - }; - - fail = function( code, message ) { - var notificationCode = code || 'unknown_error'; - api.state( 'processing' ).set( api.state( 'processing' ).get() - 1 ); - api.state( 'trashing' ).set( false ); - api.notifications.remove( 'changeset_trashing' ); - api.notifications.add( new api.Notification( notificationCode, { - message: message || api.l10n.unknownError, - dismissible: true, - type: 'error' - } ) ); - }; - - request.done( function( response ) { - success( response.message ); - } ); - - request.fail( function( response ) { - var code = response.code || 'trashing_failed'; - if ( response.success || 'non_existent_changeset' === code || 'changeset_already_trashed' === code ) { - success( response.message ); - } else { - fail( code, response.message ); - } - } ); - }, - - /** - * Builds the front preview url with the current state of customizer. - * - * @since 4.9 - * - * @return {string} Preview url. - */ - getFrontendPreviewUrl: function() { - var previewer = this, params, urlParser; - urlParser = document.createElement( 'a' ); - urlParser.href = previewer.previewUrl.get(); - params = api.utils.parseQueryString( urlParser.search.substr( 1 ) ); - - if ( api.state( 'changesetStatus' ).get() && 'publish' !== api.state( 'changesetStatus' ).get() ) { - params.customize_changeset_uuid = api.settings.changeset.uuid; - } - if ( ! api.state( 'activated' ).get() ) { - params.customize_theme = api.settings.theme.stylesheet; - } - - urlParser.search = $.param( params ); - return urlParser.href; - } - }); - - // Ensure preview nonce is included with every customized request, to allow post data to be read. - $.ajaxPrefilter( function injectPreviewNonce( options ) { - if ( ! /wp_customize=on/.test( options.data ) ) { - return; - } - options.data += '&' + $.param({ - customize_preview_nonce: api.settings.nonce.preview - }); - }); - - // Refresh the nonces if the preview sends updated nonces over. - api.previewer.bind( 'nonce', function( nonce ) { - $.extend( this.nonce, nonce ); - }); - - // Refresh the nonces if login sends updated nonces over. - api.bind( 'nonce-refresh', function( nonce ) { - $.extend( api.settings.nonce, nonce ); - $.extend( api.previewer.nonce, nonce ); - api.previewer.send( 'nonce-refresh', nonce ); - }); - - // Create Settings - $.each( api.settings.settings, function( id, data ) { - var Constructor = api.settingConstructor[ data.type ] || api.Setting; - api.add( new Constructor( id, data.value, { - transport: data.transport, - previewer: api.previewer, - dirty: !! data.dirty - } ) ); - }); - - // Create Panels - $.each( api.settings.panels, function ( id, data ) { - var Constructor = api.panelConstructor[ data.type ] || api.Panel, options; - options = _.extend( { params: data }, data ); // Inclusion of params alias is for back-compat for custom panels that expect to augment this property. - api.panel.add( new Constructor( id, options ) ); - }); - - // Create Sections - $.each( api.settings.sections, function ( id, data ) { - var Constructor = api.sectionConstructor[ data.type ] || api.Section, options; - options = _.extend( { params: data }, data ); // Inclusion of params alias is for back-compat for custom sections that expect to augment this property. - api.section.add( new Constructor( id, options ) ); - }); - - // Create Controls - $.each( api.settings.controls, function( id, data ) { - var Constructor = api.controlConstructor[ data.type ] || api.Control, options; - options = _.extend( { params: data }, data ); // Inclusion of params alias is for back-compat for custom controls that expect to augment this property. - api.control.add( new Constructor( id, options ) ); - }); - - // Focus the autofocused element - _.each( [ 'panel', 'section', 'control' ], function( type ) { - var id = api.settings.autofocus[ type ]; - if ( ! id ) { - return; - } - - /* - * Defer focus until: - * 1. The panel, section, or control exists (especially for dynamically-created ones). - * 2. The instance is embedded in the document (and so is focusable). - * 3. The preview has finished loading so that the active states have been set. - */ - api[ type ]( id, function( instance ) { - instance.deferred.embedded.done( function() { - api.previewer.deferred.active.done( function() { - instance.focus(); - }); - }); - }); - }); - - api.bind( 'ready', api.reflowPaneContents ); - $( [ api.panel, api.section, api.control ] ).each( function ( i, values ) { - var debouncedReflowPaneContents = _.debounce( api.reflowPaneContents, api.settings.timeouts.reflowPaneContents ); - values.bind( 'add', debouncedReflowPaneContents ); - values.bind( 'change', debouncedReflowPaneContents ); - values.bind( 'remove', debouncedReflowPaneContents ); - } ); - - // Set up global notifications area. - api.bind( 'ready', function setUpGlobalNotificationsArea() { - var sidebar, containerHeight, containerInitialTop; - api.notifications.container = $( '#customize-notifications-area' ); - - api.notifications.bind( 'change', _.debounce( function() { - api.notifications.render(); - } ) ); - - sidebar = $( '.wp-full-overlay-sidebar-content' ); - api.notifications.bind( 'rendered', function updateSidebarTop() { - sidebar.css( 'top', '' ); - if ( 0 !== api.notifications.count() ) { - containerHeight = api.notifications.container.outerHeight() + 1; - containerInitialTop = parseInt( sidebar.css( 'top' ), 10 ); - sidebar.css( 'top', containerInitialTop + containerHeight + 'px' ); - } - api.notifications.trigger( 'sidebarTopUpdated' ); - }); - - api.notifications.render(); - }); - - // Save and activated states - (function( state ) { - var saved = state.instance( 'saved' ), - saving = state.instance( 'saving' ), - trashing = state.instance( 'trashing' ), - activated = state.instance( 'activated' ), - processing = state.instance( 'processing' ), - paneVisible = state.instance( 'paneVisible' ), - expandedPanel = state.instance( 'expandedPanel' ), - expandedSection = state.instance( 'expandedSection' ), - changesetStatus = state.instance( 'changesetStatus' ), - selectedChangesetStatus = state.instance( 'selectedChangesetStatus' ), - changesetDate = state.instance( 'changesetDate' ), - selectedChangesetDate = state.instance( 'selectedChangesetDate' ), - previewerAlive = state.instance( 'previewerAlive' ), - editShortcutVisibility = state.instance( 'editShortcutVisibility' ), - changesetLocked = state.instance( 'changesetLocked' ), - populateChangesetUuidParam, defaultSelectedChangesetStatus; - - state.bind( 'change', function() { - var canSave; - - if ( ! activated() ) { - saveBtn.val( api.l10n.activate ); - closeBtn.find( '.screen-reader-text' ).text( api.l10n.cancel ); - - } else if ( '' === changesetStatus.get() && saved() ) { - if ( api.settings.changeset.currentUserCanPublish ) { - saveBtn.val( api.l10n.published ); - } else { - saveBtn.val( api.l10n.saved ); - } - closeBtn.find( '.screen-reader-text' ).text( api.l10n.close ); - - } else { - if ( 'draft' === selectedChangesetStatus() ) { - if ( saved() && selectedChangesetStatus() === changesetStatus() ) { - saveBtn.val( api.l10n.draftSaved ); - } else { - saveBtn.val( api.l10n.saveDraft ); - } - } else if ( 'future' === selectedChangesetStatus() ) { - if ( saved() && selectedChangesetStatus() === changesetStatus() ) { - if ( changesetDate.get() !== selectedChangesetDate.get() ) { - saveBtn.val( api.l10n.schedule ); - } else { - saveBtn.val( api.l10n.scheduled ); - } - } else { - saveBtn.val( api.l10n.schedule ); - } - } else if ( api.settings.changeset.currentUserCanPublish ) { - saveBtn.val( api.l10n.publish ); - } - closeBtn.find( '.screen-reader-text' ).text( api.l10n.cancel ); - } - - /* - * Save (publish) button should be enabled if saving is not currently happening, - * and if the theme is not active or the changeset exists but is not published. - */ - canSave = ! saving() && ! trashing() && ! changesetLocked() && ( ! activated() || ! saved() || ( changesetStatus() !== selectedChangesetStatus() && '' !== changesetStatus() ) || ( 'future' === selectedChangesetStatus() && changesetDate.get() !== selectedChangesetDate.get() ) ); - - saveBtn.prop( 'disabled', ! canSave ); - }); - - selectedChangesetStatus.validate = function( status ) { - if ( '' === status || 'auto-draft' === status ) { - return null; - } - return status; - }; - - defaultSelectedChangesetStatus = api.settings.changeset.currentUserCanPublish ? 'publish' : 'draft'; - - // Set default states. - changesetStatus( api.settings.changeset.status ); - changesetLocked( Boolean( api.settings.changeset.lockUser ) ); - changesetDate( api.settings.changeset.publishDate ); - selectedChangesetDate( api.settings.changeset.publishDate ); - selectedChangesetStatus( '' === api.settings.changeset.status || 'auto-draft' === api.settings.changeset.status ? defaultSelectedChangesetStatus : api.settings.changeset.status ); - selectedChangesetStatus.link( changesetStatus ); // Ensure that direct updates to status on server via wp.customizer.previewer.save() will update selection. - saved( true ); - if ( '' === changesetStatus() ) { // Handle case for loading starter content. - api.each( function( setting ) { - if ( setting._dirty ) { - saved( false ); - } - } ); - } - saving( false ); - activated( api.settings.theme.active ); - processing( 0 ); - paneVisible( true ); - expandedPanel( false ); - expandedSection( false ); - previewerAlive( true ); - editShortcutVisibility( 'visible' ); - - api.bind( 'change', function() { - if ( state( 'saved' ).get() ) { - state( 'saved' ).set( false ); - } - }); - - // Populate changeset UUID param when state becomes dirty. - if ( api.settings.changeset.branching ) { - saved.bind( function( isSaved ) { - if ( ! isSaved ) { - populateChangesetUuidParam( true ); - } - }); - } - - saving.bind( function( isSaving ) { - body.toggleClass( 'saving', isSaving ); - } ); - trashing.bind( function( isTrashing ) { - body.toggleClass( 'trashing', isTrashing ); - } ); - - api.bind( 'saved', function( response ) { - state('saved').set( true ); - if ( 'publish' === response.changeset_status ) { - state( 'activated' ).set( true ); - } - }); - - activated.bind( function( to ) { - if ( to ) { - api.trigger( 'activated' ); - } - }); - - /** - * Populate URL with UUID via `history.replaceState()`. - * - * @since 4.7.0 - * @access private - * - * @param {boolean} isIncluded Is UUID included. - * @returns {void} - */ - populateChangesetUuidParam = function( isIncluded ) { - var urlParser, queryParams; - - // Abort on IE9 which doesn't support history management. - if ( ! history.replaceState ) { - return; - } - - urlParser = document.createElement( 'a' ); - urlParser.href = location.href; - queryParams = api.utils.parseQueryString( urlParser.search.substr( 1 ) ); - if ( isIncluded ) { - if ( queryParams.changeset_uuid === api.settings.changeset.uuid ) { - return; - } - queryParams.changeset_uuid = api.settings.changeset.uuid; - } else { - if ( ! queryParams.changeset_uuid ) { - return; - } - delete queryParams.changeset_uuid; - } - urlParser.search = $.param( queryParams ); - history.replaceState( {}, document.title, urlParser.href ); - }; - - // Show changeset UUID in URL when in branching mode and there is a saved changeset. - if ( api.settings.changeset.branching ) { - changesetStatus.bind( function( newStatus ) { - populateChangesetUuidParam( '' !== newStatus && 'publish' !== newStatus && 'trash' !== newStatus ); - } ); - } - }( api.state ) ); - - /** - * Handles lock notice and take over request. - * - * @since 4.9.0 - */ - ( function checkAndDisplayLockNotice() { - - var LockedNotification = api.OverlayNotification.extend(/** @lends wp.customize~LockedNotification.prototype */{ - - /** - * Template ID. - * - * @type {string} - */ - templateId: 'customize-changeset-locked-notification', - - /** - * Lock user. - * - * @type {object} - */ - lockUser: null, - - /** - * A notification that is displayed in a full-screen overlay with information about the locked changeset. - * - * @constructs wp.customize~LockedNotification - * @augments wp.customize.OverlayNotification - * - * @since 4.9.0 - * - * @param {string} [code] - Code. - * @param {object} [params] - Params. - */ - initialize: function( code, params ) { - var notification = this, _code, _params; - _code = code || 'changeset_locked'; - _params = _.extend( - { - type: 'warning', - containerClasses: '', - lockUser: {} - }, - params - ); - _params.containerClasses += ' notification-changeset-locked'; - api.OverlayNotification.prototype.initialize.call( notification, _code, _params ); - }, - - /** - * Render notification. - * - * @since 4.9.0 - * - * @return {jQuery} Notification container. - */ - render: function() { - var notification = this, li, data, takeOverButton, request; - data = _.extend( - { - allowOverride: false, - returnUrl: api.settings.url['return'], - previewUrl: api.previewer.previewUrl.get(), - frontendPreviewUrl: api.previewer.getFrontendPreviewUrl() - }, - this - ); - - li = api.OverlayNotification.prototype.render.call( data ); - - // Try to autosave the changeset now. - api.requestChangesetUpdate( {}, { autosave: true } ).fail( function( response ) { - if ( ! response.autosaved ) { - li.find( '.notice-error' ).prop( 'hidden', false ).text( response.message || api.l10n.unknownRequestFail ); - } - } ); - - takeOverButton = li.find( '.customize-notice-take-over-button' ); - takeOverButton.on( 'click', function( event ) { - event.preventDefault(); - if ( request ) { - return; - } - - takeOverButton.addClass( 'disabled' ); - request = wp.ajax.post( 'customize_override_changeset_lock', { - wp_customize: 'on', - customize_theme: api.settings.theme.stylesheet, - customize_changeset_uuid: api.settings.changeset.uuid, - nonce: api.settings.nonce.override_lock - } ); - - request.done( function() { - api.notifications.remove( notification.code ); // Remove self. - api.state( 'changesetLocked' ).set( false ); - } ); - - request.fail( function( response ) { - var message = response.message || api.l10n.unknownRequestFail; - li.find( '.notice-error' ).prop( 'hidden', false ).text( message ); - - request.always( function() { - takeOverButton.removeClass( 'disabled' ); - } ); - } ); - - request.always( function() { - request = null; - } ); - } ); - - return li; - } - }); - - /** - * Start lock. - * - * @since 4.9.0 - * - * @param {object} [args] - Args. - * @param {object} [args.lockUser] - Lock user data. - * @param {boolean} [args.allowOverride=false] - Whether override is allowed. - * @returns {void} - */ - function startLock( args ) { - if ( args && args.lockUser ) { - api.settings.changeset.lockUser = args.lockUser; - } - api.state( 'changesetLocked' ).set( true ); - api.notifications.add( new LockedNotification( 'changeset_locked', { - lockUser: api.settings.changeset.lockUser, - allowOverride: Boolean( args && args.allowOverride ) - } ) ); - } - - // Show initial notification. - if ( api.settings.changeset.lockUser ) { - startLock( { allowOverride: true } ); - } - - // Check for lock when sending heartbeat requests. - $( document ).on( 'heartbeat-send.update_lock_notice', function( event, data ) { - data.check_changeset_lock = true; - data.changeset_uuid = api.settings.changeset.uuid; - } ); - - // Handle heartbeat ticks. - $( document ).on( 'heartbeat-tick.update_lock_notice', function( event, data ) { - var notification, code = 'changeset_locked'; - if ( ! data.customize_changeset_lock_user ) { - return; - } - - // Update notification when a different user takes over. - notification = api.notifications( code ); - if ( notification && notification.lockUser.id !== api.settings.changeset.lockUser.id ) { - api.notifications.remove( code ); - } - - startLock( { - lockUser: data.customize_changeset_lock_user - } ); - } ); - - // Handle locking in response to changeset save errors. - api.bind( 'error', function( response ) { - if ( 'changeset_locked' === response.code && response.lock_user ) { - startLock( { - lockUser: response.lock_user - } ); - } - } ); - } )(); - - // Set up initial notifications. - (function() { - var removedQueryParams = [], autosaveDismissed = false; - - /** - * Obtain the URL to restore the autosave. - * - * @returns {string} Customizer URL. - */ - function getAutosaveRestorationUrl() { - var urlParser, queryParams; - urlParser = document.createElement( 'a' ); - urlParser.href = location.href; - queryParams = api.utils.parseQueryString( urlParser.search.substr( 1 ) ); - if ( api.settings.changeset.latestAutoDraftUuid ) { - queryParams.changeset_uuid = api.settings.changeset.latestAutoDraftUuid; - } else { - queryParams.customize_autosaved = 'on'; - } - queryParams['return'] = api.settings.url['return']; - urlParser.search = $.param( queryParams ); - return urlParser.href; - } - - /** - * Remove parameter from the URL. - * - * @param {Array} params - Parameter names to remove. - * @returns {void} - */ - function stripParamsFromLocation( params ) { - var urlParser = document.createElement( 'a' ), queryParams, strippedParams = 0; - urlParser.href = location.href; - queryParams = api.utils.parseQueryString( urlParser.search.substr( 1 ) ); - _.each( params, function( param ) { - if ( 'undefined' !== typeof queryParams[ param ] ) { - strippedParams += 1; - delete queryParams[ param ]; - } - } ); - if ( 0 === strippedParams ) { - return; - } - - urlParser.search = $.param( queryParams ); - history.replaceState( {}, document.title, urlParser.href ); - } - - /** - * Dismiss autosave. - * - * @returns {void} - */ - function dismissAutosave() { - if ( autosaveDismissed ) { - return; - } - wp.ajax.post( 'customize_dismiss_autosave_or_lock', { - wp_customize: 'on', - customize_theme: api.settings.theme.stylesheet, - customize_changeset_uuid: api.settings.changeset.uuid, - nonce: api.settings.nonce.dismiss_autosave_or_lock, - dismiss_autosave: true - } ); - autosaveDismissed = true; - } - - /** - * Add notification regarding the availability of an autosave to restore. - * - * @returns {void} - */ - function addAutosaveRestoreNotification() { - var code = 'autosave_available', onStateChange; - - // Since there is an autosave revision and the user hasn't loaded with autosaved, add notification to prompt to load autosaved version. - api.notifications.add( new api.Notification( code, { - message: api.l10n.autosaveNotice, - type: 'warning', - dismissible: true, - render: function() { - var li = api.Notification.prototype.render.call( this ), link; - - // Handle clicking on restoration link. - link = li.find( 'a' ); - link.prop( 'href', getAutosaveRestorationUrl() ); - link.on( 'click', function( event ) { - event.preventDefault(); - location.replace( getAutosaveRestorationUrl() ); - } ); - - // Handle dismissal of notice. - li.find( '.notice-dismiss' ).on( 'click', dismissAutosave ); - - return li; - } - } ) ); - - // Remove the notification once the user starts making changes. - onStateChange = function() { - dismissAutosave(); - api.notifications.remove( code ); - api.unbind( 'change', onStateChange ); - api.state( 'changesetStatus' ).unbind( onStateChange ); - }; - api.bind( 'change', onStateChange ); - api.state( 'changesetStatus' ).bind( onStateChange ); - } - - if ( api.settings.changeset.autosaved ) { - api.state( 'saved' ).set( false ); - removedQueryParams.push( 'customize_autosaved' ); - } - if ( ! api.settings.changeset.branching && ( ! api.settings.changeset.status || 'auto-draft' === api.settings.changeset.status ) ) { - removedQueryParams.push( 'changeset_uuid' ); // Remove UUID when restoring autosave auto-draft. - } - if ( removedQueryParams.length > 0 ) { - stripParamsFromLocation( removedQueryParams ); - } - if ( api.settings.changeset.latestAutoDraftUuid || api.settings.changeset.hasAutosaveRevision ) { - addAutosaveRestoreNotification(); - } - })(); - - // Check if preview url is valid and load the preview frame. - if ( api.previewer.previewUrl() ) { - api.previewer.refresh(); - } else { - api.previewer.previewUrl( api.settings.url.home ); - } - - // Button bindings. - saveBtn.click( function( event ) { - api.previewer.save(); - event.preventDefault(); - }).keydown( function( event ) { - if ( 9 === event.which ) { // Tab. - return; - } - if ( 13 === event.which ) { // Enter. - api.previewer.save(); - } - event.preventDefault(); - }); - - closeBtn.keydown( function( event ) { - if ( 9 === event.which ) { // Tab. - return; - } - if ( 13 === event.which ) { // Enter. - this.click(); - } - event.preventDefault(); - }); - - $( '.collapse-sidebar' ).on( 'click', function() { - api.state( 'paneVisible' ).set( ! api.state( 'paneVisible' ).get() ); - }); - - api.state( 'paneVisible' ).bind( function( paneVisible ) { - overlay.toggleClass( 'preview-only', ! paneVisible ); - overlay.toggleClass( 'expanded', paneVisible ); - overlay.toggleClass( 'collapsed', ! paneVisible ); - - if ( ! paneVisible ) { - $( '.collapse-sidebar' ).attr({ 'aria-expanded': 'false', 'aria-label': api.l10n.expandSidebar }); - } else { - $( '.collapse-sidebar' ).attr({ 'aria-expanded': 'true', 'aria-label': api.l10n.collapseSidebar }); - } - }); - - // Keyboard shortcuts - esc to exit section/panel. - body.on( 'keydown', function( event ) { - var collapsedObject, expandedControls = [], expandedSections = [], expandedPanels = []; - - if ( 27 !== event.which ) { // Esc. - return; - } - - /* - * Abort if the event target is not the body (the default) and not inside of #customize-controls. - * This ensures that ESC meant to collapse a modal dialog or a TinyMCE toolbar won't collapse something else. - */ - if ( ! $( event.target ).is( 'body' ) && ! $.contains( $( '#customize-controls' )[0], event.target ) ) { - return; - } - - // Check for expanded expandable controls (e.g. widgets and nav menus items), sections, and panels. - api.control.each( function( control ) { - if ( control.expanded && control.expanded() && _.isFunction( control.collapse ) ) { - expandedControls.push( control ); - } - }); - api.section.each( function( section ) { - if ( section.expanded() ) { - expandedSections.push( section ); - } - }); - api.panel.each( function( panel ) { - if ( panel.expanded() ) { - expandedPanels.push( panel ); - } - }); - - // Skip collapsing expanded controls if there are no expanded sections. - if ( expandedControls.length > 0 && 0 === expandedSections.length ) { - expandedControls.length = 0; - } - - // Collapse the most granular expanded object. - collapsedObject = expandedControls[0] || expandedSections[0] || expandedPanels[0]; - if ( collapsedObject ) { - if ( 'themes' === collapsedObject.params.type ) { - - // Themes panel or section. - if ( body.hasClass( 'modal-open' ) ) { - collapsedObject.closeDetails(); - } else if ( api.panel.has( 'themes' ) ) { - - // If we're collapsing a section, collapse the panel also. - api.panel( 'themes' ).collapse(); - } - return; - } - collapsedObject.collapse(); - event.preventDefault(); - } - }); - - $( '.customize-controls-preview-toggle' ).on( 'click', function() { - api.state( 'paneVisible' ).set( ! api.state( 'paneVisible' ).get() ); - }); - - /* - * Sticky header feature. - */ - (function initStickyHeaders() { - var parentContainer = $( '.wp-full-overlay-sidebar-content' ), - changeContainer, updateHeaderHeight, releaseStickyHeader, resetStickyHeader, positionStickyHeader, - activeHeader, lastScrollTop; - - /** - * Determine which panel or section is currently expanded. - * - * @since 4.7.0 - * @access private - * - * @param {wp.customize.Panel|wp.customize.Section} container Construct. - * @returns {void} - */ - changeContainer = function( container ) { - var newInstance = container, - expandedSection = api.state( 'expandedSection' ).get(), - expandedPanel = api.state( 'expandedPanel' ).get(), - headerElement; - - if ( activeHeader && activeHeader.element ) { - // Release previously active header element. - releaseStickyHeader( activeHeader.element ); - - // Remove event listener in the previous panel or section. - activeHeader.element.find( '.description' ).off( 'toggled', updateHeaderHeight ); - } - - if ( ! newInstance ) { - if ( ! expandedSection && expandedPanel && expandedPanel.contentContainer ) { - newInstance = expandedPanel; - } else if ( ! expandedPanel && expandedSection && expandedSection.contentContainer ) { - newInstance = expandedSection; - } else { - activeHeader = false; - return; - } - } - - headerElement = newInstance.contentContainer.find( '.customize-section-title, .panel-meta' ).first(); - if ( headerElement.length ) { - activeHeader = { - instance: newInstance, - element: headerElement, - parent: headerElement.closest( '.customize-pane-child' ), - height: headerElement.outerHeight() - }; - - // Update header height whenever help text is expanded or collapsed. - activeHeader.element.find( '.description' ).on( 'toggled', updateHeaderHeight ); - - if ( expandedSection ) { - resetStickyHeader( activeHeader.element, activeHeader.parent ); - } - } else { - activeHeader = false; - } - }; - api.state( 'expandedSection' ).bind( changeContainer ); - api.state( 'expandedPanel' ).bind( changeContainer ); - - // Throttled scroll event handler. - parentContainer.on( 'scroll', _.throttle( function() { - if ( ! activeHeader ) { - return; - } - - var scrollTop = parentContainer.scrollTop(), - scrollDirection; - - if ( ! lastScrollTop ) { - scrollDirection = 1; - } else { - if ( scrollTop === lastScrollTop ) { - scrollDirection = 0; - } else if ( scrollTop > lastScrollTop ) { - scrollDirection = 1; - } else { - scrollDirection = -1; - } - } - lastScrollTop = scrollTop; - if ( 0 !== scrollDirection ) { - positionStickyHeader( activeHeader, scrollTop, scrollDirection ); - } - }, 8 ) ); - - // Update header position on sidebar layout change. - api.notifications.bind( 'sidebarTopUpdated', function() { - if ( activeHeader && activeHeader.element.hasClass( 'is-sticky' ) ) { - activeHeader.element.css( 'top', parentContainer.css( 'top' ) ); - } - }); - - // Release header element if it is sticky. - releaseStickyHeader = function( headerElement ) { - if ( ! headerElement.hasClass( 'is-sticky' ) ) { - return; - } - headerElement - .removeClass( 'is-sticky' ) - .addClass( 'maybe-sticky is-in-view' ) - .css( 'top', parentContainer.scrollTop() + 'px' ); - }; - - // Reset position of the sticky header. - resetStickyHeader = function( headerElement, headerParent ) { - if ( headerElement.hasClass( 'is-in-view' ) ) { - headerElement - .removeClass( 'maybe-sticky is-in-view' ) - .css( { - width: '', - top: '' - } ); - headerParent.css( 'padding-top', '' ); - } - }; - - /** - * Update active header height. - * - * @since 4.7.0 - * @access private - * - * @returns {void} - */ - updateHeaderHeight = function() { - activeHeader.height = activeHeader.element.outerHeight(); - }; - - /** - * Reposition header on throttled `scroll` event. - * - * @since 4.7.0 - * @access private - * - * @param {object} header - Header. - * @param {number} scrollTop - Scroll top. - * @param {number} scrollDirection - Scroll direction, negative number being up and positive being down. - * @returns {void} - */ - positionStickyHeader = function( header, scrollTop, scrollDirection ) { - var headerElement = header.element, - headerParent = header.parent, - headerHeight = header.height, - headerTop = parseInt( headerElement.css( 'top' ), 10 ), - maybeSticky = headerElement.hasClass( 'maybe-sticky' ), - isSticky = headerElement.hasClass( 'is-sticky' ), - isInView = headerElement.hasClass( 'is-in-view' ), - isScrollingUp = ( -1 === scrollDirection ); - - // When scrolling down, gradually hide sticky header. - if ( ! isScrollingUp ) { - if ( isSticky ) { - headerTop = scrollTop; - headerElement - .removeClass( 'is-sticky' ) - .css( { - top: headerTop + 'px', - width: '' - } ); - } - if ( isInView && scrollTop > headerTop + headerHeight ) { - headerElement.removeClass( 'is-in-view' ); - headerParent.css( 'padding-top', '' ); - } - return; - } - - // Scrolling up. - if ( ! maybeSticky && scrollTop >= headerHeight ) { - maybeSticky = true; - headerElement.addClass( 'maybe-sticky' ); - } else if ( 0 === scrollTop ) { - // Reset header in base position. - headerElement - .removeClass( 'maybe-sticky is-in-view is-sticky' ) - .css( { - top: '', - width: '' - } ); - headerParent.css( 'padding-top', '' ); - return; - } - - if ( isInView && ! isSticky ) { - // Header is in the view but is not yet sticky. - if ( headerTop >= scrollTop ) { - // Header is fully visible. - headerElement - .addClass( 'is-sticky' ) - .css( { - top: parentContainer.css( 'top' ), - width: headerParent.outerWidth() + 'px' - } ); - } - } else if ( maybeSticky && ! isInView ) { - // Header is out of the view. - headerElement - .addClass( 'is-in-view' ) - .css( 'top', ( scrollTop - headerHeight ) + 'px' ); - headerParent.css( 'padding-top', headerHeight + 'px' ); - } - }; - }()); - - // Previewed device bindings. (The api.previewedDevice property is how this Value was first introduced, but since it has moved to api.state.) - api.previewedDevice = api.state( 'previewedDevice' ); - - // Set the default device. - api.bind( 'ready', function() { - _.find( api.settings.previewableDevices, function( value, key ) { - if ( true === value['default'] ) { - api.previewedDevice.set( key ); - return true; - } - } ); - } ); - - // Set the toggled device. - footerActions.find( '.devices button' ).on( 'click', function( event ) { - api.previewedDevice.set( $( event.currentTarget ).data( 'device' ) ); - }); - - // Bind device changes. - api.previewedDevice.bind( function( newDevice ) { - var overlay = $( '.wp-full-overlay' ), - devices = ''; - - footerActions.find( '.devices button' ) - .removeClass( 'active' ) - .attr( 'aria-pressed', false ); - - footerActions.find( '.devices .preview-' + newDevice ) - .addClass( 'active' ) - .attr( 'aria-pressed', true ); - - $.each( api.settings.previewableDevices, function( device ) { - devices += ' preview-' + device; - } ); - - overlay - .removeClass( devices ) - .addClass( 'preview-' + newDevice ); - } ); - - // Bind site title display to the corresponding field. - if ( title.length ) { - api( 'blogname', function( setting ) { - var updateTitle = function() { - title.text( $.trim( setting() ) || api.l10n.untitledBlogName ); - }; - setting.bind( updateTitle ); - updateTitle(); - } ); - } - - /* - * Create a postMessage connection with a parent frame, - * in case the Customizer frame was opened with the Customize loader. - * - * @see wp.customize.Loader - */ - parent = new api.Messenger({ - url: api.settings.url.parent, - channel: 'loader' - }); - - // Handle exiting of Customizer. - (function() { - var isInsideIframe = false; - - function isCleanState() { - var defaultChangesetStatus; - - /* - * Handle special case of previewing theme switch since some settings (for nav menus and widgets) - * are pre-dirty and non-active themes can only ever be auto-drafts. - */ - if ( ! api.state( 'activated' ).get() ) { - return 0 === api._latestRevision; - } - - // Dirty if the changeset status has been changed but not saved yet. - defaultChangesetStatus = api.state( 'changesetStatus' ).get(); - if ( '' === defaultChangesetStatus || 'auto-draft' === defaultChangesetStatus ) { - defaultChangesetStatus = 'publish'; - } - if ( api.state( 'selectedChangesetStatus' ).get() !== defaultChangesetStatus ) { - return false; - } - - // Dirty if scheduled but the changeset date hasn't been saved yet. - if ( 'future' === api.state( 'selectedChangesetStatus' ).get() && api.state( 'selectedChangesetDate' ).get() !== api.state( 'changesetDate' ).get() ) { - return false; - } - - return api.state( 'saved' ).get() && 'auto-draft' !== api.state( 'changesetStatus' ).get(); - } - - /* - * If we receive a 'back' event, we're inside an iframe. - * Send any clicks to the 'Return' link to the parent page. - */ - parent.bind( 'back', function() { - isInsideIframe = true; - }); - - function startPromptingBeforeUnload() { - api.unbind( 'change', startPromptingBeforeUnload ); - api.state( 'selectedChangesetStatus' ).unbind( startPromptingBeforeUnload ); - api.state( 'selectedChangesetDate' ).unbind( startPromptingBeforeUnload ); - - // Prompt user with AYS dialog if leaving the Customizer with unsaved changes - $( window ).on( 'beforeunload.customize-confirm', function() { - if ( ! isCleanState() && ! api.state( 'changesetLocked' ).get() ) { - setTimeout( function() { - overlay.removeClass( 'customize-loading' ); - }, 1 ); - return api.l10n.saveAlert; - } - }); - } - api.bind( 'change', startPromptingBeforeUnload ); - api.state( 'selectedChangesetStatus' ).bind( startPromptingBeforeUnload ); - api.state( 'selectedChangesetDate' ).bind( startPromptingBeforeUnload ); - - function requestClose() { - var clearedToClose = $.Deferred(), dismissAutoSave = false, dismissLock = false; - - if ( isCleanState() ) { - dismissLock = true; - } else if ( confirm( api.l10n.saveAlert ) ) { - - dismissLock = true; - - // Mark all settings as clean to prevent another call to requestChangesetUpdate. - api.each( function( setting ) { - setting._dirty = false; - }); - $( document ).off( 'visibilitychange.wp-customize-changeset-update' ); - $( window ).off( 'beforeunload.wp-customize-changeset-update' ); - - closeBtn.css( 'cursor', 'progress' ); - if ( '' !== api.state( 'changesetStatus' ).get() ) { - dismissAutoSave = true; - } - } else { - clearedToClose.reject(); - } - - if ( dismissLock || dismissAutoSave ) { - wp.ajax.send( 'customize_dismiss_autosave_or_lock', { - timeout: 500, // Don't wait too long. - data: { - wp_customize: 'on', - customize_theme: api.settings.theme.stylesheet, - customize_changeset_uuid: api.settings.changeset.uuid, - nonce: api.settings.nonce.dismiss_autosave_or_lock, - dismiss_autosave: dismissAutoSave, - dismiss_lock: dismissLock - } - } ).always( function() { - clearedToClose.resolve(); - } ); - } - - return clearedToClose.promise(); - } - - parent.bind( 'confirm-close', function() { - requestClose().done( function() { - parent.send( 'confirmed-close', true ); - } ).fail( function() { - parent.send( 'confirmed-close', false ); - } ); - } ); - - closeBtn.on( 'click.customize-controls-close', function( event ) { - event.preventDefault(); - if ( isInsideIframe ) { - parent.send( 'close' ); // See confirm-close logic above. - } else { - requestClose().done( function() { - $( window ).off( 'beforeunload.customize-confirm' ); - window.location.href = closeBtn.prop( 'href' ); - } ); - } - }); - })(); - - // Pass events through to the parent. - $.each( [ 'saved', 'change' ], function ( i, event ) { - api.bind( event, function() { - parent.send( event ); - }); - } ); - - // Pass titles to the parent - api.bind( 'title', function( newTitle ) { - parent.send( 'title', newTitle ); - }); - - if ( api.settings.changeset.branching ) { - parent.send( 'changeset-uuid', api.settings.changeset.uuid ); - } - - // Initialize the connection with the parent frame. - parent.send( 'ready' ); - - // Control visibility for default controls - $.each({ - 'background_image': { - controls: [ 'background_preset', 'background_position', 'background_size', 'background_repeat', 'background_attachment' ], - callback: function( to ) { return !! to; } - }, - 'show_on_front': { - controls: [ 'page_on_front', 'page_for_posts' ], - callback: function( to ) { return 'page' === to; } - }, - 'header_textcolor': { - controls: [ 'header_textcolor' ], - callback: function( to ) { return 'blank' !== to; } - } - }, function( settingId, o ) { - api( settingId, function( setting ) { - $.each( o.controls, function( i, controlId ) { - api.control( controlId, function( control ) { - var visibility = function( to ) { - control.container.toggle( o.callback( to ) ); - }; - - visibility( setting.get() ); - setting.bind( visibility ); - }); - }); - }); - }); - - api.control( 'background_preset', function( control ) { - var visibility, defaultValues, values, toggleVisibility, updateSettings, preset; - - visibility = { // position, size, repeat, attachment - 'default': [ false, false, false, false ], - 'fill': [ true, false, false, false ], - 'fit': [ true, false, true, false ], - 'repeat': [ true, false, false, true ], - 'custom': [ true, true, true, true ] - }; - - defaultValues = [ - _wpCustomizeBackground.defaults['default-position-x'], - _wpCustomizeBackground.defaults['default-position-y'], - _wpCustomizeBackground.defaults['default-size'], - _wpCustomizeBackground.defaults['default-repeat'], - _wpCustomizeBackground.defaults['default-attachment'] - ]; - - values = { // position_x, position_y, size, repeat, attachment - 'default': defaultValues, - 'fill': [ 'left', 'top', 'cover', 'no-repeat', 'fixed' ], - 'fit': [ 'left', 'top', 'contain', 'no-repeat', 'fixed' ], - 'repeat': [ 'left', 'top', 'auto', 'repeat', 'scroll' ] - }; - - // @todo These should actually toggle the active state, but without the preview overriding the state in data.activeControls. - toggleVisibility = function( preset ) { - _.each( [ 'background_position', 'background_size', 'background_repeat', 'background_attachment' ], function( controlId, i ) { - var control = api.control( controlId ); - if ( control ) { - control.container.toggle( visibility[ preset ][ i ] ); - } - } ); - }; - - updateSettings = function( preset ) { - _.each( [ 'background_position_x', 'background_position_y', 'background_size', 'background_repeat', 'background_attachment' ], function( settingId, i ) { - var setting = api( settingId ); - if ( setting ) { - setting.set( values[ preset ][ i ] ); - } - } ); - }; - - preset = control.setting.get(); - toggleVisibility( preset ); - - control.setting.bind( 'change', function( preset ) { - toggleVisibility( preset ); - if ( 'custom' !== preset ) { - updateSettings( preset ); - } - } ); - } ); - - api.control( 'background_repeat', function( control ) { - control.elements[0].unsync( api( 'background_repeat' ) ); - - control.element = new api.Element( control.container.find( 'input' ) ); - control.element.set( 'no-repeat' !== control.setting() ); - - control.element.bind( function( to ) { - control.setting.set( to ? 'repeat' : 'no-repeat' ); - } ); - - control.setting.bind( function( to ) { - control.element.set( 'no-repeat' !== to ); - } ); - } ); - - api.control( 'background_attachment', function( control ) { - control.elements[0].unsync( api( 'background_attachment' ) ); - - control.element = new api.Element( control.container.find( 'input' ) ); - control.element.set( 'fixed' !== control.setting() ); - - control.element.bind( function( to ) { - control.setting.set( to ? 'scroll' : 'fixed' ); - } ); - - control.setting.bind( function( to ) { - control.element.set( 'fixed' !== to ); - } ); - } ); - - // Juggle the two controls that use header_textcolor - api.control( 'display_header_text', function( control ) { - var last = ''; - - control.elements[0].unsync( api( 'header_textcolor' ) ); - - control.element = new api.Element( control.container.find('input') ); - control.element.set( 'blank' !== control.setting() ); - - control.element.bind( function( to ) { - if ( ! to ) { - last = api( 'header_textcolor' ).get(); - } - - control.setting.set( to ? last : 'blank' ); - }); - - control.setting.bind( function( to ) { - control.element.set( 'blank' !== to ); - }); - }); - - // Add behaviors to the static front page controls. - api( 'show_on_front', 'page_on_front', 'page_for_posts', function( showOnFront, pageOnFront, pageForPosts ) { - var handleChange = function() { - var setting = this, pageOnFrontId, pageForPostsId, errorCode = 'show_on_front_page_collision'; - pageOnFrontId = parseInt( pageOnFront(), 10 ); - pageForPostsId = parseInt( pageForPosts(), 10 ); - - if ( 'page' === showOnFront() ) { - - // Change previewed URL to the homepage when changing the page_on_front. - if ( setting === pageOnFront && pageOnFrontId > 0 ) { - api.previewer.previewUrl.set( api.settings.url.home ); - } - - // Change the previewed URL to the selected page when changing the page_for_posts. - if ( setting === pageForPosts && pageForPostsId > 0 ) { - api.previewer.previewUrl.set( api.settings.url.home + '?page_id=' + pageForPostsId ); - } - } - - // Toggle notification when the homepage and posts page are both set and the same. - if ( 'page' === showOnFront() && pageOnFrontId && pageForPostsId && pageOnFrontId === pageForPostsId ) { - showOnFront.notifications.add( new api.Notification( errorCode, { - type: 'error', - message: api.l10n.pageOnFrontError - } ) ); - } else { - showOnFront.notifications.remove( errorCode ); - } - }; - showOnFront.bind( handleChange ); - pageOnFront.bind( handleChange ); - pageForPosts.bind( handleChange ); - handleChange.call( showOnFront, showOnFront() ); // Make sure initial notification is added after loading existing changeset. - - // Move notifications container to the bottom. - api.control( 'show_on_front', function( showOnFrontControl ) { - showOnFrontControl.deferred.embedded.done( function() { - showOnFrontControl.container.append( showOnFrontControl.getNotificationsContainerElement() ); - }); - }); - }); - - // Add code editor for Custom CSS. - (function() { - var sectionReady = $.Deferred(); - - api.section( 'custom_css', function( section ) { - section.deferred.embedded.done( function() { - if ( section.expanded() ) { - sectionReady.resolve( section ); - } else { - section.expanded.bind( function( isExpanded ) { - if ( isExpanded ) { - sectionReady.resolve( section ); - } - } ); - } - }); - }); - - // Set up the section description behaviors. - sectionReady.done( function setupSectionDescription( section ) { - var control = api.control( 'custom_css' ); - - // Hide redundant label for visual users. - control.container.find( '.customize-control-title:first' ).addClass( 'screen-reader-text' ); - - // Close the section description when clicking the close button. - section.container.find( '.section-description-buttons .section-description-close' ).on( 'click', function() { - section.container.find( '.section-meta .customize-section-description:first' ) - .removeClass( 'open' ) - .slideUp(); - - section.container.find( '.customize-help-toggle' ) - .attr( 'aria-expanded', 'false' ) - .focus(); // Avoid focus loss. - }); - - // Reveal help text if setting is empty. - if ( control && ! control.setting.get() ) { - section.container.find( '.section-meta .customize-section-description:first' ) - .addClass( 'open' ) - .show() - .trigger( 'toggled' ); - - section.container.find( '.customize-help-toggle' ).attr( 'aria-expanded', 'true' ); - } - }); - })(); - - // Toggle visibility of Header Video notice when active state change. - api.control( 'header_video', function( headerVideoControl ) { - headerVideoControl.deferred.embedded.done( function() { - var toggleNotice = function() { - var section = api.section( headerVideoControl.section() ), noticeCode = 'video_header_not_available'; - if ( ! section ) { - return; - } - if ( headerVideoControl.active.get() ) { - section.notifications.remove( noticeCode ); - } else { - section.notifications.add( new api.Notification( noticeCode, { - type: 'info', - message: api.l10n.videoHeaderNotice - } ) ); - } - }; - toggleNotice(); - headerVideoControl.active.bind( toggleNotice ); - } ); - } ); - - // Update the setting validities. - api.previewer.bind( 'selective-refresh-setting-validities', function handleSelectiveRefreshedSettingValidities( settingValidities ) { - api._handleSettingValidities( { - settingValidities: settingValidities, - focusInvalidControl: false - } ); - } ); - - // Focus on the control that is associated with the given setting. - api.previewer.bind( 'focus-control-for-setting', function( settingId ) { - var matchedControls = []; - api.control.each( function( control ) { - var settingIds = _.pluck( control.settings, 'id' ); - if ( -1 !== _.indexOf( settingIds, settingId ) ) { - matchedControls.push( control ); - } - } ); - - // Focus on the matched control with the lowest priority (appearing higher). - if ( matchedControls.length ) { - matchedControls.sort( function( a, b ) { - return a.priority() - b.priority(); - } ); - matchedControls[0].focus(); - } - } ); - - // Refresh the preview when it requests. - api.previewer.bind( 'refresh', function() { - api.previewer.refresh(); - }); - - // Update the edit shortcut visibility state. - api.state( 'paneVisible' ).bind( function( isPaneVisible ) { - var isMobileScreen; - if ( window.matchMedia ) { - isMobileScreen = window.matchMedia( 'screen and ( max-width: 640px )' ).matches; - } else { - isMobileScreen = $( window ).width() <= 640; - } - api.state( 'editShortcutVisibility' ).set( isPaneVisible || isMobileScreen ? 'visible' : 'hidden' ); - } ); - if ( window.matchMedia ) { - window.matchMedia( 'screen and ( max-width: 640px )' ).addListener( function() { - var state = api.state( 'paneVisible' ); - state.callbacks.fireWith( state, [ state.get(), state.get() ] ); - } ); - } - api.previewer.bind( 'edit-shortcut-visibility', function( visibility ) { - api.state( 'editShortcutVisibility' ).set( visibility ); - } ); - api.state( 'editShortcutVisibility' ).bind( function( visibility ) { - api.previewer.send( 'edit-shortcut-visibility', visibility ); - } ); - - // Autosave changeset. - function startAutosaving() { - var timeoutId, updateChangesetWithReschedule, scheduleChangesetUpdate, updatePending = false; - - api.unbind( 'change', startAutosaving ); // Ensure startAutosaving only fires once. - - function onChangeSaved( isSaved ) { - if ( ! isSaved && ! api.settings.changeset.autosaved ) { - api.settings.changeset.autosaved = true; // Once a change is made then autosaving kicks in. - api.previewer.send( 'autosaving' ); - } - } - api.state( 'saved' ).bind( onChangeSaved ); - onChangeSaved( api.state( 'saved' ).get() ); - - /** - * Request changeset update and then re-schedule the next changeset update time. - * - * @since 4.7.0 - * @private - */ - updateChangesetWithReschedule = function() { - if ( ! updatePending ) { - updatePending = true; - api.requestChangesetUpdate( {}, { autosave: true } ).always( function() { - updatePending = false; - } ); - } - scheduleChangesetUpdate(); - }; - - /** - * Schedule changeset update. - * - * @since 4.7.0 - * @private - */ - scheduleChangesetUpdate = function() { - clearTimeout( timeoutId ); - timeoutId = setTimeout( function() { - updateChangesetWithReschedule(); - }, api.settings.timeouts.changesetAutoSave ); - }; - - // Start auto-save interval for updating changeset. - scheduleChangesetUpdate(); - - // Save changeset when focus removed from window. - $( document ).on( 'visibilitychange.wp-customize-changeset-update', function() { - if ( document.hidden ) { - updateChangesetWithReschedule(); - } - } ); - - // Save changeset before unloading window. - $( window ).on( 'beforeunload.wp-customize-changeset-update', function() { - updateChangesetWithReschedule(); - } ); - } - api.bind( 'change', startAutosaving ); - - // Make sure TinyMCE dialogs appear above Customizer UI. - $( document ).one( 'tinymce-editor-setup', function() { - if ( window.tinymce.ui.FloatPanel && ( ! window.tinymce.ui.FloatPanel.zIndex || window.tinymce.ui.FloatPanel.zIndex < 500001 ) ) { - window.tinymce.ui.FloatPanel.zIndex = 500001; - } - } ); - - body.addClass( 'ready' ); - api.trigger( 'ready' ); - }); - -})( wp, jQuery ); diff --git a/srcs/wordpress/wp-admin/js/customize-controls.min.js b/srcs/wordpress/wp-admin/js/customize-controls.min.js deleted file mode 100644 index 346a778..0000000 --- a/srcs/wordpress/wp-admin/js/customize-controls.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,Z){var a,t,s,n,i,o,r,ee=wp.customize;ee.OverlayNotification=ee.Notification.extend({loading:!1,initialize:function(e,t){var n=this;ee.Notification.prototype.initialize.call(n,e,t),n.containerClasses+=" notification-overlay",n.loading&&(n.containerClasses+=" notification-loading")},render:function(){var e=ee.Notification.prototype.render.call(this);return e.on("keydown",_.bind(this.handleEscape,this)),e},handleEscape:function(e){var t=this;27===e.which&&(e.stopPropagation(),t.dismissible&&t.parent&&t.parent.remove(t.code))}}),ee.Notifications=ee.Values.extend({alt:!1,defaultConstructor:ee.Notification,initialize:function(e){var t=this;ee.Values.prototype.initialize.call(t,e),_.bindAll(t,"constrainFocus"),t._addedIncrement=0,t._addedOrder={},t.bind("add",function(e){t.trigger("change",e)}),t.bind("removed",function(e){t.trigger("change",e)})},count:function(){return _.size(this._value)},add:function(e,t){var n,i,a=this;return i="string"==typeof e?(n=e,t):(n=e.code,e),a.has(n)||(a._addedIncrement+=1,a._addedOrder[n]=a._addedIncrement),ee.Values.prototype.add.call(a,n,i)},remove:function(e){return delete this._addedOrder[e],ee.Values.prototype.remove.call(this,e)},get:function(e){var t,a,o=this;return t=_.values(o._value),_.extend({sort:!1},e).sort&&(a={error:4,warning:3,success:2,info:1},t.sort(function(e,t){var n=0,i=0;return _.isUndefined(a[e.type])||(n=a[e.type]),_.isUndefined(a[t.type])||(i=a[t.type]),n!==i?i-n:o._addedOrder[t.code]-o._addedOrder[e.code]})),t},render:function(){var e,t,n,i,a=this,o=!1,s=[],r={};a.container&&a.container.length&&(e=a.get({sort:!0}),a.container.toggle(0!==e.length),a.container.is(a.previousContainer)&&_.isEqual(e,a.previousNotifications)||((n=a.container.children("ul").first()).length||(n=Z("<ul></ul>"),a.container.append(n)),n.find("> [data-code]").remove(),_.each(a.previousNotifications,function(e){r[e.code]=e}),_.each(e,function(e){var t;!wp.a11y||r[e.code]&&_.isEqual(e.message,r[e.code].message)||wp.a11y.speak(e.message,"assertive"),t=Z(e.render()),e.container=t,n.append(t),e.extended(ee.OverlayNotification)&&s.push(e)}),t=Boolean(s.length),a.previousNotifications&&(o=Boolean(_.find(a.previousNotifications,function(e){return e.extended(ee.OverlayNotification)}))),t!==o&&(Z(document.body).toggleClass("customize-loading",t),a.container.toggleClass("has-overlay-notifications",t),t?(a.previousActiveElement=document.activeElement,Z(document).on("keydown",a.constrainFocus)):Z(document).off("keydown",a.constrainFocus)),t?(a.focusContainer=s[s.length-1].container,a.focusContainer.prop("tabIndex",-1),(i=a.focusContainer.find(":focusable")).length?i.first().focus():a.focusContainer.focus()):a.previousActiveElement&&(Z(a.previousActiveElement).focus(),a.previousActiveElement=null),a.previousNotifications=e,a.previousContainer=a.container,a.trigger("rendered")))},constrainFocus:function(e){var t,n=this;e.stopPropagation(),9===e.which&&(0===(t=n.focusContainer.find(":focusable")).length&&(t=n.focusContainer),Z.contains(n.focusContainer[0],e.target)&&Z.contains(n.focusContainer[0],document.activeElement)?t.last().is(e.target)&&!e.shiftKey?(e.preventDefault(),t.first().focus()):t.first().is(e.target)&&e.shiftKey&&(e.preventDefault(),t.last().focus()):(e.preventDefault(),t.first().focus()))}}),ee.Setting=ee.Value.extend({defaults:{transport:"refresh",dirty:!1},initialize:function(e,t,n){var i,a=this;i=_.extend({previewer:ee.previewer},a.defaults,n||{}),ee.Value.prototype.initialize.call(a,t,i),a.id=e,a._dirty=i.dirty,a.notifications=new ee.Notifications,a.bind(a.preview)},preview:function(){var e,t=this;"postMessage"!==(e=t.transport)||ee.state("previewerAlive").get()||(e="refresh"),"postMessage"===e?t.previewer.send("setting",[t.id,t()]):"refresh"===e&&t.previewer.refresh()},findControls:function(){var n=this,i=[];return ee.control.each(function(t){_.each(t.settings,function(e){e.id===n.id&&i.push(t)})}),i}}),ee._latestRevision=0,ee._lastSavedRevision=0,ee._latestSettingRevisions={},ee.bind("change",function(e){ee._latestRevision+=1,ee._latestSettingRevisions[e.id]=ee._latestRevision}),ee.bind("ready",function(){ee.bind("add",function(e){e._dirty&&(ee._latestRevision+=1,ee._latestSettingRevisions[e.id]=ee._latestRevision)})}),ee.dirtyValues=function(n){var i={};return ee.each(function(e){var t;e._dirty&&(t=ee._latestSettingRevisions[e.id],ee.state("changesetStatus").get()&&n&&n.unsaved&&(_.isUndefined(t)||t<=ee._lastSavedRevision)||(i[e.id]=e.get()))}),i},ee.requestChangesetUpdate=function(n,e){var t,i,a,o,s={};return t=new Z.Deferred,0!==ee.state("processing").get()?(t.reject("already_processing"),t.promise()):(o=_.extend({title:null,date:null,autosave:!1,force:!1},e),n&&_.extend(s,n),_.each(ee.dirtyValues({unsaved:!0}),function(e,t){n&&null===n[t]||(s[t]=_.extend({},s[t]||{},{value:e}))}),ee.trigger("changeset-save",s,o),!o.force&&_.isEmpty(s)&&null===o.title&&null===o.date?(t.resolve({}),t.promise()):o.status?t.reject({code:"illegal_status_in_changeset_update"}).promise():o.date&&o.autosave?t.reject({code:"illegal_autosave_with_date_gmt"}).promise():(ee.state("processing").set(ee.state("processing").get()+1),t.always(function(){ee.state("processing").set(ee.state("processing").get()-1)}),delete(a=ee.previewer.query({excludeCustomizedSaved:!0})).customized,_.extend(a,{nonce:ee.settings.nonce.save,customize_theme:ee.settings.theme.stylesheet,customize_changeset_data:JSON.stringify(s)}),null!==o.title&&(a.customize_changeset_title=o.title),null!==o.date&&(a.customize_changeset_date=o.date),!1!==o.autosave&&(a.customize_changeset_autosave="true"),ee.trigger("save-request-params",a),(i=wp.ajax.post("customize_save",a)).done(function(e){var n={};ee._lastSavedRevision=Math.max(ee._latestRevision,ee._lastSavedRevision),ee.state("changesetStatus").set(e.changeset_status),e.changeset_date&&ee.state("changesetDate").set(e.changeset_date),t.resolve(e),ee.trigger("changeset-saved",e),e.setting_validities&&_.each(e.setting_validities,function(e,t){!0===e&&_.isObject(s[t])&&!_.isUndefined(s[t].value)&&(n[t]=s[t].value)}),ee.previewer.send("changeset-saved",_.extend({},e,{saved_changeset_values:n}))}),i.fail(function(e){t.reject(e),ee.trigger("changeset-error",e)}),i.always(function(e){e.setting_validities&&ee._handleSettingValidities({settingValidities:e.setting_validities})}),t.promise()))},ee.utils.bubbleChildValueChanges=function(n,e){Z.each(e,function(e,t){n[t].bind(function(e,t){n.parent&&e!==t&&n.parent.trigger("change",n)})})},t=function(e){var t,n,i,a;t=this,i=function(){var e;e=(t.extended(ee.Panel)||t.extended(ee.Section))&&t.expanded&&t.expanded()?t.contentContainer:t.container,0===(a=e.find(".control-focus:first")).length&&(a=e.find("input, select, textarea, button, object, a[href], [tabindex]").filter(":visible").first()),a.focus()},(e=e||{}).completeCallback?(n=e.completeCallback,e.completeCallback=function(){i(),n()}):e.completeCallback=i,ee.state("paneVisible").set(!0),t.expand?t.expand(e):e.completeCallback()},ee.utils.prioritySort=function(e,t){return e.priority()===t.priority()&&"number"==typeof e.params.instanceNumber&&"number"==typeof t.params.instanceNumber?e.params.instanceNumber-t.params.instanceNumber:e.priority()-t.priority()},ee.utils.isKeydownButNotEnterEvent=function(e){return"keydown"===e.type&&13!==e.which},ee.utils.areElementListsEqual=function(e,t){return e.length===t.length&&-1===_.indexOf(_.map(_.zip(e,t),function(e){return Z(e[0]).is(e[1])}),!1)},ee.utils.highlightButton=function(e,t){var n,i="button-see-me",a=!1;function o(){a=!0}return(n=_.extend({delay:0,focusTarget:e},t)).focusTarget.on("focusin",o),setTimeout(function(){n.focusTarget.off("focusin",o),a||(e.addClass(i),e.one("animationend",function(){e.removeClass(i)}))},n.delay),o},ee.utils.getCurrentTimestamp=function(){var e,t,n;return t=_.now(),e=new Date(ee.settings.initialServerDate.replace(/-/g,"/")),n=t-ee.settings.initialClientTimestamp,n+=ee.settings.initialClientTimestamp-ee.settings.initialServerTimestamp,e.setTime(e.getTime()+n),e.getTime()},ee.utils.getRemainingTime=function(e){var t;return t=(e instanceof Date?e.getTime():"string"==typeof e?new Date(e.replace(/-/g,"/")).getTime():e)-ee.utils.getCurrentTimestamp(),t=Math.ceil(t/1e3)},n=document.createElement("div"),i={transition:"transitionend",OTransition:"oTransitionEnd",MozTransition:"transitionend",WebkitTransition:"webkitTransitionEnd"},s=(o=_.find(_.keys(i),function(e){return!_.isUndefined(n.style[e])}))?i[o]:null,a=ee.Class.extend({defaultActiveArguments:{duration:"fast",completeCallback:Z.noop},defaultExpandedArguments:{duration:"fast",completeCallback:Z.noop},containerType:"container",defaults:{title:"",description:"",priority:100,type:"default",content:null,active:!0,instanceNumber:null},initialize:function(e,t){var n=this;n.id=e,a.instanceCounter||(a.instanceCounter=0),a.instanceCounter++,Z.extend(n,{params:_.defaults(t.params||t,n.defaults)}),n.params.instanceNumber||(n.params.instanceNumber=a.instanceCounter),n.notifications=new ee.Notifications,n.templateSelector=n.params.templateId||"customize-"+n.containerType+"-"+n.params.type,n.container=Z(n.params.content),0===n.container.length&&(n.container=Z(n.getContainer())),n.headContainer=n.container,n.contentContainer=n.getContent(),n.container=n.container.add(n.contentContainer),n.deferred={embedded:new Z.Deferred},n.priority=new ee.Value,n.active=new ee.Value,n.activeArgumentsQueue=[],n.expanded=new ee.Value,n.expandedArgumentsQueue=[],n.active.bind(function(e){var t=n.activeArgumentsQueue.shift();t=Z.extend({},n.defaultActiveArguments,t),e=e&&n.isContextuallyActive(),n.onChangeActive(e,t)}),n.expanded.bind(function(e){var t=n.expandedArgumentsQueue.shift();t=Z.extend({},n.defaultExpandedArguments,t),n.onChangeExpanded(e,t)}),n.deferred.embedded.done(function(){n.setupNotifications(),n.attachEvents()}),ee.utils.bubbleChildValueChanges(n,["priority","active"]),n.priority.set(n.params.priority),n.active.set(n.params.active),n.expanded.set(!1)},getNotificationsContainerElement:function(){return this.contentContainer.find(".customize-control-notifications-container:first")},setupNotifications:function(){var e,t=this;t.notifications.container=t.getNotificationsContainerElement(),e=function(){t.expanded.get()&&t.notifications.render()},t.expanded.bind(e),e(),t.notifications.bind("change",_.debounce(e))},ready:function(){},_children:function(t,e){var n=this,i=[];return ee[e].each(function(e){e[t].get()===n.id&&i.push(e)}),i.sort(ee.utils.prioritySort),i},isContextuallyActive:function(){throw new Error("Container.isContextuallyActive() must be overridden in a subclass.")},onChangeActive:function(e,t){var n,i=this,a=i.headContainer;t.unchanged?t.completeCallback&&t.completeCallback():(n="resolved"===ee.previewer.deferred.active.state()?t.duration:0,i.extended(ee.Panel)&&(ee.panel.each(function(e){e!==i&&e.expanded()&&(e,n=0)}),e||_.each(i.sections(),function(e){e.collapse({duration:0})})),Z.contains(document,a.get(0))?e?a.slideDown(n,t.completeCallback):i.expanded()?i.collapse({duration:n,completeCallback:function(){a.slideUp(n,t.completeCallback)}}):a.slideUp(n,t.completeCallback):(a.toggle(e),t.completeCallback&&t.completeCallback()))},_toggleActive:function(e,t){return t=t||{},e&&this.active.get()||!e&&!this.active.get()?(t.unchanged=!0,this.onChangeActive(this.active.get(),t),!1):(t.unchanged=!1,this.activeArgumentsQueue.push(t),this.active.set(e),!0)},activate:function(e){return this._toggleActive(!0,e)},deactivate:function(e){return this._toggleActive(!1,e)},onChangeExpanded:function(){throw new Error("Must override with subclass.")},_toggleExpanded:function(e,t){var n,i=this;return n=(t=t||{}).completeCallback,!(e&&!i.active())&&(ee.state("paneVisible").set(!0),t.completeCallback=function(){n&&n.apply(i,arguments),e?i.container.trigger("expanded"):i.container.trigger("collapsed")},e&&i.expanded.get()||!e&&!i.expanded.get()?(t.unchanged=!0,i.onChangeExpanded(i.expanded.get(),t),!1):(t.unchanged=!1,i.expandedArgumentsQueue.push(t),i.expanded.set(e),!0))},expand:function(e){return this._toggleExpanded(!0,e)},collapse:function(e){return this._toggleExpanded(!1,e)},_animateChangeExpanded:function(t){if(s){var n,i,a=this,o=a.contentContainer,e=o.closest(".wp-full-overlay");n=e.add(o),(!a.panel||""===a.panel()||!!ee.panel(a.panel()).contentContainer.hasClass("skip-transition"))&&(n=n.add("#customize-info, .customize-pane-parent")),i=function(e){2===e.eventPhase&&Z(e.target).is(o)&&(o.off(s,i),n.removeClass("busy"),t&&t())},o.on(s,i),n.addClass("busy"),_.defer(function(){var e=o.closest(".wp-full-overlay-sidebar-content"),t=e.scrollTop(),n=o.data("previous-scrollTop")||0,i=a.expanded();i&&0<t?(o.css("top",t+"px"),o.data("previous-scrollTop",t)):!i&&0<t+n&&(o.css("top",n-t+"px"),e.scrollTop(n))})}else t&&t()},focus:t,getContainer:function(){var e,t=this;return(e=0!==Z("#tmpl-"+t.templateSelector).length?wp.template(t.templateSelector):wp.template("customize-"+t.containerType+"-default"))&&t.container?Z.trim(e(_.extend({id:t.id},t.params))):"<li></li>"},getContent:function(){var e=this.container,t=e.find(".accordion-section-content, .control-panel-content").first(),n="sub-"+e.attr("id"),i=n,a=e.attr("aria-owns");return a&&(i=i+" "+a),e.attr("aria-owns",i),t.detach().attr({id:n,class:"customize-pane-child "+t.attr("class")+" "+e.attr("class")})}}),ee.Section=a.extend({containerType:"section",containerParent:"#customize-theme-controls",containerPaneParent:".customize-pane-parent",defaults:{title:"",description:"",priority:100,type:"default",content:null,active:!0,instanceNumber:null,panel:null,customizeAction:""},initialize:function(e,t){var n,i=this;(n=t.params||t).type||_.find(ee.sectionConstructor,function(e,t){return e===i.constructor&&(n.type=t,!0)}),a.prototype.initialize.call(i,e,n),i.id=e,i.panel=new ee.Value,i.panel.bind(function(e){Z(i.headContainer).toggleClass("control-subsection",!!e)}),i.panel.set(i.params.panel||""),ee.utils.bubbleChildValueChanges(i,["panel"]),i.embed(),i.deferred.embedded.done(function(){i.ready()})},embed:function(){var e,n=this;n.containerParent=ee.ensure(n.containerParent),e=function(e){var t;e?ee.panel(e,function(e){e.deferred.embedded.done(function(){t=e.contentContainer,n.headContainer.parent().is(t)||t.append(n.headContainer),n.contentContainer.parent().is(n.headContainer)||n.containerParent.append(n.contentContainer),n.deferred.embedded.resolve()})}):(t=ee.ensure(n.containerPaneParent),n.headContainer.parent().is(t)||t.append(n.headContainer),n.contentContainer.parent().is(n.headContainer)||n.containerParent.append(n.contentContainer),n.deferred.embedded.resolve())},n.panel.bind(e),e(n.panel.get())},attachEvents:function(){var e,t,n=this;n.container.hasClass("cannot-expand")||(n.container.find(".accordion-section-title, .customize-section-back").on("click keydown",function(e){ee.utils.isKeydownButNotEnterEvent(e)||(e.preventDefault(),n.expanded()?n.collapse():n.expand())}),n.container.find(".customize-section-title .customize-help-toggle").on("click",function(){(e=n.container.find(".section-meta")).hasClass("cannot-expand")||((t=e.find(".customize-section-description:first")).toggleClass("open"),t.slideToggle(n.defaultExpandedArguments.duration,function(){t.trigger("toggled")}),Z(this).attr("aria-expanded",function(e,t){return"true"===t?"false":"true"}))}))},isContextuallyActive:function(){var e=this.controls(),t=0;return _(e).each(function(e){e.active()&&(t+=1)}),0!==t},controls:function(){return this._children("section","control")},onChangeExpanded:function(e,t){var n,i,a=this,o=a.headContainer.closest(".wp-full-overlay-sidebar-content"),s=a.contentContainer,r=a.headContainer.closest(".wp-full-overlay"),c=s.find(".customize-section-back"),l=a.headContainer.find(".accordion-section-title").first();e&&!s.hasClass("open")?(n=t.unchanged?t.completeCallback:Z.proxy(function(){a._animateChangeExpanded(function(){l.attr("tabindex","-1"),c.attr("tabindex","0"),c.focus(),s.css("top",""),o.scrollTop(0),t.completeCallback&&t.completeCallback()}),s.addClass("open"),r.addClass("section-open"),ee.state("expandedSection").set(a)},this),t.allowMultiple||ee.section.each(function(e){e!==a&&e.collapse({duration:t.duration})}),a.panel()?ee.panel(a.panel()).expand({duration:t.duration,completeCallback:n}):(t.allowMultiple||ee.panel.each(function(e){e.collapse()}),n())):!e&&s.hasClass("open")?(a.panel()&&(i=ee.panel(a.panel())).contentContainer.hasClass("skip-transition")&&i.collapse(),a._animateChangeExpanded(function(){c.attr("tabindex","-1"),l.attr("tabindex","0"),l.focus(),s.css("top",""),t.completeCallback&&t.completeCallback()}),s.removeClass("open"),r.removeClass("section-open"),a===ee.state("expandedSection").get()&&ee.state("expandedSection").set(!1)):t.completeCallback&&t.completeCallback()}}),ee.ThemesSection=ee.Section.extend({currentTheme:"",overlay:"",template:"",screenshotQueue:null,$window:null,$body:null,loaded:0,loading:!1,fullyLoaded:!1,term:"",tags:"",nextTerm:"",nextTags:"",filtersHeight:0,headerContainer:null,updateCountDebounced:null,initialize:function(e,t){var n=this;n.headerContainer=Z(),n.$window=Z(window),n.$body=Z(document.body),ee.Section.prototype.initialize.call(n,e,t),n.updateCountDebounced=_.debounce(n.updateCount,500)},embed:function(){var e,n=this;e=function(e){var t;ee.panel(e,function(e){e.deferred.embedded.done(function(){t=e.contentContainer,n.headContainer.parent().is(t)||t.find(".customize-themes-full-container-container").before(n.headContainer),n.contentContainer.parent().is(n.headContainer)||n.containerParent.append(n.contentContainer),n.deferred.embedded.resolve()})})},n.panel.bind(e),e(n.panel.get())},ready:function(){var t=this;t.overlay=t.container.find(".theme-overlay"),t.template=wp.template("customize-themes-details-view"),t.container.on("keydown",function(e){t.overlay.find(".theme-wrap").is(":visible")&&(39===e.keyCode&&t.nextTheme(),37===e.keyCode&&t.previousTheme(),27===e.keyCode&&(t.$body.hasClass("modal-open")?t.closeDetails():t.headerContainer.find(".customize-themes-section-title").focus(),e.stopPropagation()))}),t.renderScreenshots=_.throttle(t.renderScreenshots,100),_.bindAll(t,"renderScreenshots","loadMore","checkTerm","filtersChecked")},isContextuallyActive:function(){return this.active()},attachEvents:function(){var e,a=this;function t(){var e=a.headerContainer.find(".customize-themes-section-title");e.toggleClass("selected",a.expanded()),e.attr("aria-expanded",a.expanded()?"true":"false"),a.expanded()||e.removeClass("details-open")}a.container.find(".customize-section-back").on("click keydown",function(e){ee.utils.isKeydownButNotEnterEvent(e)||(e.preventDefault(),a.collapse())}),a.headerContainer=Z("#accordion-section-"+a.id),a.headerContainer.on("click",".customize-themes-section-title",function(){a.headerContainer.find(".filter-details").length&&(a.headerContainer.find(".customize-themes-section-title").toggleClass("details-open").attr("aria-expanded",function(e,t){return"true"===t?"false":"true"}),a.headerContainer.find(".filter-details").slideToggle(180)),a.expanded()||a.expand()}),a.container.on("click",".theme-actions .preview-theme",function(){ee.panel("themes").loadThemePreview(Z(this).data("slug"))}),a.container.on("click",".left",function(){a.previousTheme()}),a.container.on("click",".right",function(){a.nextTheme()}),a.container.on("click",".theme-backdrop, .close",function(){a.closeDetails()}),"local"===a.params.filter_type?a.container.on("input",".wp-filter-search-themes",function(e){a.filterSearch(e.currentTarget.value)}):"remote"===a.params.filter_type&&(e=_.debounce(a.checkTerm,500),a.contentContainer.on("input",".wp-filter-search",function(){ee.panel("themes").expanded()&&(e(a),a.expanded()||a.expand())}),a.contentContainer.on("click",".filter-group input",function(){a.filtersChecked(),a.checkTerm(a)})),a.contentContainer.on("click",".feature-filter-toggle",function(e){var t=Z(".customize-themes-full-container"),n=Z(e.currentTarget);if(a.filtersHeight=n.parent().next(".filter-drawer").height(),!(0<t.scrollTop()&&(t.animate({scrollTop:0},400),n.hasClass("open"))))if(n.toggleClass("open").attr("aria-expanded",function(e,t){return"true"===t?"false":"true"}).parent().next(".filter-drawer").slideToggle(180,"linear"),n.hasClass("open")){var i=1018<window.innerWidth?50:76;a.contentContainer.find(".themes").css("margin-top",a.filtersHeight+i)}else a.contentContainer.find(".themes").css("margin-top",0)}),a.contentContainer.on("click",".no-themes-local .search-dotorg-themes",function(){ee.section("wporg_themes").focus()}),a.expanded.bind(t),t(),ee.bind("ready",function(){a.contentContainer=a.container.find(".customize-themes-section"),a.contentContainer.appendTo(Z(".customize-themes-full-container")),a.container.add(a.headerContainer)})},onChangeExpanded:function(e,n){var i=this,t=i.contentContainer.closest(".customize-themes-full-container");function a(){0===i.loaded&&i.loadThemes(),ee.section.each(function(e){var t;e!==i&&"themes"===e.params.type&&(t=e.contentContainer.find(".wp-filter-search").val(),i.contentContainer.find(".wp-filter-search").val(t),""===t&&""!==i.term&&"local"!==i.params.filter_type?(i.term="",i.initializeNewQuery(i.term,i.tags)):"remote"===i.params.filter_type?i.checkTerm(i):"local"===i.params.filter_type&&i.filterSearch(t),e.collapse({duration:n.duration}))}),i.contentContainer.addClass("current-section"),t.scrollTop(),t.on("scroll",_.throttle(i.renderScreenshots,300)),t.on("scroll",_.throttle(i.loadMore,300)),n.completeCallback&&n.completeCallback(),i.updateCount()}n.unchanged?n.completeCallback&&n.completeCallback():e?i.panel()&&ee.panel.has(i.panel())?ee.panel(i.panel()).expand({duration:n.duration,completeCallback:a}):a():(i.contentContainer.removeClass("current-section"),i.headerContainer.find(".filter-details").slideUp(180),t.off("scroll"),n.completeCallback&&n.completeCallback())},getContent:function(){return this.container.find(".control-section-content")},loadThemes:function(){var e,n,t,i=this;i.loading||(n=Math.ceil(i.loaded/100)+1,e={nonce:ee.settings.nonce.switch_themes,wp_customize:"on",theme_action:i.params.action,customized_theme:ee.settings.theme.stylesheet,page:n},"remote"===i.params.filter_type&&(e.search=i.term,e.tags=i.tags),i.headContainer.closest(".wp-full-overlay").addClass("loading"),i.loading=!0,i.container.find(".no-themes").hide(),(t=wp.ajax.post("customize_load_themes",e)).done(function(e){var t=e.themes;if(""!==i.nextTerm||""!==i.nextTags)return i.nextTerm&&(i.term=i.nextTerm),i.nextTags&&(i.tags=i.nextTags),i.nextTerm="",i.nextTags="",i.loading=!1,void i.loadThemes();0!==t.length?(i.loadControls(t,n),1===n&&(_.each(i.controls().slice(0,3),function(e){var t=e.params.theme.screenshot[0];t&&((new Image).src=t)}),"local"!==i.params.filter_type&&wp.a11y.speak(ee.settings.l10n.themeSearchResults.replace("%d",e.info.results))),_.delay(i.renderScreenshots,100),("local"===i.params.filter_type||t.length<100)&&(i.fullyLoaded=!0)):0===i.loaded?(i.container.find(".no-themes").show(),wp.a11y.speak(i.container.find(".no-themes").text())):i.fullyLoaded=!0,"local"===i.params.filter_type?i.updateCount():i.updateCount(e.info.results),i.container.find(".unexpected-error").hide(),i.headContainer.closest(".wp-full-overlay").removeClass("loading"),i.loading=!1}),t.fail(function(e){void 0===e?(i.container.find(".unexpected-error").show(),wp.a11y.speak(i.container.find(".unexpected-error").text())):"undefined"!=typeof console&&console.error&&console.error(e),i.headContainer.closest(".wp-full-overlay").removeClass("loading"),i.loading=!1}))},loadControls:function(e,t){var n=[],i=this;_.each(e,function(e){var t=new ee.controlConstructor.theme(i.params.action+"_theme_"+e.id,{type:"theme",section:i.params.id,theme:e,priority:i.loaded+1});ee.control.add(t),n.push(t),i.loaded=i.loaded+1}),1!==t&&Array.prototype.push.apply(i.screenshotQueue,n)},loadMore:function(){var e,t;this.fullyLoaded||this.loading||(t=(e=this.container.closest(".customize-themes-full-container")).scrollTop()+e.height(),e.prop("scrollHeight")-3e3<t&&this.loadThemes())},filterSearch:function(e){var t,n=0,i=this,a=ee.section.has("wporg_themes")&&"remote"!==i.params.filter_type?".no-themes-local":".no-themes",o=i.controls();i.loading||(t=e.toLowerCase().trim().replace(/-/g," ").split(" "),_.each(o,function(e){e.filter(t)&&(n+=1)}),0===n?(i.container.find(a).show(),wp.a11y.speak(i.container.find(a).text())):i.container.find(a).hide(),i.renderScreenshots(),ee.reflowPaneContents(),i.updateCountDebounced(n))},checkTerm:function(e){var t;"remote"===e.params.filter_type&&(t=e.contentContainer.find(".wp-filter-search").val(),e.term!==t.trim()&&e.initializeNewQuery(t,e.tags))},filtersChecked:function(){var e=this,t=e.container.find(".filter-group").find(":checkbox"),n=[];_.each(t.filter(":checked"),function(e){n.push(Z(e).prop("value"))}),0===n.length?(n="",e.contentContainer.find(".feature-filter-toggle .filter-count-0").show(),e.contentContainer.find(".feature-filter-toggle .filter-count-filters").hide()):(e.contentContainer.find(".feature-filter-toggle .theme-filter-count").text(n.length),e.contentContainer.find(".feature-filter-toggle .filter-count-0").hide(),e.contentContainer.find(".feature-filter-toggle .filter-count-filters").show()),_.isEqual(e.tags,n)||(e.loading?e.nextTags=n:"remote"===e.params.filter_type?e.initializeNewQuery(e.term,n):"local"===e.params.filter_type&&e.filterSearch(n.join(" ")))},initializeNewQuery:function(e,t){var n=this;_.each(n.controls(),function(e){e.container.remove(),ee.control.remove(e.id)}),n.loaded=0,n.fullyLoaded=!1,n.screenshotQueue=null,n.loading?(n.nextTerm=e,n.nextTags=t):(n.term=e,n.tags=t,n.loadThemes()),n.expanded()||n.expand()},renderScreenshots:function(){var l=this;null!==l.screenshotQueue&&0!==l.screenshotQueue.length||(l.screenshotQueue=_.filter(l.controls(),function(e){return!e.screenshotRendered})),l.screenshotQueue.length&&(l.screenshotQueue=_.filter(l.screenshotQueue,function(e){var t=e.container.find(".theme-screenshot"),n=t.find("img");if(!n.length)return!1;if(n.is(":hidden"))return!0;var i=l.$window.scrollTop(),a=i+l.$window.height(),o=n.offset().top,s=t.height(),r=3*s,c=i-r<=o+s&&o<=a+r;return c&&e.container.trigger("render-screenshot"),!c}))},getVisibleCount:function(){return this.contentContainer.find("li.customize-control:visible").length},updateCount:function(e){var t,n;e||0===e||(e=this.getVisibleCount()),n=this.contentContainer.find(".themes-displayed"),t=this.contentContainer.find(".theme-count"),0===e?t.text("0"):(n.fadeOut(180,function(){t.text(e),n.fadeIn(180)}),wp.a11y.speak(ee.settings.l10n.announceThemeCount.replace("%d",e)))},nextTheme:function(){var e=this;e.getNextTheme()&&e.showDetails(e.getNextTheme(),function(){e.overlay.find(".right").focus()})},getNextTheme:function(){var e,t,n,i;return e=ee.control(this.params.action+"_theme_"+this.currentTheme),n=this.controls(),-1!==(i=_.indexOf(n,e))&&(!!(t=n[i+1])&&t.params.theme)},previousTheme:function(){var e=this;e.getPreviousTheme()&&e.showDetails(e.getPreviousTheme(),function(){e.overlay.find(".left").focus()})},getPreviousTheme:function(){var e,t,n,i;return e=ee.control(this.params.action+"_theme_"+this.currentTheme),n=this.controls(),-1!==(i=_.indexOf(n,e))&&(!!(t=n[i-1])&&t.params.theme)},updateLimits:function(){this.getNextTheme()||this.overlay.find(".right").addClass("disabled"),this.getPreviousTheme()||this.overlay.find(".left").addClass("disabled")},loadThemePreview:function(e){return ee.ThemesPanel.prototype.loadThemePreview.call(this,e)},showDetails:function(e,t){var n=this,i=ee.panel("themes");function a(){return!i.canSwitchTheme(e.id)}n.currentTheme=e.id,n.overlay.html(n.template(e)).fadeIn("fast").focus(),n.overlay.find("button.preview, button.preview-theme").toggleClass("disabled",a()),n.overlay.find("button.theme-install").toggleClass("disabled",a()||!1===ee.settings.theme._canInstall||!0===ee.settings.theme._filesystemCredentialsNeeded),n.$body.addClass("modal-open"),n.containFocus(n.overlay),n.updateLimits(),wp.a11y.speak(ee.settings.l10n.announceThemeDetails.replace("%s",e.name)),t&&t()},closeDetails:function(){this.$body.removeClass("modal-open"),this.overlay.fadeOut("fast"),ee.control(this.params.action+"_theme_"+this.currentTheme).container.find(".theme").focus()},containFocus:function(t){var n;t.on("keydown",function(e){if(9===e.keyCode)return(n=Z(":tabbable",t)).last()[0]!==e.target||e.shiftKey?n.first()[0]===e.target&&e.shiftKey?(n.last().focus(),!1):void 0:(n.first().focus(),!1)})}}),ee.OuterSection=ee.Section.extend({initialize:function(){this.containerParent="#customize-outer-theme-controls",this.containerPaneParent=".customize-outer-pane-parent",ee.Section.prototype.initialize.apply(this,arguments)},onChangeExpanded:function(e,t){var n,i,a=this,o=a.headContainer.closest(".wp-full-overlay-sidebar-content"),s=a.contentContainer,r=s.find(".customize-section-back"),c=a.headContainer.find(".accordion-section-title").first();Z(document.body).toggleClass("outer-section-open",e),a.container.toggleClass("open",e),a.container.removeClass("busy"),ee.section.each(function(e){"outer"===e.params.type&&e.id!==a.id&&e.container.removeClass("open")}),e&&!s.hasClass("open")?(n=t.unchanged?t.completeCallback:Z.proxy(function(){a._animateChangeExpanded(function(){c.attr("tabindex","-1"),r.attr("tabindex","0"),r.focus(),s.css("top",""),o.scrollTop(0),t.completeCallback&&t.completeCallback()}),s.addClass("open")},this),a.panel()?ee.panel(a.panel()).expand({duration:t.duration,completeCallback:n}):n()):!e&&s.hasClass("open")?(a.panel()&&(i=ee.panel(a.panel())).contentContainer.hasClass("skip-transition")&&i.collapse(),a._animateChangeExpanded(function(){r.attr("tabindex","-1"),c.attr("tabindex","0"),c.focus(),s.css("top",""),t.completeCallback&&t.completeCallback()}),s.removeClass("open")):t.completeCallback&&t.completeCallback()}}),ee.Panel=a.extend({containerType:"panel",initialize:function(e,t){var n,i=this;(n=t.params||t).type||_.find(ee.panelConstructor,function(e,t){return e===i.constructor&&(n.type=t,!0)}),a.prototype.initialize.call(i,e,n),i.embed(),i.deferred.embedded.done(function(){i.ready()})},embed:function(){var e=this,t=Z("#customize-theme-controls"),n=Z(".customize-pane-parent");e.headContainer.parent().is(n)||n.append(e.headContainer),e.contentContainer.parent().is(e.headContainer)||t.append(e.contentContainer),e.renderContent(),e.deferred.embedded.resolve()},attachEvents:function(){var t,n=this;n.headContainer.find(".accordion-section-title").on("click keydown",function(e){ee.utils.isKeydownButNotEnterEvent(e)||(e.preventDefault(),n.expanded()||n.expand())}),n.container.find(".customize-panel-back").on("click keydown",function(e){ee.utils.isKeydownButNotEnterEvent(e)||(e.preventDefault(),n.expanded()&&n.collapse())}),(t=n.container.find(".panel-meta:first")).find("> .accordion-section-title .customize-help-toggle").on("click",function(){if(!t.hasClass("cannot-expand")){var e=t.find(".customize-panel-description:first");t.hasClass("open")?(t.toggleClass("open"),e.slideUp(n.defaultExpandedArguments.duration,function(){e.trigger("toggled")}),Z(this).attr("aria-expanded",!1)):(e.slideDown(n.defaultExpandedArguments.duration,function(){e.trigger("toggled")}),t.toggleClass("open"),Z(this).attr("aria-expanded",!0))}})},sections:function(){return this._children("panel","section")},isContextuallyActive:function(){var e=this.sections(),t=0;return _(e).each(function(e){e.active()&&e.isContextuallyActive()&&(t+=1)}),0!==t},onChangeExpanded:function(e,t){if(t.unchanged)t.completeCallback&&t.completeCallback();else{var n=this,i=n.contentContainer,a=i.closest(".wp-full-overlay"),o=i.closest(".wp-full-overlay-sidebar-content"),s=n.headContainer.find(".accordion-section-title"),r=i.find(".customize-panel-back"),c=n.sections();e&&!i.hasClass("current-panel")?(ee.section.each(function(e){n.id!==e.panel()&&e.collapse({duration:0})}),ee.panel.each(function(e){n!==e&&e.collapse({duration:0})}),n.params.autoExpandSoleSection&&1===c.length&&c[0].active.get()?(i.addClass("current-panel skip-transition"),a.addClass("in-sub-panel"),c[0].expand({completeCallback:t.completeCallback})):(n._animateChangeExpanded(function(){s.attr("tabindex","-1"),r.attr("tabindex","0"),r.focus(),i.css("top",""),o.scrollTop(0),t.completeCallback&&t.completeCallback()}),i.addClass("current-panel"),a.addClass("in-sub-panel")),ee.state("expandedPanel").set(n)):!e&&i.hasClass("current-panel")&&(i.hasClass("skip-transition")?i.removeClass("skip-transition"):n._animateChangeExpanded(function(){s.attr("tabindex","0"),r.attr("tabindex","-1"),s.focus(),i.css("top",""),t.completeCallback&&t.completeCallback()}),a.removeClass("in-sub-panel"),i.removeClass("current-panel"),n===ee.state("expandedPanel").get()&&ee.state("expandedPanel").set(!1))}},renderContent:function(){var e,t=this;(e=0!==Z("#tmpl-"+t.templateSelector+"-content").length?wp.template(t.templateSelector+"-content"):wp.template("customize-panel-default-content"))&&t.headContainer&&t.contentContainer.html(e(_.extend({id:t.id},t.params)))}}),ee.ThemesPanel=ee.Panel.extend({initialize:function(e,t){this.installingThemes=[],ee.Panel.prototype.initialize.call(this,e,t)},canSwitchTheme:function(e){return!(!e||e!==ee.settings.theme.stylesheet)||"publish"===ee.state("selectedChangesetStatus").get()&&(""===ee.state("changesetStatus").get()||"auto-draft"===ee.state("changesetStatus").get())},attachEvents:function(){var t=this;function e(){t.canSwitchTheme()?t.notifications.remove("theme_switch_unavailable"):t.notifications.add(new ee.Notification("theme_switch_unavailable",{message:ee.l10n.themePreviewUnavailable,type:"warning"}))}ee.Panel.prototype.attachEvents.apply(t),ee.settings.theme._canInstall&&ee.settings.theme._filesystemCredentialsNeeded&&t.notifications.add(new ee.Notification("theme_install_unavailable",{message:ee.l10n.themeInstallUnavailable,type:"info",dismissible:!0})),e(),ee.state("selectedChangesetStatus").bind(e),ee.state("changesetStatus").bind(e),t.contentContainer.on("click",".customize-theme",function(){t.collapse()}),t.contentContainer.on("click",".customize-themes-section-title, .customize-themes-mobile-back",function(){Z(".wp-full-overlay").toggleClass("showing-themes")}),t.contentContainer.on("click",".theme-install",function(e){t.installTheme(e)}),t.contentContainer.on("click",".update-theme, #update-theme",function(e){e.preventDefault(),e.stopPropagation(),t.updateTheme(e)}),t.contentContainer.on("click",".delete-theme",function(e){t.deleteTheme(e)}),_.bindAll(t,"installTheme","updateTheme")},onChangeExpanded:function(e,t){var n,i,a=!1;ee.Panel.prototype.onChangeExpanded.apply(this,[e,t]),t.unchanged?t.completeCallback&&t.completeCallback():(n=this.headContainer.closest(".wp-full-overlay"),e?(n.addClass("in-themes-panel").delay(200).find(".customize-themes-full-container").addClass("animate"),_.delay(function(){n.addClass("themes-panel-expanded")},200),600<window.innerWidth&&(i=this.sections(),_.each(i,function(e){e.expanded()&&(a=!0)}),!a&&0<i.length&&i[0].expand())):n.removeClass("in-themes-panel themes-panel-expanded").find(".customize-themes-full-container").removeClass("animate"))},installTheme:function(e){var i,t,n,a=this,o=Z(e.target).data("slug"),s=Z.Deferred();return i=Z(e.target).hasClass("preview"),ee.settings.theme._filesystemCredentialsNeeded?s.reject({errorCode:"theme_install_unavailable"}):a.canSwitchTheme(o)?_.contains(a.installingThemes,o)?s.reject({errorCode:"theme_already_installing"}):(wp.updates.maybeRequestFilesystemCredentials(e),t=function(t){var e,n=!1;if(i)ee.notifications.remove("theme_installing"),a.loadThemePreview(o);else{if(ee.control.each(function(e){"theme"===e.params.type&&e.params.theme.id===t.slug&&(n=e.params.theme,e.rerenderAsInstalled(!0))}),!n||ee.control.has("installed_theme_"+n.id))return void s.resolve(t);n.type="installed",e=new ee.controlConstructor.theme("installed_theme_"+n.id,{type:"theme",section:"installed_themes",theme:n,priority:0}),ee.control.add(e),ee.control(e.id).container.trigger("render-screenshot"),ee.section.each(function(e){"themes"===e.params.type&&n.id===e.currentTheme&&e.closeDetails()})}s.resolve(t)},a.installingThemes.push(o),n=wp.updates.installTheme({slug:o}),i&&ee.notifications.add(new ee.OverlayNotification("theme_installing",{message:ee.l10n.themeDownloading,type:"info",loading:!0})),n.done(t),n.fail(function(){ee.notifications.remove("theme_installing")})):s.reject({errorCode:"theme_switch_unavailable"}),s.promise()},loadThemePreview:function(e){var t,n,i,a=Z.Deferred();return this.canSwitchTheme(e)?((n=document.createElement("a")).href=location.href,i=_.extend(ee.utils.parseQueryString(n.search.substr(1)),{theme:e,changeset_uuid:ee.settings.changeset.uuid,return:ee.settings.url.return}),ee.state("saved").get()||(i.customize_autosaved="on"),n.search=Z.param(i),ee.notifications.add(new ee.OverlayNotification("theme_previewing",{message:ee.l10n.themePreviewWait,type:"info",loading:!0})),t=function(){var e;0<ee.state("processing").get()||(ee.state("processing").unbind(t),(e=ee.requestChangesetUpdate({},{autosave:!0})).done(function(){a.resolve(),Z(window).off("beforeunload.customize-confirm"),location.replace(n.href)}),e.fail(function(){ee.notifications.remove("theme_previewing"),a.reject()}))},0===ee.state("processing").get()?t():ee.state("processing").bind(t)):a.reject({errorCode:"theme_switch_unavailable"}),a.promise()},updateTheme:function(e){wp.updates.maybeRequestFilesystemCredentials(e),Z(document).one("wp-theme-update-success",function(e,t){ee.control.each(function(e){"theme"===e.params.type&&e.params.theme.id===t.slug&&(e.params.theme.hasUpdate=!1,e.params.theme.version=t.newVersion,setTimeout(function(){e.rerenderAsInstalled(!0)},2e3))})}),wp.updates.updateTheme({slug:Z(e.target).closest(".notice").data("slug")})},deleteTheme:function(e){var t,n;t=Z(e.target).data("slug"),n=ee.section("installed_themes"),e.preventDefault(),ee.settings.theme._filesystemCredentialsNeeded||window.confirm(ee.settings.l10n.confirmDeleteTheme)&&(wp.updates.maybeRequestFilesystemCredentials(e),Z(document).one("wp-theme-delete-success",function(){var e=ee.control("installed_theme_"+t);e.container.remove(),ee.control.remove(e.id),n.loaded=n.loaded-1,n.updateCount(),ee.control.each(function(e){"theme"===e.params.type&&e.params.theme.id===t&&e.rerenderAsInstalled(!1)})}),wp.updates.deleteTheme({slug:t}),n.closeDetails(),n.focus())}}),ee.Control=ee.Class.extend({defaultActiveArguments:{duration:"fast",completeCallback:Z.noop},defaults:{label:"",description:"",active:!0,priority:10},initialize:function(e,t){var n,i,a=this,o=[];a.params=_.extend({},a.defaults,a.params||{},t.params||t||{}),ee.Control.instanceCounter||(ee.Control.instanceCounter=0),ee.Control.instanceCounter++,a.params.instanceNumber||(a.params.instanceNumber=ee.Control.instanceCounter),a.params.type||_.find(ee.controlConstructor,function(e,t){return e===a.constructor&&(a.params.type=t,!0)}),a.params.content||(a.params.content=Z("<li></li>",{id:"customize-control-"+e.replace(/]/g,"").replace(/\[/g,"-"),class:"customize-control customize-control-"+a.params.type})),a.id=e,a.selector="#customize-control-"+e.replace(/\]/g,"").replace(/\[/g,"-"),a.params.content?a.container=Z(a.params.content):a.container=Z(a.selector),a.params.templateId?a.templateSelector=a.params.templateId:a.templateSelector="customize-control-"+a.params.type+"-content",a.deferred=_.extend(a.deferred||{},{embedded:new Z.Deferred}),a.section=new ee.Value,a.priority=new ee.Value,a.active=new ee.Value,a.activeArgumentsQueue=[],a.notifications=new ee.Notifications({alt:a.altNotice}),a.elements=[],a.active.bind(function(e){var t=a.activeArgumentsQueue.shift();t=Z.extend({},a.defaultActiveArguments,t),a.onChangeActive(e,t)}),a.section.set(a.params.section),a.priority.set(isNaN(a.params.priority)?10:a.params.priority),a.active.set(a.params.active),ee.utils.bubbleChildValueChanges(a,["section","priority","active"]),a.settings={},n={},a.params.setting&&(n.default=a.params.setting),_.extend(n,a.params.settings),_.each(n,function(e,t){var n;_.isObject(e)&&_.isFunction(e.extended)&&e.extended(ee.Value)?a.settings[t]=e:_.isString(e)&&((n=ee(e))?a.settings[t]=n:o.push(e))}),i=function(){_.each(n,function(e,t){!a.settings[t]&&_.isString(e)&&(a.settings[t]=ee(e))}),a.settings[0]&&!a.settings.default&&(a.settings.default=a.settings[0]),a.setting=a.settings.default||null,a.linkElements(),a.embed()},0===o.length?i():ee.apply(ee,o.concat(i)),a.deferred.embedded.done(function(){a.linkElements(),a.setupNotifications(),a.ready()})},linkElements:function(){var i,a,o,s=this;i=s.container.find("[data-customize-setting-link], [data-customize-setting-key-link]"),a={},i.each(function(){var e,t,n=Z(this);if(!n.data("customizeSettingLinked")){if(n.data("customizeSettingLinked",!0),n.is(":radio")){if(e=n.prop("name"),a[e])return;a[e]=!0,n=i.filter('[name="'+e+'"]')}n.data("customizeSettingLink")?t=ee(n.data("customizeSettingLink")):n.data("customizeSettingKeyLink")&&(t=s.settings[n.data("customizeSettingKeyLink")]),t&&(o=new ee.Element(n),s.elements.push(o),o.sync(t),o.set(t()))}})},embed:function(){var e,n=this;e=function(e){var t;e&&ee.section(e,function(e){e.deferred.embedded.done(function(){t=e.contentContainer.is("ul")?e.contentContainer:e.contentContainer.find("ul:first"),n.container.parent().is(t)||(t.append(n.container),n.renderContent()),n.deferred.embedded.resolve()})})},n.section.bind(e),e(n.section.get())},ready:function(){var t,n=this;"dropdown-pages"===n.params.type&&n.params.allow_addition&&((t=n.container.find(".new-content-item")).hide(),n.container.on("click",".add-new-toggle",function(e){Z(e.currentTarget).slideUp(180),t.slideDown(180),t.find(".create-item-input").focus()}),n.container.on("click",".add-content",function(){n.addNewPage()}),n.container.on("keydown",".create-item-input",function(e){13===e.which&&n.addNewPage()}))},getNotificationsContainerElement:function(){var e,t,n=this;return(t=n.container.find(".customize-control-notifications-container:first")).length||(t=Z('<div class="customize-control-notifications-container"></div>'),n.container.hasClass("customize-control-nav_menu_item")?n.container.find(".menu-item-settings:first").prepend(t):n.container.hasClass("customize-control-widget_form")?n.container.find(".widget-inside:first").prepend(t):(e=n.container.find(".customize-control-title")).length?e.after(t):n.container.prepend(t)),t},setupNotifications:function(){var n,e,i=this;_.each(i.settings,function(n){n.notifications&&(n.notifications.bind("add",function(e){var t=_.extend({},e,{setting:n.id});i.notifications.add(new ee.Notification(n.id+":"+e.code,t))}),n.notifications.bind("remove",function(e){i.notifications.remove(n.id+":"+e.code)}))}),n=function(){var e=i.section();(!e||ee.section.has(e)&&ee.section(e).expanded())&&i.notifications.render()},i.notifications.bind("rendered",function(){var e=i.notifications.get();i.container.toggleClass("has-notifications",0!==e.length),i.container.toggleClass("has-error",0!==_.where(e,{type:"error"}).length)}),e=function(e,t){t&&ee.section.has(t)&&ee.section(t).expanded.unbind(n),e&&ee.section(e,function(e){e.expanded.bind(n),n()})},i.section.bind(e),e(i.section.get()),i.notifications.bind("change",_.debounce(n))},renderNotifications:function(){var e,t,n=this,i=!1;"undefined"!=typeof console&&console.warn&&console.warn("[DEPRECATED] wp.customize.Control.prototype.renderNotifications() is deprecated in favor of instantating a wp.customize.Notifications and calling its render() method."),(e=n.getNotificationsContainerElement())&&e.length&&(t=[],n.notifications.each(function(e){t.push(e),"error"===e.type&&(i=!0)}),0===t.length?e.stop().slideUp("fast"):e.stop().slideDown("fast",null,function(){Z(this).css("height","auto")}),n.notificationsTemplate||(n.notificationsTemplate=wp.template("customize-control-notifications")),n.container.toggleClass("has-notifications",0!==t.length),n.container.toggleClass("has-error",i),e.empty().append(Z.trim(n.notificationsTemplate({notifications:t,altNotice:Boolean(n.altNotice)}))))},expand:function(e){ee.section(this.section()).expand(e)},focus:t,onChangeActive:function(e,t){t.unchanged?t.completeCallback&&t.completeCallback():Z.contains(document,this.container[0])?e?this.container.slideDown(t.duration,t.completeCallback):this.container.slideUp(t.duration,t.completeCallback):(this.container.toggle(e),t.completeCallback&&t.completeCallback())},toggle:function(e){return this.onChangeActive(e,this.defaultActiveArguments)},activate:a.prototype.activate,deactivate:a.prototype.deactivate,_toggleActive:a.prototype._toggleActive,dropdownInit:function(){function e(e){"string"==typeof e&&i.statuses&&i.statuses[e]?n.html(i.statuses[e]).show():n.hide()}var t=this,n=this.container.find(".dropdown-status"),i=this.params,a=!1;this.container.on("click keydown",".dropdown",function(e){ee.utils.isKeydownButNotEnterEvent(e)||(e.preventDefault(),a||t.container.toggleClass("open"),t.container.hasClass("open")&&t.container.parent().parent().find("li.library-selected").focus(),a=!0,setTimeout(function(){a=!1},400))}),this.setting.bind(e),e(this.setting())},renderContent:function(){var e,t,n,i,a=this;t=["button","checkbox","date","datetime-local","email","month","number","password","radio","range","search","select","tel","time","text","textarea","week","url"],(n=a.templateSelector)==="customize-control-"+a.params.type+"-content"&&_.contains(t,a.params.type)&&!document.getElementById("tmpl-"+n)&&0===a.container.children().length&&(n="customize-control-default-content"),document.getElementById("tmpl-"+n)&&(e=wp.template(n))&&a.container&&a.container.html(e(a.params)),a.notifications.container=a.getNotificationsContainerElement(),(!(i=a.section())||ee.section.has(i)&&ee.section(i).expanded())&&a.notifications.render()},addNewPage:function(){var e,a,o,t,s,r,c=this;"dropdown-pages"===c.params.type&&c.params.allow_addition&&ee.Menus&&(a=c.container.find(".add-new-toggle"),o=c.container.find(".new-content-item"),t=c.container.find(".create-item-input"),s=t.val(),r=c.container.find("select"),s?(t.removeClass("invalid"),t.attr("disabled","disabled"),(e=ee.Menus.insertAutoDraftPost({post_title:s,post_type:"page"})).done(function(e){var t,n,i;t=new ee.Menus.AvailableItemModel({id:"post-"+e.post_id,title:s,type:"post_type",type_label:ee.Menus.data.l10n.page_label,object:"page",object_id:e.post_id,url:e.url}),ee.Menus.availableMenuItemsPanel.collection.add(t),n=Z("#available-menu-items-post_type-page").find(".available-menu-items-list"),i=wp.template("available-menu-item"),n.prepend(i(t.attributes)),r.focus(),c.setting.set(String(e.post_id)),o.slideUp(180),a.slideDown(180)}),e.always(function(){t.val("").removeAttr("disabled")})):t.addClass("invalid"))}}),ee.ColorControl=ee.Control.extend({ready:function(){var t,n=this,e="hue"===this.params.mode,i=!1;e?(t=this.container.find(".color-picker-hue")).val(n.setting()).wpColorPicker({change:function(e,t){i=!0,n.setting(t.color.h()),i=!1}}):(t=this.container.find(".color-picker-hex")).val(n.setting()).wpColorPicker({change:function(){i=!0,n.setting.set(t.wpColorPicker("color")),i=!1},clear:function(){i=!0,n.setting.set(""),i=!1}}),n.setting.bind(function(e){i||(t.val(e),t.wpColorPicker("color",e))}),n.container.on("keydown",function(e){27===e.which&&n.container.find(".wp-picker-container").hasClass("wp-picker-active")&&(t.wpColorPicker("close"),n.container.find(".wp-color-result").focus(),e.stopPropagation())})}}),ee.MediaControl=ee.Control.extend({ready:function(){var n=this;function e(e){var t=Z.Deferred();n.extended(ee.UploadControl)?t.resolve():(e=parseInt(e,10),_.isNaN(e)||e<=0?(delete n.params.attachment,t.resolve()):n.params.attachment&&n.params.attachment.id===e&&t.resolve()),"pending"===t.state()&&wp.media.attachment(e).fetch().done(function(){n.params.attachment=this.attributes,t.resolve(),wp.customize.previewer.send(n.setting.id+"-attachment-data",this.attributes)}),t.done(function(){n.renderContent()})}_.bindAll(n,"restoreDefault","removeFile","openFrame","select","pausePlayer"),n.container.on("click keydown",".upload-button",n.openFrame),n.container.on("click keydown",".upload-button",n.pausePlayer),n.container.on("click keydown",".thumbnail-image img",n.openFrame),n.container.on("click keydown",".default-button",n.restoreDefault),n.container.on("click keydown",".remove-button",n.pausePlayer),n.container.on("click keydown",".remove-button",n.removeFile),n.container.on("click keydown",".remove-button",n.cleanupPlayer),ee.section(n.section()).container.on("expanded",function(){n.player&&n.player.setControlsSize()}).on("collapsed",function(){n.pausePlayer()}),e(n.setting()),n.setting.bind(e)},pausePlayer:function(){this.player&&this.player.pause()},cleanupPlayer:function(){this.player&&wp.media.mixin.removePlayer(this.player)},openFrame:function(e){ee.utils.isKeydownButNotEnterEvent(e)||(e.preventDefault(),this.frame||this.initFrame(),this.frame.open())},initFrame:function(){this.frame=wp.media({button:{text:this.params.button_labels.frame_button},states:[new wp.media.controller.Library({title:this.params.button_labels.frame_title,library:wp.media.query({type:this.params.mime_type}),multiple:!1,date:!1})]}),this.frame.on("select",this.select)},select:function(){var e,t=this.frame.state().get("selection").first().toJSON(),n=window._wpmejsSettings||{};this.params.attachment=t,this.setting(t.id),(e=this.container.find("audio, video").get(0))?this.player=new MediaElementPlayer(e,n):this.cleanupPlayer()},restoreDefault:function(e){ee.utils.isKeydownButNotEnterEvent(e)||(e.preventDefault(),this.params.attachment=this.params.defaultAttachment,this.setting(this.params.defaultAttachment.url))},removeFile:function(e){ee.utils.isKeydownButNotEnterEvent(e)||(e.preventDefault(),this.params.attachment={},this.setting(""),this.renderContent())}}),ee.UploadControl=ee.MediaControl.extend({select:function(){var e,t=this.frame.state().get("selection").first().toJSON(),n=window._wpmejsSettings||{};this.params.attachment=t,this.setting(t.url),(e=this.container.find("audio, video").get(0))?this.player=new MediaElementPlayer(e,n):this.cleanupPlayer()},success:function(){},removerVisibility:function(){}}),ee.ImageControl=ee.UploadControl.extend({thumbnailSrc:function(){}}),ee.BackgroundControl=ee.UploadControl.extend({ready:function(){ee.UploadControl.prototype.ready.apply(this,arguments)},select:function(){ee.UploadControl.prototype.select.apply(this,arguments),wp.ajax.post("custom-background-add",{nonce:_wpCustomizeBackground.nonces.add,wp_customize:"on",customize_theme:ee.settings.theme.stylesheet,attachment_id:this.params.attachment.id})}}),ee.BackgroundPositionControl=ee.Control.extend({ready:function(){var e,i=this;i.container.on("change",'input[name="background-position"]',function(){var e=Z(this).val().split(" ");i.settings.x(e[0]),i.settings.y(e[1])}),e=_.debounce(function(){var e,t,n;e=i.settings.x.get(),t=i.settings.y.get(),n=String(e)+" "+String(t),i.container.find('input[name="background-position"][value="'+n+'"]').click()}),i.settings.x.bind(e),i.settings.y.bind(e),e()}}),ee.CroppedImageControl=ee.MediaControl.extend({openFrame:function(e){ee.utils.isKeydownButNotEnterEvent(e)||(this.initFrame(),this.frame.setState("library").open())},initFrame:function(){var e=_wpMediaViewsL10n;this.frame=wp.media({button:{text:e.select,close:!1},states:[new wp.media.controller.Library({title:this.params.button_labels.frame_title,library:wp.media.query({type:"image"}),multiple:!1,date:!1,priority:20,suggestedWidth:this.params.width,suggestedHeight:this.params.height}),new wp.media.controller.CustomizeImageCropper({imgSelectOptions:this.calculateImageSelectOptions,control:this})]}),this.frame.on("select",this.onSelect,this),this.frame.on("cropped",this.onCropped,this),this.frame.on("skippedcrop",this.onSkippedCrop,this)},onSelect:function(){var e=this.frame.state().get("selection").first().toJSON();this.params.width!==e.width||this.params.height!==e.height||this.params.flex_width||this.params.flex_height?this.frame.setState("cropper"):(this.setImageFromAttachment(e),this.frame.close())},onCropped:function(e){this.setImageFromAttachment(e)},calculateImageSelectOptions:function(e,t){var n,i,a,o=t.get("control"),s=!!parseInt(o.params.flex_width,10),r=!!parseInt(o.params.flex_height,10),c=e.get("width"),l=e.get("height"),d=parseInt(o.params.width,10),u=parseInt(o.params.height,10),p=d/u,h=d,f=u;return t.set("canSkipCrop",!o.mustBeCropped(s,r,d,u,c,l)),p<c/l?d=(u=l)*p:u=(d=c)/p,!(a={handles:!0,keys:!0,instance:!0,persistent:!0,imageWidth:c,imageHeight:l,minWidth:d<h?d:h,minHeight:u<f?u:f,x1:n=(c-d)/2,y1:i=(l-u)/2,x2:d+n,y2:u+i})==r&&!1==s&&(a.aspectRatio=d+":"+u),!0==r&&(delete a.minHeight,a.maxWidth=c),!0==s&&(delete a.minWidth,a.maxHeight=l),a},mustBeCropped:function(e,t,n,i,a,o){return(!0!==e||!0!==t)&&((!0!==e||i!==o)&&((!0!==t||n!==a)&&((n!==a||i!==o)&&!(a<=n))))},onSkippedCrop:function(){var e=this.frame.state().get("selection").first().toJSON();this.setImageFromAttachment(e)},setImageFromAttachment:function(e){this.params.attachment=e,this.setting(e.id)}}),ee.SiteIconControl=ee.CroppedImageControl.extend({initFrame:function(){var e=_wpMediaViewsL10n;this.frame=wp.media({button:{text:e.select,close:!1},states:[new wp.media.controller.Library({title:this.params.button_labels.frame_title,library:wp.media.query({type:"image"}),multiple:!1,date:!1,priority:20,suggestedWidth:this.params.width,suggestedHeight:this.params.height}),new wp.media.controller.SiteIconCropper({imgSelectOptions:this.calculateImageSelectOptions,control:this})]}),this.frame.on("select",this.onSelect,this),this.frame.on("cropped",this.onCropped,this),this.frame.on("skippedcrop",this.onSkippedCrop,this)},onSelect:function(){var e=this.frame.state().get("selection").first().toJSON(),t=this;this.params.width!==e.width||this.params.height!==e.height||this.params.flex_width||this.params.flex_height?this.frame.setState("cropper"):wp.ajax.post("crop-image",{nonce:e.nonces.edit,id:e.id,context:"site-icon",cropDetails:{x1:0,y1:0,width:this.params.width,height:this.params.height,dst_width:this.params.width,dst_height:this.params.height}}).done(function(e){t.setImageFromAttachment(e),t.frame.close()}).fail(function(){t.frame.trigger("content:error:crop")})},setImageFromAttachment:function(t){var n;_.each(["site_icon-32","thumbnail","full"],function(e){n||_.isUndefined(t.sizes[e])||(n=t.sizes[e])}),this.params.attachment=t,this.setting(t.id),n&&Z('link[rel="icon"][sizes="32x32"]').attr("href",n.url)},removeFile:function(e){ee.utils.isKeydownButNotEnterEvent(e)||(e.preventDefault(),this.params.attachment={},this.setting(""),this.renderContent(),Z('link[rel="icon"][sizes="32x32"]').attr("href","/favicon.ico"))}}),ee.HeaderControl=ee.Control.extend({ready:function(){this.btnRemove=Z("#customize-control-header_image .actions .remove"),this.btnNew=Z("#customize-control-header_image .actions .new"),_.bindAll(this,"openMedia","removeImage"),this.btnNew.on("click",this.openMedia),this.btnRemove.on("click",this.removeImage),ee.HeaderTool.currentHeader=this.getInitialHeaderImage(),new ee.HeaderTool.CurrentView({model:ee.HeaderTool.currentHeader,el:"#customize-control-header_image .current .container"}),new ee.HeaderTool.ChoiceListView({collection:ee.HeaderTool.UploadsList=new ee.HeaderTool.ChoiceList,el:"#customize-control-header_image .choices .uploaded .list"}),new ee.HeaderTool.ChoiceListView({collection:ee.HeaderTool.DefaultsList=new ee.HeaderTool.DefaultsList,el:"#customize-control-header_image .choices .default .list"}),ee.HeaderTool.combinedList=ee.HeaderTool.CombinedList=new ee.HeaderTool.CombinedList([ee.HeaderTool.UploadsList,ee.HeaderTool.DefaultsList]),wp.media.controller.Cropper.prototype.defaults.doCropArgs.wp_customize="on",wp.media.controller.Cropper.prototype.defaults.doCropArgs.customize_theme=ee.settings.theme.stylesheet},getInitialHeaderImage:function(){if(!ee.get().header_image||!ee.get().header_image_data||_.contains(["remove-header","random-default-image","random-uploaded-image"],ee.get().header_image))return new ee.HeaderTool.ImageModel;var e=_.find(_wpCustomizeHeader.uploads,function(e){return e.attachment_id===ee.get().header_image_data.attachment_id});return e=e||{url:ee.get().header_image,thumbnail_url:ee.get().header_image,attachment_id:ee.get().header_image_data.attachment_id},new ee.HeaderTool.ImageModel({header:e,choice:e.url.split("/").pop()})},calculateImageSelectOptions:function(e,t){var n,i,a,o,s,r,c=parseInt(_wpCustomizeHeader.data.width,10),l=parseInt(_wpCustomizeHeader.data.height,10),d=!!parseInt(_wpCustomizeHeader.data["flex-width"],10),u=!!parseInt(_wpCustomizeHeader.data["flex-height"],10);return s=e.get("width"),o=e.get("height"),this.headerImage=new ee.HeaderTool.ImageModel,this.headerImage.set({themeWidth:c,themeHeight:l,themeFlexWidth:d,themeFlexHeight:u,imageWidth:s,imageHeight:o}),t.set("canSkipCrop",!this.headerImage.shouldBeCropped()),(n=c/l)<(i=s)/(a=o)?c=(l=a)*n:l=(c=i)/n,!(r={handles:!0,keys:!0,instance:!0,persistent:!0,imageWidth:s,imageHeight:o,x1:0,y1:0,x2:c,y2:l})==u&&!1==d&&(r.aspectRatio=c+":"+l),!1==u&&(r.maxHeight=l),!1==d&&(r.maxWidth=c),r},openMedia:function(e){var t=_wpMediaViewsL10n;e.preventDefault(),this.frame=wp.media({button:{text:t.selectAndCrop,close:!1},states:[new wp.media.controller.Library({title:t.chooseImage,library:wp.media.query({type:"image"}),multiple:!1,date:!1,priority:20,suggestedWidth:_wpCustomizeHeader.data.width,suggestedHeight:_wpCustomizeHeader.data.height}),new wp.media.controller.Cropper({imgSelectOptions:this.calculateImageSelectOptions})]}),this.frame.on("select",this.onSelect,this),this.frame.on("cropped",this.onCropped,this),this.frame.on("skippedcrop",this.onSkippedCrop,this),this.frame.open()},onSelect:function(){this.frame.setState("cropper")},onCropped:function(e){var t=e.url,n=e.attachment_id,i=e.width,a=e.height;this.setImageFromURL(t,n,i,a)},onSkippedCrop:function(e){var t=e.get("url"),n=e.get("width"),i=e.get("height");this.setImageFromURL(t,e.id,n,i)},setImageFromURL:function(e,t,n,i){var a,o={};o.url=e,o.thumbnail_url=e,o.timestamp=_.now(),t&&(o.attachment_id=t),n&&(o.width=n),i&&(o.height=i),a=new ee.HeaderTool.ImageModel({header:o,choice:e.split("/").pop()}),ee.HeaderTool.UploadsList.add(a),ee.HeaderTool.currentHeader.set(a.toJSON()),a.save(),a.importImage()},removeImage:function(){ee.HeaderTool.currentHeader.trigger("hide"),ee.HeaderTool.CombinedList.trigger("control:removeImage")}}),ee.ThemeControl=ee.Control.extend({touchDrag:!1,screenshotRendered:!1,ready:function(){var n=this,e=ee.panel("themes");function t(){return!e.canSwitchTheme(n.params.theme.id)}function i(){n.container.find("button.preview, button.preview-theme").toggleClass("disabled",t()),n.container.find("button.theme-install").toggleClass("disabled",t()||!1===ee.settings.theme._canInstall||!0===ee.settings.theme._filesystemCredentialsNeeded)}ee.state("selectedChangesetStatus").bind(i),ee.state("changesetStatus").bind(i),i(),n.container.on("touchmove",".theme",function(){n.touchDrag=!0}),n.container.on("click keydown touchend",".theme",function(e){var t;if(!ee.utils.isKeydownButNotEnterEvent(e))return!0===n.touchDrag?n.touchDrag=!1:void(Z(e.target).is(".theme-actions .button, .update-theme")||(e.preventDefault(),(t=ee.section(n.section())).showDetails(n.params.theme,function(){ee.settings.theme._filesystemCredentialsNeeded&&t.overlay.find(".theme-actions .delete-theme").remove()})))}),n.container.on("render-screenshot",function(){var e=Z(this).find("img"),t=e.data("src");t&&e.attr("src",t),n.screenshotRendered=!0})},filter:function(e){var t=this,n=0,i=t.params.theme.name+" "+t.params.theme.description+" "+t.params.theme.tags+" "+t.params.theme.author+" ";return i=i.toLowerCase().replace("-"," "),_.isArray(e)||(e=[e]),t.params.theme.name.toLowerCase()===e.join(" ")?n=100:(n+=10*(i.split(e.join(" ")).length-1),_.each(e,function(e){n=(n+=2*(i.split(e+" ").length-1))+i.split(e).length-1}),99<n&&(n=99)),0!==n?(t.activate(),t.params.priority=101-n,!0):(t.deactivate(),!(t.params.priority=101))},rerenderAsInstalled:function(e){var t,n=this;e?n.params.theme.type="installed":(t=ee.section(n.params.section),n.params.theme.type=t.params.action),n.renderContent(),n.container.trigger("render-screenshot")}}),ee.CodeEditorControl=ee.Control.extend({initialize:function(e,t){var n=this;n.deferred=_.extend(n.deferred||{},{codemirror:Z.Deferred()}),ee.Control.prototype.initialize.call(n,e,t),n.notifications.bind("add",function(e){var t;e.code===n.setting.id+":csslint_error"&&(e.templateId="customize-code-editor-lint-error-notification",e.render=(t=e.render,function(){var e=t.call(this);return e.find("input[type=checkbox]").on("click",function(){n.setting.notifications.remove("csslint_error")}),e}))})},ready:function(){var i=this;i.section()?ee.section(i.section(),function(n){n.deferred.embedded.done(function(){var t;n.expanded()?i.initEditor():(t=function(e){e&&(i.initEditor(),n.expanded.unbind(t))},n.expanded.bind(t))})}):i.initEditor()},initEditor:function(){var e,t=this,n=!1;wp.codeEditor&&(_.isUndefined(t.params.editor_settings)||!1!==t.params.editor_settings)&&((n=wp.codeEditor.defaultSettings?_.clone(wp.codeEditor.defaultSettings):{}).codemirror=_.extend({},n.codemirror,{indentUnit:2,tabSize:2}),_.isObject(t.params.editor_settings)&&_.each(t.params.editor_settings,function(e,t){_.isObject(e)&&(n[t]=_.extend({},n[t],e))})),e=new ee.Element(t.container.find("textarea")),t.elements.push(e),e.sync(t.setting),e.set(t.setting()),n?t.initSyntaxHighlightingEditor(n):t.initPlainTextareaEditor()},focus:function(e){var t,n=this,i=_.extend({},e);t=i.completeCallback,i.completeCallback=function(){t&&t(),n.editor&&n.editor.codemirror.focus()},ee.Control.prototype.focus.call(n,i)},initSyntaxHighlightingEditor:function(e){var t,n=this,i=n.container.find("textarea"),a=!1;t=_.extend({},e,{onTabNext:_.bind(n.onTabNext,n),onTabPrevious:_.bind(n.onTabPrevious,n),onUpdateErrorNotice:_.bind(n.onUpdateErrorNotice,n)}),n.editor=wp.codeEditor.initialize(i,t),Z(n.editor.codemirror.display.lineDiv).attr({role:"textbox","aria-multiline":"true","aria-label":n.params.label,"aria-describedby":"editor-keyboard-trap-help-1 editor-keyboard-trap-help-2 editor-keyboard-trap-help-3 editor-keyboard-trap-help-4"}),n.container.find("label").on("click",function(){n.editor.codemirror.focus()}),n.editor.codemirror.on("change",function(e){a=!0,i.val(e.getValue()).trigger("change"),a=!1}),n.setting.bind(function(e){a||n.editor.codemirror.setValue(e)}),n.editor.codemirror.on("keydown",function(e,t){27===t.keyCode&&t.stopPropagation()}),n.deferred.codemirror.resolveWith(n,[n.editor.codemirror])},onTabNext:function(){var e,t;t=(e=ee.section(this.section()).controls()).indexOf(this),e.length===t+1?Z("#customize-footer-actions .collapse-sidebar").focus():e[t+1].container.find(":focusable:first").focus()},onTabPrevious:function(){var e,t,n;0===(t=(e=(n=ee.section(this.section())).controls()).indexOf(this))?n.contentContainer.find(".customize-section-title .customize-help-toggle, .customize-section-title .customize-section-description.open .section-description-close").last().focus():e[t-1].contentContainer.find(":focusable:first").focus()},onUpdateErrorNotice:function(e){var t;this.setting.notifications.remove("csslint_error"),0!==e.length&&(t=1===e.length?ee.l10n.customCssError.singular.replace("%d","1"):ee.l10n.customCssError.plural.replace("%d",String(e.length)),this.setting.notifications.add(new ee.Notification("csslint_error",{message:t,type:"error"})))},initPlainTextareaEditor:function(){var a=this.container.find("textarea"),o=a[0];a.on("blur",function(){a.data("next-tab-blurs",!1)}),a.on("keydown",function(e){var t,n,i;27!==e.keyCode?9!==e.keyCode||e.ctrlKey||e.altKey||e.shiftKey||a.data("next-tab-blurs")||(t=o.selectionStart,n=o.selectionEnd,i=o.value,0<=t&&(o.value=i.substring(0,t).concat("\t",i.substring(n)),a.selectionStart=o.selectionEnd=t+1),e.stopPropagation(),e.preventDefault()):a.data("next-tab-blurs")||(a.data("next-tab-blurs",!0),e.stopPropagation())}),this.deferred.codemirror.rejectWith(this)}}),ee.DateTimeControl=ee.Control.extend({ready:function(){var i=this;if(i.inputElements={},i.invalidDate=!1,_.bindAll(i,"populateSetting","updateDaysForMonth","populateDateInputs"),!i.setting)throw new Error("Missing setting");i.container.find(".date-input").each(function(){var e,t,n=Z(this);e=n.data("component"),t=new ee.Element(n),i.inputElements[e]=t,i.elements.push(t),n.on("change",function(){i.invalidDate&&i.notifications.add(new ee.Notification("invalid_date",{message:ee.l10n.invalidDate}))}),n.on("input",_.debounce(function(){i.invalidDate||i.notifications.remove("invalid_date")})),n.on("blur",_.debounce(function(){i.invalidDate||i.populateDateInputs()}))}),i.inputElements.month.bind(i.updateDaysForMonth),i.inputElements.year.bind(i.updateDaysForMonth),i.populateDateInputs(),i.setting.bind(i.populateDateInputs),_.each(i.inputElements,function(e){e.bind(i.populateSetting)})},parseDateTime:function(e){var t,n;return e&&(t=e.match(/^(\d\d\d\d)-(\d\d)-(\d\d)(?: (\d\d):(\d\d)(?::(\d\d))?)?$/)),t?(t.shift(),n={year:t.shift(),month:t.shift(),day:t.shift(),hour:t.shift()||"00",minute:t.shift()||"00",second:t.shift()||"00"},this.params.includeTime&&this.params.twelveHourFormat&&(n.hour=parseInt(n.hour,10),n.meridian=12<=n.hour?"pm":"am",n.hour=n.hour%12?String(n.hour%12):String(12),delete n.second),n):null},validateInputs:function(){var e,o,s=this;return s.invalidDate=!1,e=["year","day"],s.params.includeTime&&e.push("hour","minute"),_.find(e,function(e){var t,n,i,a;return t=s.inputElements[e],o=t.element.get(0),n=parseInt(t.element.attr("max"),10),i=parseInt(t.element.attr("min"),10),a=parseInt(t(),10),s.invalidDate=isNaN(a)||n<a||a<i,s.invalidDate||o.setCustomValidity(""),s.invalidDate}),s.inputElements.meridian&&!s.invalidDate&&(o=s.inputElements.meridian.element.get(0),"am"!==s.inputElements.meridian.get()&&"pm"!==s.inputElements.meridian.get()?s.invalidDate=!0:o.setCustomValidity("")),s.invalidDate?o.setCustomValidity(ee.l10n.invalidValue):o.setCustomValidity(""),(!s.section()||ee.section.has(s.section())&&ee.section(s.section()).expanded())&&_.result(o,"reportValidity"),s.invalidDate},updateDaysForMonth:function(){var e,t,n,i,a=this;n=parseInt(a.inputElements.month(),10),t=parseInt(a.inputElements.year(),10),i=parseInt(a.inputElements.day(),10),n&&t&&(e=new Date(t,n,0).getDate(),a.inputElements.day.element.attr("max",e),e<i&&a.inputElements.day(String(e)))},populateSetting:function(){var e,t=this;return!(t.validateInputs()||!t.params.allowPastDate&&!t.isFutureDate())&&(e=t.convertInputDateToString(),t.setting.set(e),!0)},convertInputDateToString:function(){var e,t,n,i,a=this,o="";return i=function(e,t){var n;return String(e).length<t&&(n=t-String(e).length,e=Math.pow(10,n).toString().substr(1)+String(e)),e},n=function(e){var t=parseInt(a.inputElements[e].get(),10);return _.contains(["month","day","hour","minute"],e)?t=i(t,2):"year"===e&&(t=i(t,4)),t},e=["year","-","month","-","day"],a.params.includeTime&&(t=a.inputElements.meridian?a.convertHourToTwentyFourHourFormat(a.inputElements.hour(),a.inputElements.meridian()):a.inputElements.hour(),e=e.concat([" ",i(t,2),":","minute",":","00"])),_.each(e,function(e){o+=a.inputElements[e]?n(e):e}),o},isFutureDate:function(){return 0<ee.utils.getRemainingTime(this.convertInputDateToString())},convertHourToTwentyFourHourFormat:function(e,t){var n,i;return i=parseInt(e,10),isNaN(i)?"":(n="pm"===t&&i<12?i+12:"am"===t&&12===i?i-12:i,String(n))},populateDateInputs:function(){var i;return!!(i=this.parseDateTime(this.setting.get()))&&(_.each(this.inputElements,function(e,t){var n=i[t];"month"===t||"meridian"===t?(n=n.replace(/^0/,""),e.set(n)):(n=parseInt(n,10),e.element.is(document.activeElement)?n!==parseInt(e(),10)&&e.set(String(n)):e.set(i[t]))}),!0)},toggleFutureDateNotification:function(e){var t,n;return t="not_future_date",e?(n=new ee.Notification(t,{type:"error",message:ee.l10n.futureDateError}),this.notifications.add(n)):this.notifications.remove(t),this}}),ee.PreviewLinkControl=ee.Control.extend({defaults:_.extend({},ee.Control.prototype.defaults,{templateId:"customize-preview-link-control"}),ready:function(){var e,t,n,i,a,o,s=this;_.bindAll(s,"updatePreviewLink"),s.setting||(s.setting=new ee.Value),s.previewElements={},s.container.find(".preview-control-element").each(function(){n=Z(this),t=n.data("component"),e=new ee.Element(n),s.previewElements[t]=e,s.elements.push(e)}),i=s.previewElements.url,a=s.previewElements.input,o=s.previewElements.button,a.link(s.setting),i.link(s.setting),i.bind(function(e){i.element.parent().attr({href:e,target:ee.settings.changeset.uuid})}),ee.bind("ready",s.updatePreviewLink),ee.state("saved").bind(s.updatePreviewLink),ee.state("changesetStatus").bind(s.updatePreviewLink),ee.state("activated").bind(s.updatePreviewLink),ee.previewer.previewUrl.bind(s.updatePreviewLink),o.element.on("click",function(e){e.preventDefault(),s.setting()&&(a.element.select(),document.execCommand("copy"),o(o.element.data("copied-text")))}),i.element.parent().on("click",function(e){Z(this).hasClass("disabled")&&e.preventDefault()}),o.element.on("mouseenter",function(){s.setting()&&o(o.element.data("copy-text"))})},updatePreviewLink:function(){var e;e=!ee.state("saved").get()||""===ee.state("changesetStatus").get()||"auto-draft"===ee.state("changesetStatus").get(),this.toggleSaveNotification(e),this.previewElements.url.element.parent().toggleClass("disabled",e),this.previewElements.button.element.prop("disabled",e),this.setting.set(ee.previewer.getFrontendPreviewUrl())},toggleSaveNotification:function(e){var t,n;t="changes_not_saved",e?(n=new ee.Notification(t,{type:"info",message:ee.l10n.saveBeforeShare}),this.notifications.add(n)):this.notifications.remove(t)}}),ee.defaultConstructor=ee.Setting,ee.control=new ee.Values({defaultConstructor:ee.Control}),ee.section=new ee.Values({defaultConstructor:ee.Section}),ee.panel=new ee.Values({defaultConstructor:ee.Panel}),ee.notifications=new ee.Notifications,ee.PreviewFrame=ee.Messenger.extend({sensitivity:null,initialize:function(e,t){var n=Z.Deferred();n.promise(this),this.container=e.container,Z.extend(e,{channel:ee.PreviewFrame.uuid()}),ee.Messenger.prototype.initialize.call(this,e,t),this.add("previewUrl",e.previewUrl),this.query=Z.extend(e.query||{},{customize_messenger_channel:this.channel()}),this.run(n)},run:function(t){var e,n,i,a=this,o=!1,s=!1,r=null,c="{}"!==a.query.customized;a._ready&&a.unbind("ready",a._ready),a._ready=function(e){s=!0,r=e,a.container.addClass("iframe-ready"),e&&o&&t.resolveWith(a,[e])},a.bind("ready",a._ready),(e=document.createElement("a")).href=a.previewUrl(),n=_.extend(ee.utils.parseQueryString(e.search.substr(1)),{customize_changeset_uuid:a.query.customize_changeset_uuid,customize_theme:a.query.customize_theme,customize_messenger_channel:a.query.customize_messenger_channel}),!ee.settings.changeset.autosaved&&ee.state("saved").get()||(n.customize_autosaved="on"),e.search=Z.param(n),a.iframe=Z("<iframe />",{title:ee.l10n.previewIframeTitle,name:"customize-"+a.channel()}),a.iframe.attr("onmousewheel",""),a.iframe.attr("sandbox","allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-same-origin allow-scripts"),c?a.iframe.attr("data-src",e.href):a.iframe.attr("src",e.href),a.iframe.appendTo(a.container),a.targetWindow(a.iframe[0].contentWindow),c&&((i=Z("<form>",{action:e.href,target:a.iframe.attr("name"),method:"post",hidden:"hidden"})).append(Z("<input>",{type:"hidden",name:"_method",value:"GET"})),_.each(a.query,function(e,t){i.append(Z("<input>",{type:"hidden",name:t,value:e}))}),a.container.append(i),i.submit(),i.remove()),a.bind("iframe-loading-error",function(e){a.iframe.remove(),0!==e?-1!==e?t.rejectWith(a,["request failure"]):t.rejectWith(a,["cheatin"]):a.login(t)}),a.iframe.one("load",function(){o=!0,s?t.resolveWith(a,[r]):setTimeout(function(){t.rejectWith(a,["ready timeout"])},a.sensitivity)})},login:function(n){var i,a=this;if(i=function(){n.rejectWith(a,["logged out"])},this.triedLogin)return i();Z.get(ee.settings.url.ajax,{action:"logged-in"}).fail(i).done(function(e){var t;"1"!==e&&i(),(t=Z("<iframe />",{src:a.previewUrl(),title:ee.l10n.previewIframeTitle}).hide()).appendTo(a.container),t.on("load",function(){a.triedLogin=!0,t.remove(),a.run(n)})})},destroy:function(){ee.Messenger.prototype.destroy.call(this),this.iframe&&this.iframe.remove(),delete this.iframe,delete this.targetWindow}}),r=0,ee.PreviewFrame.uuid=function(){return"preview-"+String(r++)},ee.setDocumentTitle=function(e){var t;t=ee.settings.documentTitleTmpl.replace("%s",e),document.title=t,ee.trigger("title",t)},ee.Previewer=ee.Messenger.extend({refreshBuffer:null,initialize:function(e,t){var n,s=this,i=document.createElement("a");Z.extend(s,t||{}),s.deferred={active:Z.Deferred()},s.refresh=_.debounce((n=s.refresh,function(){var e,t;(e=function(){return 0===ee.state("processing").get()})()?n.call(s):(t=function(){e()&&(n.call(s),ee.state("processing").unbind(t))},ee.state("processing").bind(t))}),s.refreshBuffer),s.container=ee.ensure(e.container),s.allowedUrls=e.allowedUrls,e.url=window.location.href,ee.Messenger.prototype.initialize.call(s,e),i.href=s.origin(),s.add("scheme",i.protocol.replace(/:$/,"")),s.add("previewUrl",e.previewUrl).setter(function(e){var n,t,i,a=null,o=[];return(n=document.createElement("a")).href=e,/\/wp-(admin|includes|content)(\/|$)/.test(n.pathname)?null:(1<n.search.length&&(delete(t=ee.utils.parseQueryString(n.search.substr(1))).customize_changeset_uuid,delete t.customize_theme,delete t.customize_messenger_channel,delete t.customize_autosaved,_.isEmpty(t)?n.search="":n.search=Z.param(t)),o.push(n),s.scheme.get()+":"!==n.protocol&&((n=document.createElement("a")).href=o[0].href,n.protocol=s.scheme.get()+":",o.unshift(n)),i=document.createElement("a"),_.find(o,function(t){return!_.isUndefined(_.find(s.allowedUrls,function(e){if(i.href=e,n.protocol===i.protocol&&n.host===i.host&&0===n.pathname.indexOf(i.pathname.replace(/\/$/,"")))return a=t.href,!0}))}),a)}),s.bind("ready",s.ready),s.deferred.active.done(_.bind(s.keepPreviewAlive,s)),s.bind("synced",function(){s.send("active")}),s.previewUrl.bind(s.refresh),s.scroll=0,s.bind("scroll",function(e){s.scroll=e}),s.bind("url",function(e){var t,n=!1;s.scroll=0,t=function(){n=!0},s.previewUrl.bind(t),s.previewUrl.set(e),s.previewUrl.unbind(t),n||s.refresh()}),s.bind("documentTitle",function(e){ee.setDocumentTitle(e)})},ready:function(e){var t,n=this,i={};i.settings=ee.get(),i["settings-modified-while-loading"]=n.settingsModifiedWhileLoading,"resolved"===n.deferred.active.state()&&!n.loading||(i.scroll=n.scroll),i["edit-shortcut-visibility"]=ee.state("editShortcutVisibility").get(),n.send("sync",i),e.currentUrl&&(n.previewUrl.unbind(n.refresh),n.previewUrl.set(e.currentUrl),n.previewUrl.bind(n.refresh)),t={panel:e.activePanels,section:e.activeSections,control:e.activeControls},_(t).each(function(n,i){ee[i].each(function(e,t){_.isUndefined(ee.settings[i+"s"][t])&&_.isUndefined(n[t])||(n[t]?e.activate():e.deactivate())})}),e.settingValidities&&ee._handleSettingValidities({settingValidities:e.settingValidities,focusInvalidControl:!1})},keepPreviewAlive:function(){var e,t,n,i;i=function(){t=setTimeout(n,ee.settings.timeouts.keepAliveCheck)},e=function(){ee.state("previewerAlive").set(!0),clearTimeout(t),i()},n=function(){ee.state("previewerAlive").set(!1)},i(),this.bind("ready",e),this.bind("keep-alive",e)},query:function(){},abort:function(){this.loading&&(this.loading.destroy(),delete this.loading)},refresh:function(){var e,i=this;i.send("loading-initiated"),i.abort(),i.loading=new ee.PreviewFrame({url:i.url(),previewUrl:i.previewUrl(),query:i.query({excludeCustomizedSaved:!0})||{},container:i.container}),i.settingsModifiedWhileLoading={},e=function(e){i.settingsModifiedWhileLoading[e.id]=!0},ee.bind("change",e),i.loading.always(function(){ee.unbind("change",e)}),i.loading.done(function(e){var t,n=this;i.preview=n,i.targetWindow(n.targetWindow()),i.channel(n.channel()),t=function(){n.unbind("synced",t),i._previousPreview&&i._previousPreview.destroy(),i._previousPreview=i.preview,i.deferred.active.resolve(),delete i.loading},n.bind("synced",t),i.trigger("ready",e)}),i.loading.fail(function(e){i.send("loading-failed"),"logged out"===e&&(i.preview&&(i.preview.destroy(),delete i.preview),i.login().done(i.refresh)),"cheatin"===e&&i.cheatin()})},login:function(){var t,n,i,a=this;return this._login||(t=Z.Deferred(),this._login=t.promise(),n=new ee.Messenger({channel:"login",url:ee.settings.url.login}),i=Z("<iframe />",{src:ee.settings.url.login,title:ee.l10n.loginIframeTitle}).appendTo(this.container),n.targetWindow(i[0].contentWindow),n.bind("login",function(){var e=a.refreshNonces();e.always(function(){i.remove(),n.destroy(),delete a._login}),e.done(function(){t.resolve()}),e.fail(function(){a.cheatin(),t.reject()})})),this._login},cheatin:function(){Z(document.body).empty().addClass("cheatin").append("<h1>"+ee.l10n.notAllowedHeading+"</h1><p>"+ee.l10n.notAllowed+"</p>")},refreshNonces:function(){var e,t=Z.Deferred();return t.promise(),(e=wp.ajax.post("customize_refresh_nonces",{wp_customize:"on",customize_theme:ee.settings.theme.stylesheet})).done(function(e){ee.trigger("nonce-refresh",e),t.resolve()}),e.fail(function(){t.reject()}),t}}),ee.settingConstructor={},ee.controlConstructor={color:ee.ColorControl,media:ee.MediaControl,upload:ee.UploadControl,image:ee.ImageControl,cropped_image:ee.CroppedImageControl,site_icon:ee.SiteIconControl,header:ee.HeaderControl,background:ee.BackgroundControl,background_position:ee.BackgroundPositionControl,theme:ee.ThemeControl,date_time:ee.DateTimeControl,code_editor:ee.CodeEditorControl},ee.panelConstructor={themes:ee.ThemesPanel},ee.sectionConstructor={themes:ee.ThemesSection,outer:ee.OuterSection},ee._handleSettingValidities=function(e){var t,s=[],n=!1;_.each(e.settingValidities,function(t,e){var o=ee(e);o&&(_.isObject(t)&&_.each(t,function(e,t){var n,i,a=!1;n=new ee.Notification(t,_.extend({fromServer:!0},e)),(i=o.notifications(n.code))&&(a=n.type!==i.type||n.message!==i.message||!_.isEqual(n.data,i.data)),a&&o.notifications.remove(t),o.notifications.has(n.code)||o.notifications.add(n),s.push(o.id)}),o.notifications.each(function(e){!e.fromServer||"error"!==e.type||!0!==t&&t[e.code]||o.notifications.remove(e.code)}))}),e.focusInvalidControl&&(t=ee.findControlsForSettings(s),_(_.values(t)).find(function(e){return _(e).find(function(e){var t=e.section()&&ee.section.has(e.section())&&ee.section(e.section()).expanded();return t&&e.expanded&&(t=e.expanded()),t&&(e.focus(),n=!0),n})}),n||_.isEmpty(t)||_.values(t)[0][0].focus())},ee.findControlsForSettings=function(e){var n,i={};return _.each(_.unique(e),function(e){var t=ee(e);t&&(n=t.findControls())&&0<n.length&&(i[e]=n)}),i},ee.reflowPaneContents=_.bind(function(){var i,e,t,a=[],o=!1;document.activeElement&&(e=Z(document.activeElement)),ee.panel.each(function(e){if("themes"!==e.id){var t=e.sections(),n=_.pluck(t,"headContainer");a.push(e),i=e.contentContainer.is("ul")?e.contentContainer:e.contentContainer.find("ul:first"),ee.utils.areElementListsEqual(n,i.children("[id]"))||(_(t).each(function(e){i.append(e.headContainer)}),o=!0)}}),ee.section.each(function(e){var t=e.controls(),n=_.pluck(t,"container");e.panel()||a.push(e),i=e.contentContainer.is("ul")?e.contentContainer:e.contentContainer.find("ul:first"),ee.utils.areElementListsEqual(n,i.children("[id]"))||(_(t).each(function(e){i.append(e.container)}),o=!0)}),a.sort(ee.utils.prioritySort),t=_.pluck(a,"headContainer"),i=Z("#customize-theme-controls .customize-pane-parent"),ee.utils.areElementListsEqual(t,i.children())||(_(a).each(function(e){i.append(e.headContainer)}),o=!0),ee.panel.each(function(e){var t=e.active();e.active.callbacks.fireWith(e.active,[t,t])}),ee.section.each(function(e){var t=e.active();e.active.callbacks.fireWith(e.active,[t,t])}),o&&e&&e.focus(),ee.trigger("pane-contents-reflowed")},ee),ee.state=new ee.Values,_.each(["saved","saving","trashing","activated","processing","paneVisible","expandedPanel","expandedSection","changesetDate","selectedChangesetDate","changesetStatus","selectedChangesetStatus","remainingTimeToPublish","previewerAlive","editShortcutVisibility","changesetLocked","previewedDevice"],function(e){ee.state.create(e)}),Z(function(){if(ee.settings=window._wpCustomizeSettings,ee.l10n=window._wpCustomizeControlsL10n,ee.settings&&Z.support.postMessage&&(Z.support.cors||!ee.settings.isCrossDomain)){null===ee.PreviewFrame.prototype.sensitivity&&(ee.PreviewFrame.prototype.sensitivity=ee.settings.timeouts.previewFrameSensitivity),null===ee.Previewer.prototype.refreshBuffer&&(ee.Previewer.prototype.refreshBuffer=ee.settings.timeouts.windowRefresh);var m,t,n,e,i,a,o,s,r,c,l,d,u,p,h,f,g,v,w,b,C,y,x,k,z,S,T,E,D,P,N,I,U,A,F,V,H,L,M=Z(document.body),O=M.children(".wp-full-overlay"),j=Z("#customize-info .panel-title.site-title"),R=Z(".customize-controls-close"),B=Z("#save"),W=Z("#customize-save-button-wrapper"),q=Z("#publish-settings"),Q=Z("#customize-footer-actions");ee.bind("ready",function(){ee.section.add(new ee.OuterSection("publish_settings",{title:ee.l10n.publishSettings,priority:0,active:ee.settings.theme.active}))}),ee.section("publish_settings",function(t){var e,n,i,a,o,s,r,c,l,d,u;function p(){u=u||ee.utils.highlightButton(W,{delay:1e3,focusTarget:B})}function h(){u&&(u(),u=null)}n=new ee.Control("trash_changeset",{type:"button",section:t.id,priority:30,input_attrs:{class:"button-link button-link-delete",value:ee.l10n.discardChanges}}),ee.control.add(n),n.deferred.embedded.done(function(){n.container.find(".button-link").on("click",function(){confirm(ee.l10n.trashConfirm)&&wp.customize.previewer.trash()})}),ee.control.add(new ee.PreviewLinkControl("changeset_preview_link",{section:t.id,priority:100})),a=function(){return!!ee.state("activated").get()&&(!ee.state("trashing").get()&&"trash"!==ee.state("changesetStatus").get()&&(""!==ee.state("changesetStatus").get()||!ee.state("saved").get()))},t.active.validate=a,i=function(){t.active.set(a())},ee.state("activated").bind(i),ee.state("trashing").bind(i),ee.state("saved").bind(i),ee.state("changesetStatus").bind(i),i(),(e=function(){q.toggle(t.active.get()),B.toggleClass("has-next-sibling",t.active.get())})(),t.active.bind(e),ee.state("selectedChangesetStatus").bind(h),t.contentContainer.find(".customize-action").text(ee.l10n.updating),t.contentContainer.find(".customize-section-back").removeAttr("tabindex"),q.prop("disabled",!1),q.on("click",function(e){e.preventDefault(),t.expanded.set(!t.expanded.get())}),t.expanded.bind(function(e){var t;q.attr("aria-expanded",String(e)),q.toggleClass("active",e),e?h():(""!==(t=ee.state("changesetStatus").get())&&"auto-draft"!==t||(t="publish"),ee.state("selectedChangesetStatus").get()!==t?p():"future"===ee.state("selectedChangesetStatus").get()&&ee.state("selectedChangesetDate").get()!==ee.state("changesetDate").get()&&p())}),o=new ee.Control("changeset_status",{priority:10,type:"radio",section:"publish_settings",setting:ee.state("selectedChangesetStatus"),templateId:"customize-selected-changeset-status-control",label:ee.l10n.action,choices:ee.settings.changeset.statusChoices}),ee.control.add(o),(s=new ee.DateTimeControl("changeset_scheduled_date",{priority:20,section:"publish_settings",setting:ee.state("selectedChangesetDate"),minYear:(new Date).getFullYear(),allowPastDate:!1,includeTime:!0,twelveHourFormat:/a/i.test(ee.settings.timeFormat),description:ee.l10n.scheduleDescription})).notifications.alt=!0,ee.control.add(s),c=function(){ee.state("selectedChangesetStatus").set("publish"),ee.previewer.save()},d=function(){var e="future"===ee.state("changesetStatus").get()&&"future"===ee.state("selectedChangesetStatus").get()&&ee.state("changesetDate").get()&&ee.state("selectedChangesetDate").get()===ee.state("changesetDate").get()&&0<=ee.utils.getRemainingTime(ee.state("changesetDate").get());e&&!l?l=setInterval(function(){var e=ee.utils.getRemainingTime(ee.state("changesetDate").get());ee.state("remainingTimeToPublish").set(e),e<=0&&(clearInterval(l),l=0,c())},1e3):!e&&l&&(clearInterval(l),l=0)},ee.state("changesetDate").bind(d),ee.state("selectedChangesetDate").bind(d),ee.state("changesetStatus").bind(d),ee.state("selectedChangesetStatus").bind(d),d(),s.active.validate=function(){return"future"===ee.state("selectedChangesetStatus").get()},(r=function(e){s.active.set("future"===e)})(ee.state("selectedChangesetStatus").get()),ee.state("selectedChangesetStatus").bind(r),ee.state("saving").bind(function(e){e&&"future"===ee.state("selectedChangesetStatus").get()&&s.toggleFutureDateNotification(!s.isFutureDate())})}),Z("#customize-controls").on("keydown",function(e){var t=13===e.which,n=Z(e.target);t&&(n.is("input:not([type=button])")||n.is("select"))&&e.preventDefault()}),Z(".customize-info").find("> .accordion-section-title .customize-help-toggle").on("click",function(){var e=Z(this).closest(".accordion-section"),t=e.find(".customize-panel-description:first");e.hasClass("cannot-expand")||(e.hasClass("open")?(e.toggleClass("open"),t.slideUp(ee.Panel.prototype.defaultExpandedArguments.duration,function(){t.trigger("toggled")}),Z(this).attr("aria-expanded",!1)):(t.slideDown(ee.Panel.prototype.defaultExpandedArguments.duration,function(){t.trigger("toggled")}),e.toggleClass("open"),Z(this).attr("aria-expanded",!0)))}),ee.previewer=new ee.Previewer({container:"#customize-preview",form:"#customize-controls",previewUrl:ee.settings.url.preview,allowedUrls:ee.settings.url.allowed},{nonce:ee.settings.nonce,query:function(e){var t={wp_customize:"on",customize_theme:ee.settings.theme.stylesheet,nonce:this.nonce.preview,customize_changeset_uuid:ee.settings.changeset.uuid};return!ee.settings.changeset.autosaved&&ee.state("saved").get()||(t.customize_autosaved="on"),t.customized=JSON.stringify(ee.dirtyValues({unsaved:e&&e.excludeCustomizedSaved})),t},save:function(o){var e,t,s=this,r=Z.Deferred(),c=ee.state("selectedChangesetStatus").get(),l=ee.state("selectedChangesetDate").get(),n=ee.state("processing"),d={},u=[],p=[],h=[];function f(e){d[e.id]=!0}return o&&o.status&&(c=o.status),ee.state("saving").get()&&(r.reject("already_saving"),r.promise()),ee.state("saving").set(!0),t=function(){var e,t,n={},i=ee._latestRevision,a="client_side_error";if(ee.bind("change",f),ee.notifications.remove(a),ee.each(function(t){t.notifications.each(function(e){"error"!==e.type||e.fromServer||(u.push(t.id),n[t.id]||(n[t.id]={}),n[t.id][e.code]=e)})}),ee.control.each(function(t){t.setting&&(t.setting.id||!t.active.get())||t.notifications.each(function(e){"error"===e.type&&h.push([t])})}),p=_.union(h,_.values(ee.findControlsForSettings(u))),!_.isEmpty(p))return p[0][0].focus(),ee.unbind("change",f),u.length&&ee.notifications.add(new ee.Notification(a,{message:(1===u.length?ee.l10n.saveBlockedError.singular:ee.l10n.saveBlockedError.plural).replace(/%s/g,String(u.length)),type:"error",dismissible:!0,saveFailure:!0})),r.rejectWith(s,[{setting_invalidities:n}]),ee.state("saving").set(!1),r.promise();t=Z.extend(s.query({excludeCustomizedSaved:!1}),{nonce:s.nonce.save,customize_changeset_status:c}),o&&o.date?t.customize_changeset_date=o.date:"future"===c&&l&&(t.customize_changeset_date=l),o&&o.title&&(t.customize_changeset_title=o.title),ee.trigger("save-request-params",t),e=wp.ajax.post("customize_save",t),ee.state("processing").set(ee.state("processing").get()+1),ee.trigger("save",e),e.always(function(){ee.state("processing").set(ee.state("processing").get()-1),ee.state("saving").set(!1),ee.unbind("change",f)}),ee.notifications.each(function(e){e.saveFailure&&ee.notifications.remove(e.code)}),e.fail(function(e){var t,n;n={type:"error",dismissible:!0,fromServer:!0,saveFailure:!0},"0"===e?e="not_logged_in":"-1"===e&&(e="invalid_nonce"),"invalid_nonce"===e?s.cheatin():"not_logged_in"===e?(s.preview.iframe.hide(),s.login().done(function(){s.save(),s.preview.iframe.show()})):e.code?"not_future_date"===e.code&&ee.section.has("publish_settings")&&ee.section("publish_settings").active.get()&&ee.control.has("changeset_scheduled_date")?ee.control("changeset_scheduled_date").toggleFutureDateNotification(!0).focus():"changeset_locked"!==e.code&&(t=new ee.Notification(e.code,_.extend(n,{message:e.message}))):t=new ee.Notification("unknown_error",_.extend(n,{message:ee.l10n.unknownRequestFail})),t&&ee.notifications.add(t),e.setting_validities&&ee._handleSettingValidities({settingValidities:e.setting_validities,focusInvalidControl:!0}),r.rejectWith(s,[e]),ee.trigger("error",e),"changeset_already_published"===e.code&&e.next_changeset_uuid&&(ee.settings.changeset.uuid=e.next_changeset_uuid,ee.state("changesetStatus").set(""),ee.settings.changeset.branching&&m.send("changeset-uuid",ee.settings.changeset.uuid),ee.previewer.send("changeset-uuid",ee.settings.changeset.uuid))}),e.done(function(e){s.send("saved",e),ee.state("changesetStatus").set(e.changeset_status),e.changeset_date&&ee.state("changesetDate").set(e.changeset_date),"publish"===e.changeset_status&&(ee.each(function(e){e._dirty&&(_.isUndefined(ee._latestSettingRevisions[e.id])||ee._latestSettingRevisions[e.id]<=i)&&(e._dirty=!1)}),ee.state("changesetStatus").set(""),ee.settings.changeset.uuid=e.next_changeset_uuid,ee.settings.changeset.branching&&m.send("changeset-uuid",ee.settings.changeset.uuid)),ee._lastSavedRevision=Math.max(i,ee._lastSavedRevision),e.setting_validities&&ee._handleSettingValidities({settingValidities:e.setting_validities,focusInvalidControl:!0}),r.resolveWith(s,[e]),ee.trigger("saved",e),_.isEmpty(d)||ee.state("saved").set(!1)})},0===n()?t():(e=function(){0===n()&&(ee.state.unbind("change",e),t())},ee.state.bind("change",e)),r.promise()},trash:function(){var e,n,i;ee.state("trashing").set(!0),ee.state("processing").set(ee.state("processing").get()+1),e=wp.ajax.post("customize_trash",{customize_changeset_uuid:ee.settings.changeset.uuid,nonce:ee.settings.nonce.trash}),ee.notifications.add(new ee.OverlayNotification("changeset_trashing",{type:"info",message:ee.l10n.revertingChanges,loading:!0})),n=function(){var e,t=document.createElement("a");ee.state("changesetStatus").set("trash"),ee.each(function(e){e._dirty=!1}),ee.state("saved").set(!0),t.href=location.href,delete(e=ee.utils.parseQueryString(t.search.substr(1))).changeset_uuid,e.return=ee.settings.url.return,t.search=Z.param(e),location.replace(t.href)},i=function(e,t){var n=e||"unknown_error";ee.state("processing").set(ee.state("processing").get()-1),ee.state("trashing").set(!1),ee.notifications.remove("changeset_trashing"),ee.notifications.add(new ee.Notification(n,{message:t||ee.l10n.unknownError,dismissible:!0,type:"error"}))},e.done(function(e){n(e.message)}),e.fail(function(e){var t=e.code||"trashing_failed";e.success||"non_existent_changeset"===t||"changeset_already_trashed"===t?n(e.message):i(t,e.message)})},getFrontendPreviewUrl:function(){var e,t;return(t=document.createElement("a")).href=this.previewUrl.get(),e=ee.utils.parseQueryString(t.search.substr(1)),ee.state("changesetStatus").get()&&"publish"!==ee.state("changesetStatus").get()&&(e.customize_changeset_uuid=ee.settings.changeset.uuid),ee.state("activated").get()||(e.customize_theme=ee.settings.theme.stylesheet),t.search=Z.param(e),t.href}}),Z.ajaxPrefilter(function(e){/wp_customize=on/.test(e.data)&&(e.data+="&"+Z.param({customize_preview_nonce:ee.settings.nonce.preview}))}),ee.previewer.bind("nonce",function(e){Z.extend(this.nonce,e)}),ee.bind("nonce-refresh",function(e){Z.extend(ee.settings.nonce,e),Z.extend(ee.previewer.nonce,e),ee.previewer.send("nonce-refresh",e)}),Z.each(ee.settings.settings,function(e,t){var n=ee.settingConstructor[t.type]||ee.Setting;ee.add(new n(e,t.value,{transport:t.transport,previewer:ee.previewer,dirty:!!t.dirty}))}),Z.each(ee.settings.panels,function(e,t){var n,i=ee.panelConstructor[t.type]||ee.Panel;n=_.extend({params:t},t),ee.panel.add(new i(e,n))}),Z.each(ee.settings.sections,function(e,t){var n,i=ee.sectionConstructor[t.type]||ee.Section;n=_.extend({params:t},t),ee.section.add(new i(e,n))}),Z.each(ee.settings.controls,function(e,t){var n,i=ee.controlConstructor[t.type]||ee.Control;n=_.extend({params:t},t),ee.control.add(new i(e,n))}),_.each(["panel","section","control"],function(e){var t=ee.settings.autofocus[e];t&&ee[e](t,function(e){e.deferred.embedded.done(function(){ee.previewer.deferred.active.done(function(){e.focus()})})})}),ee.bind("ready",ee.reflowPaneContents),Z([ee.panel,ee.section,ee.control]).each(function(e,t){var n=_.debounce(ee.reflowPaneContents,ee.settings.timeouts.reflowPaneContents);t.bind("add",n),t.bind("change",n),t.bind("remove",n)}),ee.bind("ready",function(){var e,t,n;ee.notifications.container=Z("#customize-notifications-area"),ee.notifications.bind("change",_.debounce(function(){ee.notifications.render()})),e=Z(".wp-full-overlay-sidebar-content"),ee.notifications.bind("rendered",function(){e.css("top",""),0!==ee.notifications.count()&&(t=ee.notifications.container.outerHeight()+1,n=parseInt(e.css("top"),10),e.css("top",n+t+"px")),ee.notifications.trigger("sidebarTopUpdated")}),ee.notifications.render()}),t=ee.state,i=t.instance("saved"),a=t.instance("saving"),o=t.instance("trashing"),s=t.instance("activated"),r=t.instance("processing"),c=t.instance("paneVisible"),l=t.instance("expandedPanel"),d=t.instance("expandedSection"),u=t.instance("changesetStatus"),p=t.instance("selectedChangesetStatus"),h=t.instance("changesetDate"),f=t.instance("selectedChangesetDate"),g=t.instance("previewerAlive"),v=t.instance("editShortcutVisibility"),w=t.instance("changesetLocked"),t.bind("change",function(){var e;s()?""===u.get()&&i()?(ee.settings.changeset.currentUserCanPublish?B.val(ee.l10n.published):B.val(ee.l10n.saved),R.find(".screen-reader-text").text(ee.l10n.close)):("draft"===p()?i()&&p()===u()?B.val(ee.l10n.draftSaved):B.val(ee.l10n.saveDraft):"future"===p()?i()&&p()===u()?h.get()!==f.get()?B.val(ee.l10n.schedule):B.val(ee.l10n.scheduled):B.val(ee.l10n.schedule):ee.settings.changeset.currentUserCanPublish&&B.val(ee.l10n.publish),R.find(".screen-reader-text").text(ee.l10n.cancel)):(B.val(ee.l10n.activate),R.find(".screen-reader-text").text(ee.l10n.cancel)),e=!a()&&!o()&&!w()&&(!s()||!i()||u()!==p()&&""!==u()||"future"===p()&&h.get()!==f.get()),B.prop("disabled",!e)}),p.validate=function(e){return""===e||"auto-draft"===e?null:e},e=ee.settings.changeset.currentUserCanPublish?"publish":"draft",u(ee.settings.changeset.status),w(Boolean(ee.settings.changeset.lockUser)),h(ee.settings.changeset.publishDate),f(ee.settings.changeset.publishDate),p(""===ee.settings.changeset.status||"auto-draft"===ee.settings.changeset.status?e:ee.settings.changeset.status),p.link(u),i(!0),""===u()&&ee.each(function(e){e._dirty&&i(!1)}),a(!1),s(ee.settings.theme.active),r(0),c(!0),l(!1),d(!1),g(!0),v("visible"),ee.bind("change",function(){t("saved").get()&&t("saved").set(!1)}),ee.settings.changeset.branching&&i.bind(function(e){e||n(!0)}),a.bind(function(e){M.toggleClass("saving",e)}),o.bind(function(e){M.toggleClass("trashing",e)}),ee.bind("saved",function(e){t("saved").set(!0),"publish"===e.changeset_status&&t("activated").set(!0)}),s.bind(function(e){e&&ee.trigger("activated")}),n=function(e){var t,n;if(history.replaceState){if((t=document.createElement("a")).href=location.href,n=ee.utils.parseQueryString(t.search.substr(1)),e){if(n.changeset_uuid===ee.settings.changeset.uuid)return;n.changeset_uuid=ee.settings.changeset.uuid}else{if(!n.changeset_uuid)return;delete n.changeset_uuid}t.search=Z.param(n),history.replaceState({},document.title,t.href)}},ee.settings.changeset.branching&&u.bind(function(e){n(""!==e&&"publish"!==e&&"trash"!==e)}),b=ee.OverlayNotification.extend({templateId:"customize-changeset-locked-notification",lockUser:null,initialize:function(e,t){var n,i;n=e||"changeset_locked",(i=_.extend({type:"warning",containerClasses:"",lockUser:{}},t)).containerClasses+=" notification-changeset-locked",ee.OverlayNotification.prototype.initialize.call(this,n,i)},render:function(){var n,e,i,a,t=this;return e=_.extend({allowOverride:!1,returnUrl:ee.settings.url.return,previewUrl:ee.previewer.previewUrl.get(),frontendPreviewUrl:ee.previewer.getFrontendPreviewUrl()},this),n=ee.OverlayNotification.prototype.render.call(e),ee.requestChangesetUpdate({},{autosave:!0}).fail(function(e){e.autosaved||n.find(".notice-error").prop("hidden",!1).text(e.message||ee.l10n.unknownRequestFail)}),(i=n.find(".customize-notice-take-over-button")).on("click",function(e){e.preventDefault(),a||(i.addClass("disabled"),(a=wp.ajax.post("customize_override_changeset_lock",{wp_customize:"on",customize_theme:ee.settings.theme.stylesheet,customize_changeset_uuid:ee.settings.changeset.uuid,nonce:ee.settings.nonce.override_lock})).done(function(){ee.notifications.remove(t.code),ee.state("changesetLocked").set(!1)}),a.fail(function(e){var t=e.message||ee.l10n.unknownRequestFail;n.find(".notice-error").prop("hidden",!1).text(t),a.always(function(){i.removeClass("disabled")})}),a.always(function(){a=null}))}),n}}),ee.settings.changeset.lockUser&&K({allowOverride:!0}),Z(document).on("heartbeat-send.update_lock_notice",function(e,t){t.check_changeset_lock=!0,t.changeset_uuid=ee.settings.changeset.uuid}),Z(document).on("heartbeat-tick.update_lock_notice",function(e,t){var n,i="changeset_locked";t.customize_changeset_lock_user&&((n=ee.notifications(i))&&n.lockUser.id!==ee.settings.changeset.lockUser.id&&ee.notifications.remove(i),K({lockUser:t.customize_changeset_lock_user}))}),ee.bind("error",function(e){"changeset_locked"===e.code&&e.lock_user&&K({lockUser:e.lock_user})}),E=!(T=[]),ee.settings.changeset.autosaved&&(ee.state("saved").set(!1),T.push("customize_autosaved")),ee.settings.changeset.branching||ee.settings.changeset.status&&"auto-draft"!==ee.settings.changeset.status||T.push("changeset_uuid"),0<T.length&&(C=T,x=document.createElement("a"),k=0,x.href=location.href,y=ee.utils.parseQueryString(x.search.substr(1)),_.each(C,function(e){void 0!==y[e]&&(k+=1,delete y[e])}),0!==k&&(x.search=Z.param(y),history.replaceState({},document.title,x.href))),(ee.settings.changeset.latestAutoDraftUuid||ee.settings.changeset.hasAutosaveRevision)&&(S="autosave_available",ee.notifications.add(new ee.Notification(S,{message:ee.l10n.autosaveNotice,type:"warning",dismissible:!0,render:function(){var e,t=ee.Notification.prototype.render.call(this);return(e=t.find("a")).prop("href",$()),e.on("click",function(e){e.preventDefault(),location.replace($())}),t.find(".notice-dismiss").on("click",J),t}})),z=function(){J(),ee.notifications.remove(S),ee.unbind("change",z),ee.state("changesetStatus").unbind(z)},ee.bind("change",z),ee.state("changesetStatus").bind(z)),ee.previewer.previewUrl()?ee.previewer.refresh():ee.previewer.previewUrl(ee.settings.url.home),B.click(function(e){ee.previewer.save(),e.preventDefault()}).keydown(function(e){9!==e.which&&(13===e.which&&ee.previewer.save(),e.preventDefault())}),R.keydown(function(e){9!==e.which&&(13===e.which&&this.click(),e.preventDefault())}),Z(".collapse-sidebar").on("click",function(){ee.state("paneVisible").set(!ee.state("paneVisible").get())}),ee.state("paneVisible").bind(function(e){O.toggleClass("preview-only",!e),O.toggleClass("expanded",e),O.toggleClass("collapsed",!e),e?Z(".collapse-sidebar").attr({"aria-expanded":"true","aria-label":ee.l10n.collapseSidebar}):Z(".collapse-sidebar").attr({"aria-expanded":"false","aria-label":ee.l10n.expandSidebar})}),M.on("keydown",function(e){var t,n=[],i=[],a=[];if(27===e.which&&(Z(e.target).is("body")||Z.contains(Z("#customize-controls")[0],e.target))&&(ee.control.each(function(e){e.expanded&&e.expanded()&&_.isFunction(e.collapse)&&n.push(e)}),ee.section.each(function(e){e.expanded()&&i.push(e)}),ee.panel.each(function(e){e.expanded()&&a.push(e)}),0<n.length&&0===i.length&&(n.length=0),t=n[0]||i[0]||a[0])){if("themes"===t.params.type)return void(M.hasClass("modal-open")?t.closeDetails():ee.panel.has("themes")&&ee.panel("themes").collapse());t.collapse(),e.preventDefault()}}),Z(".customize-controls-preview-toggle").on("click",function(){ee.state("paneVisible").set(!ee.state("paneVisible").get())}),V=Z(".wp-full-overlay-sidebar-content"),D=function(e){var t,n=e,i=ee.state("expandedSection").get(),a=ee.state("expandedPanel").get();if(A&&A.element&&(N(A.element),A.element.find(".description").off("toggled",P)),!n)if(!i&&a&&a.contentContainer)n=a;else{if(a||!i||!i.contentContainer)return void(A=!1);n=i}(t=n.contentContainer.find(".customize-section-title, .panel-meta").first()).length?((A={instance:n,element:t,parent:t.closest(".customize-pane-child"),height:t.outerHeight()}).element.find(".description").on("toggled",P),i&&I(A.element,A.parent)):A=!1},ee.state("expandedSection").bind(D),ee.state("expandedPanel").bind(D),V.on("scroll",_.throttle(function(){if(A){var e,t=V.scrollTop();e=F?t===F?0:F<t?1:-1:1,F=t,0!==e&&U(A,t,e)}},8)),ee.notifications.bind("sidebarTopUpdated",function(){A&&A.element.hasClass("is-sticky")&&A.element.css("top",V.css("top"))}),N=function(e){e.hasClass("is-sticky")&&e.removeClass("is-sticky").addClass("maybe-sticky is-in-view").css("top",V.scrollTop()+"px")},I=function(e,t){e.hasClass("is-in-view")&&(e.removeClass("maybe-sticky is-in-view").css({width:"",top:""}),t.css("padding-top",""))},P=function(){A.height=A.element.outerHeight()},U=function(e,t,n){var i=e.element,a=e.parent,o=e.height,s=parseInt(i.css("top"),10),r=i.hasClass("maybe-sticky"),c=i.hasClass("is-sticky"),l=i.hasClass("is-in-view");if(-1!==n)return c&&(s=t,i.removeClass("is-sticky").css({top:s+"px",width:""})),void(l&&s+o<t&&(i.removeClass("is-in-view"),a.css("padding-top","")));if(!r&&o<=t)r=!0,i.addClass("maybe-sticky");else if(0===t)return i.removeClass("maybe-sticky is-in-view is-sticky").css({top:"",width:""}),void a.css("padding-top","");l&&!c?t<=s&&i.addClass("is-sticky").css({top:V.css("top"),width:a.outerWidth()+"px"}):r&&!l&&(i.addClass("is-in-view").css("top",t-o+"px"),a.css("padding-top",o+"px"))},ee.previewedDevice=ee.state("previewedDevice"),ee.bind("ready",function(){_.find(ee.settings.previewableDevices,function(e,t){if(!0===e.default)return ee.previewedDevice.set(t),!0})}),Q.find(".devices button").on("click",function(e){ee.previewedDevice.set(Z(e.currentTarget).data("device"))}),ee.previewedDevice.bind(function(e){var t=Z(".wp-full-overlay"),n="";Q.find(".devices button").removeClass("active").attr("aria-pressed",!1),Q.find(".devices .preview-"+e).addClass("active").attr("aria-pressed",!0),Z.each(ee.settings.previewableDevices,function(e){n+=" preview-"+e}),t.removeClass(n).addClass("preview-"+e)}),j.length&&ee("blogname",function(e){function t(){j.text(Z.trim(e())||ee.l10n.untitledBlogName)}e.bind(t),t()}),m=new ee.Messenger({url:ee.settings.url.parent,channel:"loader"}),H=!1,m.bind("back",function(){H=!0}),ee.bind("change",G),ee.state("selectedChangesetStatus").bind(G),ee.state("selectedChangesetDate").bind(G),m.bind("confirm-close",function(){X().done(function(){m.send("confirmed-close",!0)}).fail(function(){m.send("confirmed-close",!1)})}),R.on("click.customize-controls-close",function(e){e.preventDefault(),H?m.send("close"):X().done(function(){Z(window).off("beforeunload.customize-confirm"),window.location.href=R.prop("href")})}),Z.each(["saved","change"],function(e,t){ee.bind(t,function(){m.send(t)})}),ee.bind("title",function(e){m.send("title",e)}),ee.settings.changeset.branching&&m.send("changeset-uuid",ee.settings.changeset.uuid),m.send("ready"),Z.each({background_image:{controls:["background_preset","background_position","background_size","background_repeat","background_attachment"],callback:function(e){return!!e}},show_on_front:{controls:["page_on_front","page_for_posts"],callback:function(e){return"page"===e}},header_textcolor:{controls:["header_textcolor"],callback:function(e){return"blank"!==e}}},function(e,i){ee(e,function(n){Z.each(i.controls,function(e,t){ee.control(t,function(t){function e(e){t.container.toggle(i.callback(e))}e(n.get()),n.bind(e)})})})}),ee.control("background_preset",function(e){var a,t,o,n,i,s;a={default:[!1,!1,!1,!1],fill:[!0,!1,!1,!1],fit:[!0,!1,!0,!1],repeat:[!0,!1,!1,!0],custom:[!0,!0,!0,!0]},t=[_wpCustomizeBackground.defaults["default-position-x"],_wpCustomizeBackground.defaults["default-position-y"],_wpCustomizeBackground.defaults["default-size"],_wpCustomizeBackground.defaults["default-repeat"],_wpCustomizeBackground.defaults["default-attachment"]],o={default:t,fill:["left","top","cover","no-repeat","fixed"],fit:["left","top","contain","no-repeat","fixed"],repeat:["left","top","auto","repeat","scroll"]},n=function(i){_.each(["background_position","background_size","background_repeat","background_attachment"],function(e,t){var n=ee.control(e);n&&n.container.toggle(a[i][t])})},i=function(i){_.each(["background_position_x","background_position_y","background_size","background_repeat","background_attachment"],function(e,t){var n=ee(e);n&&n.set(o[i][t])})},s=e.setting.get(),n(s),e.setting.bind("change",function(e){n(e),"custom"!==e&&i(e)})}),ee.control("background_repeat",function(t){t.elements[0].unsync(ee("background_repeat")),t.element=new ee.Element(t.container.find("input")),t.element.set("no-repeat"!==t.setting()),t.element.bind(function(e){t.setting.set(e?"repeat":"no-repeat")}),t.setting.bind(function(e){t.element.set("no-repeat"!==e)})}),ee.control("background_attachment",function(t){t.elements[0].unsync(ee("background_attachment")),t.element=new ee.Element(t.container.find("input")),t.element.set("fixed"!==t.setting()),t.element.bind(function(e){t.setting.set(e?"scroll":"fixed")}),t.setting.bind(function(e){t.element.set("fixed"!==e)})}),ee.control("display_header_text",function(t){var n="";t.elements[0].unsync(ee("header_textcolor")),t.element=new ee.Element(t.container.find("input")),t.element.set("blank"!==t.setting()),t.element.bind(function(e){e||(n=ee("header_textcolor").get()),t.setting.set(e?n:"blank")}),t.setting.bind(function(e){t.element.set("blank"!==e)})}),ee("show_on_front","page_on_front","page_for_posts",function(i,a,o){function e(){var e,t,n="show_on_front_page_collision";e=parseInt(a(),10),t=parseInt(o(),10),"page"===i()&&(this===a&&0<e&&ee.previewer.previewUrl.set(ee.settings.url.home),this===o&&0<t&&ee.previewer.previewUrl.set(ee.settings.url.home+"?page_id="+t)),"page"===i()&&e&&t&&e===t?i.notifications.add(new ee.Notification(n,{type:"error",message:ee.l10n.pageOnFrontError})):i.notifications.remove(n)}i.bind(e),a.bind(e),o.bind(e),e.call(i,i()),ee.control("show_on_front",function(e){e.deferred.embedded.done(function(){e.container.append(e.getNotificationsContainerElement())})})}),L=Z.Deferred(),ee.section("custom_css",function(t){t.deferred.embedded.done(function(){t.expanded()?L.resolve(t):t.expanded.bind(function(e){e&&L.resolve(t)})})}),L.done(function(e){var t=ee.control("custom_css");t.container.find(".customize-control-title:first").addClass("screen-reader-text"),e.container.find(".section-description-buttons .section-description-close").on("click",function(){e.container.find(".section-meta .customize-section-description:first").removeClass("open").slideUp(),e.container.find(".customize-help-toggle").attr("aria-expanded","false").focus()}),t&&!t.setting.get()&&(e.container.find(".section-meta .customize-section-description:first").addClass("open").show().trigger("toggled"),e.container.find(".customize-help-toggle").attr("aria-expanded","true"))}),ee.control("header_video",function(n){n.deferred.embedded.done(function(){function e(){var e=ee.section(n.section()),t="video_header_not_available";e&&(n.active.get()?e.notifications.remove(t):e.notifications.add(new ee.Notification(t,{type:"info",message:ee.l10n.videoHeaderNotice})))}e(),n.active.bind(e)})}),ee.previewer.bind("selective-refresh-setting-validities",function(e){ee._handleSettingValidities({settingValidities:e,focusInvalidControl:!1})}),ee.previewer.bind("focus-control-for-setting",function(n){var i=[];ee.control.each(function(e){var t=_.pluck(e.settings,"id");-1!==_.indexOf(t,n)&&i.push(e)}),i.length&&(i.sort(function(e,t){return e.priority()-t.priority()}),i[0].focus())}),ee.previewer.bind("refresh",function(){ee.previewer.refresh()}),ee.state("paneVisible").bind(function(e){var t;t=window.matchMedia?window.matchMedia("screen and ( max-width: 640px )").matches:Z(window).width()<=640,ee.state("editShortcutVisibility").set(e||t?"visible":"hidden")}),window.matchMedia&&window.matchMedia("screen and ( max-width: 640px )").addListener(function(){var e=ee.state("paneVisible");e.callbacks.fireWith(e,[e.get(),e.get()])}),ee.previewer.bind("edit-shortcut-visibility",function(e){ee.state("editShortcutVisibility").set(e)}),ee.state("editShortcutVisibility").bind(function(e){ee.previewer.send("edit-shortcut-visibility",e)}),ee.bind("change",function e(){var t,n,i,a=!1;function o(e){e||ee.settings.changeset.autosaved||(ee.settings.changeset.autosaved=!0,ee.previewer.send("autosaving"))}ee.unbind("change",e),ee.state("saved").bind(o),o(ee.state("saved").get()),n=function(){a||(a=!0,ee.requestChangesetUpdate({},{autosave:!0}).always(function(){a=!1})),i()},(i=function(){clearTimeout(t),t=setTimeout(function(){n()},ee.settings.timeouts.changesetAutoSave)})(),Z(document).on("visibilitychange.wp-customize-changeset-update",function(){document.hidden&&n()}),Z(window).on("beforeunload.wp-customize-changeset-update",function(){n()})}),Z(document).one("tinymce-editor-setup",function(){window.tinymce.ui.FloatPanel&&(!window.tinymce.ui.FloatPanel.zIndex||window.tinymce.ui.FloatPanel.zIndex<500001)&&(window.tinymce.ui.FloatPanel.zIndex=500001)}),M.addClass("ready"),ee.trigger("ready")}function K(e){e&&e.lockUser&&(ee.settings.changeset.lockUser=e.lockUser),ee.state("changesetLocked").set(!0),ee.notifications.add(new b("changeset_locked",{lockUser:ee.settings.changeset.lockUser,allowOverride:Boolean(e&&e.allowOverride)}))}function $(){var e,t;return(e=document.createElement("a")).href=location.href,t=ee.utils.parseQueryString(e.search.substr(1)),ee.settings.changeset.latestAutoDraftUuid?t.changeset_uuid=ee.settings.changeset.latestAutoDraftUuid:t.customize_autosaved="on",t.return=ee.settings.url.return,e.search=Z.param(t),e.href}function J(){E||(wp.ajax.post("customize_dismiss_autosave_or_lock",{wp_customize:"on",customize_theme:ee.settings.theme.stylesheet,customize_changeset_uuid:ee.settings.changeset.uuid,nonce:ee.settings.nonce.dismiss_autosave_or_lock,dismiss_autosave:!0}),E=!0)}function Y(){var e;return ee.state("activated").get()?(""!==(e=ee.state("changesetStatus").get())&&"auto-draft"!==e||(e="publish"),ee.state("selectedChangesetStatus").get()===e&&(("future"!==ee.state("selectedChangesetStatus").get()||ee.state("selectedChangesetDate").get()===ee.state("changesetDate").get())&&(ee.state("saved").get()&&"auto-draft"!==ee.state("changesetStatus").get()))):0===ee._latestRevision}function G(){ee.unbind("change",G),ee.state("selectedChangesetStatus").unbind(G),ee.state("selectedChangesetDate").unbind(G),Z(window).on("beforeunload.customize-confirm",function(){if(!Y()&&!ee.state("changesetLocked").get())return setTimeout(function(){O.removeClass("customize-loading")},1),ee.l10n.saveAlert})}function X(){var e=Z.Deferred(),t=!1,n=!1;return Y()?n=!0:confirm(ee.l10n.saveAlert)?(n=!0,ee.each(function(e){e._dirty=!1}),Z(document).off("visibilitychange.wp-customize-changeset-update"),Z(window).off("beforeunload.wp-customize-changeset-update"),R.css("cursor","progress"),""!==ee.state("changesetStatus").get()&&(t=!0)):e.reject(),(n||t)&&wp.ajax.send("customize_dismiss_autosave_or_lock",{timeout:500,data:{wp_customize:"on",customize_theme:ee.settings.theme.stylesheet,customize_changeset_uuid:ee.settings.changeset.uuid,nonce:ee.settings.nonce.dismiss_autosave_or_lock,dismiss_autosave:t,dismiss_lock:n}}).always(function(){e.resolve()}),e.promise()}})}(wp,jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/customize-nav-menus.js b/srcs/wordpress/wp-admin/js/customize-nav-menus.js deleted file mode 100644 index e92104a..0000000 --- a/srcs/wordpress/wp-admin/js/customize-nav-menus.js +++ /dev/null @@ -1,3463 +0,0 @@ -/** - * @output wp-admin/js/customize-nav-menus.js - */ - -/* global _wpCustomizeNavMenusSettings, wpNavMenu, console */ -( function( api, wp, $ ) { - 'use strict'; - - /** - * Set up wpNavMenu for drag and drop. - */ - wpNavMenu.originalInit = wpNavMenu.init; - wpNavMenu.options.menuItemDepthPerLevel = 20; - wpNavMenu.options.sortableItems = '> .customize-control-nav_menu_item'; - wpNavMenu.options.targetTolerance = 10; - wpNavMenu.init = function() { - this.jQueryExtensions(); - }; - - /** - * @namespace wp.customize.Menus - */ - api.Menus = api.Menus || {}; - - // Link settings. - api.Menus.data = { - itemTypes: [], - l10n: {}, - settingTransport: 'refresh', - phpIntMax: 0, - defaultSettingValues: { - nav_menu: {}, - nav_menu_item: {} - }, - locationSlugMappedToName: {} - }; - if ( 'undefined' !== typeof _wpCustomizeNavMenusSettings ) { - $.extend( api.Menus.data, _wpCustomizeNavMenusSettings ); - } - - /** - * Newly-created Nav Menus and Nav Menu Items have negative integer IDs which - * serve as placeholders until Save & Publish happens. - * - * @alias wp.customize.Menus.generatePlaceholderAutoIncrementId - * - * @return {number} - */ - api.Menus.generatePlaceholderAutoIncrementId = function() { - return -Math.ceil( api.Menus.data.phpIntMax * Math.random() ); - }; - - /** - * wp.customize.Menus.AvailableItemModel - * - * A single available menu item model. See PHP's WP_Customize_Nav_Menu_Item_Setting class. - * - * @class wp.customize.Menus.AvailableItemModel - * @augments Backbone.Model - */ - api.Menus.AvailableItemModel = Backbone.Model.extend( $.extend( - { - id: null // This is only used by Backbone. - }, - api.Menus.data.defaultSettingValues.nav_menu_item - ) ); - - /** - * wp.customize.Menus.AvailableItemCollection - * - * Collection for available menu item models. - * - * @class wp.customize.Menus.AvailableItemCollection - * @augments Backbone.Collection - */ - api.Menus.AvailableItemCollection = Backbone.Collection.extend(/** @lends wp.customize.Menus.AvailableItemCollection.prototype */{ - model: api.Menus.AvailableItemModel, - - sort_key: 'order', - - comparator: function( item ) { - return -item.get( this.sort_key ); - }, - - sortByField: function( fieldName ) { - this.sort_key = fieldName; - this.sort(); - } - }); - api.Menus.availableMenuItems = new api.Menus.AvailableItemCollection( api.Menus.data.availableMenuItems ); - - /** - * Insert a new `auto-draft` post. - * - * @since 4.7.0 - * @alias wp.customize.Menus.insertAutoDraftPost - * - * @param {object} params - Parameters for the draft post to create. - * @param {string} params.post_type - Post type to add. - * @param {string} params.post_title - Post title to use. - * @return {jQuery.promise} Promise resolved with the added post. - */ - api.Menus.insertAutoDraftPost = function insertAutoDraftPost( params ) { - var request, deferred = $.Deferred(); - - request = wp.ajax.post( 'customize-nav-menus-insert-auto-draft', { - 'customize-menus-nonce': api.settings.nonce['customize-menus'], - 'wp_customize': 'on', - 'customize_changeset_uuid': api.settings.changeset.uuid, - 'params': params - } ); - - request.done( function( response ) { - if ( response.post_id ) { - api( 'nav_menus_created_posts' ).set( - api( 'nav_menus_created_posts' ).get().concat( [ response.post_id ] ) - ); - - if ( 'page' === params.post_type ) { - - // Activate static front page controls as this could be the first page created. - if ( api.section.has( 'static_front_page' ) ) { - api.section( 'static_front_page' ).activate(); - } - - // Add new page to dropdown-pages controls. - api.control.each( function( control ) { - var select; - if ( 'dropdown-pages' === control.params.type ) { - select = control.container.find( 'select[name^="_customize-dropdown-pages-"]' ); - select.append( new Option( params.post_title, response.post_id ) ); - } - } ); - } - deferred.resolve( response ); - } - } ); - - request.fail( function( response ) { - var error = response || ''; - - if ( 'undefined' !== typeof response.message ) { - error = response.message; - } - - console.error( error ); - deferred.rejectWith( error ); - } ); - - return deferred.promise(); - }; - - api.Menus.AvailableMenuItemsPanelView = wp.Backbone.View.extend(/** @lends wp.customize.Menus.AvailableMenuItemsPanelView.prototype */{ - - el: '#available-menu-items', - - events: { - 'input #menu-items-search': 'debounceSearch', - 'focus .menu-item-tpl': 'focus', - 'click .menu-item-tpl': '_submit', - 'click #custom-menu-item-submit': '_submitLink', - 'keypress #custom-menu-item-name': '_submitLink', - 'click .new-content-item .add-content': '_submitNew', - 'keypress .create-item-input': '_submitNew', - 'keydown': 'keyboardAccessible' - }, - - // Cache current selected menu item. - selected: null, - - // Cache menu control that opened the panel. - currentMenuControl: null, - debounceSearch: null, - $search: null, - $clearResults: null, - searchTerm: '', - rendered: false, - pages: {}, - sectionContent: '', - loading: false, - addingNew: false, - - /** - * wp.customize.Menus.AvailableMenuItemsPanelView - * - * View class for the available menu items panel. - * - * @constructs wp.customize.Menus.AvailableMenuItemsPanelView - * @augments wp.Backbone.View - */ - initialize: function() { - var self = this; - - if ( ! api.panel.has( 'nav_menus' ) ) { - return; - } - - this.$search = $( '#menu-items-search' ); - this.$clearResults = this.$el.find( '.clear-results' ); - this.sectionContent = this.$el.find( '.available-menu-items-list' ); - - this.debounceSearch = _.debounce( self.search, 500 ); - - _.bindAll( this, 'close' ); - - // If the available menu items panel is open and the customize controls are - // interacted with (other than an item being deleted), then close the - // available menu items panel. Also close on back button click. - $( '#customize-controls, .customize-section-back' ).on( 'click keydown', function( e ) { - var isDeleteBtn = $( e.target ).is( '.item-delete, .item-delete *' ), - isAddNewBtn = $( e.target ).is( '.add-new-menu-item, .add-new-menu-item *' ); - if ( $( 'body' ).hasClass( 'adding-menu-items' ) && ! isDeleteBtn && ! isAddNewBtn ) { - self.close(); - } - } ); - - // Clear the search results and trigger a `keyup` event to fire a new search. - this.$clearResults.on( 'click', function() { - self.$search.val( '' ).focus().trigger( 'keyup' ); - } ); - - this.$el.on( 'input', '#custom-menu-item-name.invalid, #custom-menu-item-url.invalid', function() { - $( this ).removeClass( 'invalid' ); - }); - - // Load available items if it looks like we'll need them. - api.panel( 'nav_menus' ).container.bind( 'expanded', function() { - if ( ! self.rendered ) { - self.initList(); - self.rendered = true; - } - }); - - // Load more items. - this.sectionContent.scroll( function() { - var totalHeight = self.$el.find( '.accordion-section.open .available-menu-items-list' ).prop( 'scrollHeight' ), - visibleHeight = self.$el.find( '.accordion-section.open' ).height(); - - if ( ! self.loading && $( this ).scrollTop() > 3 / 4 * totalHeight - visibleHeight ) { - var type = $( this ).data( 'type' ), - object = $( this ).data( 'object' ); - - if ( 'search' === type ) { - if ( self.searchTerm ) { - self.doSearch( self.pages.search ); - } - } else { - self.loadItems( [ - { type: type, object: object } - ] ); - } - } - }); - - // Close the panel if the URL in the preview changes - api.previewer.bind( 'url', this.close ); - - self.delegateEvents(); - }, - - // Search input change handler. - search: function( event ) { - var $searchSection = $( '#available-menu-items-search' ), - $otherSections = $( '#available-menu-items .accordion-section' ).not( $searchSection ); - - if ( ! event ) { - return; - } - - if ( this.searchTerm === event.target.value ) { - return; - } - - if ( '' !== event.target.value && ! $searchSection.hasClass( 'open' ) ) { - $otherSections.fadeOut( 100 ); - $searchSection.find( '.accordion-section-content' ).slideDown( 'fast' ); - $searchSection.addClass( 'open' ); - this.$clearResults.addClass( 'is-visible' ); - } else if ( '' === event.target.value ) { - $searchSection.removeClass( 'open' ); - $otherSections.show(); - this.$clearResults.removeClass( 'is-visible' ); - } - - this.searchTerm = event.target.value; - this.pages.search = 1; - this.doSearch( 1 ); - }, - - // Get search results. - doSearch: function( page ) { - var self = this, params, - $section = $( '#available-menu-items-search' ), - $content = $section.find( '.accordion-section-content' ), - itemTemplate = wp.template( 'available-menu-item' ); - - if ( self.currentRequest ) { - self.currentRequest.abort(); - } - - if ( page < 0 ) { - return; - } else if ( page > 1 ) { - $section.addClass( 'loading-more' ); - $content.attr( 'aria-busy', 'true' ); - wp.a11y.speak( api.Menus.data.l10n.itemsLoadingMore ); - } else if ( '' === self.searchTerm ) { - $content.html( '' ); - wp.a11y.speak( '' ); - return; - } - - $section.addClass( 'loading' ); - self.loading = true; - - params = api.previewer.query( { excludeCustomizedSaved: true } ); - _.extend( params, { - 'customize-menus-nonce': api.settings.nonce['customize-menus'], - 'wp_customize': 'on', - 'search': self.searchTerm, - 'page': page - } ); - - self.currentRequest = wp.ajax.post( 'search-available-menu-items-customizer', params ); - - self.currentRequest.done(function( data ) { - var items; - if ( 1 === page ) { - // Clear previous results as it's a new search. - $content.empty(); - } - $section.removeClass( 'loading loading-more' ); - $content.attr( 'aria-busy', 'false' ); - $section.addClass( 'open' ); - self.loading = false; - items = new api.Menus.AvailableItemCollection( data.items ); - self.collection.add( items.models ); - items.each( function( menuItem ) { - $content.append( itemTemplate( menuItem.attributes ) ); - } ); - if ( 20 > items.length ) { - self.pages.search = -1; // Up to 20 posts and 20 terms in results, if <20, no more results for either. - } else { - self.pages.search = self.pages.search + 1; - } - if ( items && page > 1 ) { - wp.a11y.speak( api.Menus.data.l10n.itemsFoundMore.replace( '%d', items.length ) ); - } else if ( items && page === 1 ) { - wp.a11y.speak( api.Menus.data.l10n.itemsFound.replace( '%d', items.length ) ); - } - }); - - self.currentRequest.fail(function( data ) { - // data.message may be undefined, for example when typing slow and the request is aborted. - if ( data.message ) { - $content.empty().append( $( '<li class="nothing-found"></li>' ).text( data.message ) ); - wp.a11y.speak( data.message ); - } - self.pages.search = -1; - }); - - self.currentRequest.always(function() { - $section.removeClass( 'loading loading-more' ); - $content.attr( 'aria-busy', 'false' ); - self.loading = false; - self.currentRequest = null; - }); - }, - - // Render the individual items. - initList: function() { - var self = this; - - // Render the template for each item by type. - _.each( api.Menus.data.itemTypes, function( itemType ) { - self.pages[ itemType.type + ':' + itemType.object ] = 0; - } ); - self.loadItems( api.Menus.data.itemTypes ); - }, - - /** - * Load available nav menu items. - * - * @since 4.3.0 - * @since 4.7.0 Changed function signature to take list of item types instead of single type/object. - * @access private - * - * @param {Array.<object>} itemTypes List of objects containing type and key. - * @param {string} deprecated Formerly the object parameter. - * @returns {void} - */ - loadItems: function( itemTypes, deprecated ) { - var self = this, _itemTypes, requestItemTypes = [], params, request, itemTemplate, availableMenuItemContainers = {}; - itemTemplate = wp.template( 'available-menu-item' ); - - if ( _.isString( itemTypes ) && _.isString( deprecated ) ) { - _itemTypes = [ { type: itemTypes, object: deprecated } ]; - } else { - _itemTypes = itemTypes; - } - - _.each( _itemTypes, function( itemType ) { - var container, name = itemType.type + ':' + itemType.object; - if ( -1 === self.pages[ name ] ) { - return; // Skip types for which there are no more results. - } - container = $( '#available-menu-items-' + itemType.type + '-' + itemType.object ); - container.find( '.accordion-section-title' ).addClass( 'loading' ); - availableMenuItemContainers[ name ] = container; - - requestItemTypes.push( { - object: itemType.object, - type: itemType.type, - page: self.pages[ name ] - } ); - } ); - - if ( 0 === requestItemTypes.length ) { - return; - } - - self.loading = true; - - params = api.previewer.query( { excludeCustomizedSaved: true } ); - _.extend( params, { - 'customize-menus-nonce': api.settings.nonce['customize-menus'], - 'wp_customize': 'on', - 'item_types': requestItemTypes - } ); - - request = wp.ajax.post( 'load-available-menu-items-customizer', params ); - - request.done(function( data ) { - var typeInner; - _.each( data.items, function( typeItems, name ) { - if ( 0 === typeItems.length ) { - if ( 0 === self.pages[ name ] ) { - availableMenuItemContainers[ name ].find( '.accordion-section-title' ) - .addClass( 'cannot-expand' ) - .removeClass( 'loading' ) - .find( '.accordion-section-title > button' ) - .prop( 'tabIndex', -1 ); - } - self.pages[ name ] = -1; - return; - } else if ( ( 'post_type:page' === name ) && ( ! availableMenuItemContainers[ name ].hasClass( 'open' ) ) ) { - availableMenuItemContainers[ name ].find( '.accordion-section-title > button' ).click(); - } - typeItems = new api.Menus.AvailableItemCollection( typeItems ); // @todo Why is this collection created and then thrown away? - self.collection.add( typeItems.models ); - typeInner = availableMenuItemContainers[ name ].find( '.available-menu-items-list' ); - typeItems.each( function( menuItem ) { - typeInner.append( itemTemplate( menuItem.attributes ) ); - } ); - self.pages[ name ] += 1; - }); - }); - request.fail(function( data ) { - if ( typeof console !== 'undefined' && console.error ) { - console.error( data ); - } - }); - request.always(function() { - _.each( availableMenuItemContainers, function( container ) { - container.find( '.accordion-section-title' ).removeClass( 'loading' ); - } ); - self.loading = false; - }); - }, - - // Adjust the height of each section of items to fit the screen. - itemSectionHeight: function() { - var sections, lists, totalHeight, accordionHeight, diff; - totalHeight = window.innerHeight; - sections = this.$el.find( '.accordion-section:not( #available-menu-items-search ) .accordion-section-content' ); - lists = this.$el.find( '.accordion-section:not( #available-menu-items-search ) .available-menu-items-list:not(":only-child")' ); - accordionHeight = 46 * ( 1 + sections.length ) + 14; // Magic numbers. - diff = totalHeight - accordionHeight; - if ( 120 < diff && 290 > diff ) { - sections.css( 'max-height', diff ); - lists.css( 'max-height', ( diff - 60 ) ); - } - }, - - // Highlights a menu item. - select: function( menuitemTpl ) { - this.selected = $( menuitemTpl ); - this.selected.siblings( '.menu-item-tpl' ).removeClass( 'selected' ); - this.selected.addClass( 'selected' ); - }, - - // Highlights a menu item on focus. - focus: function( event ) { - this.select( $( event.currentTarget ) ); - }, - - // Submit handler for keypress and click on menu item. - _submit: function( event ) { - // Only proceed with keypress if it is Enter or Spacebar - if ( 'keypress' === event.type && ( 13 !== event.which && 32 !== event.which ) ) { - return; - } - - this.submit( $( event.currentTarget ) ); - }, - - // Adds a selected menu item to the menu. - submit: function( menuitemTpl ) { - var menuitemId, menu_item; - - if ( ! menuitemTpl ) { - menuitemTpl = this.selected; - } - - if ( ! menuitemTpl || ! this.currentMenuControl ) { - return; - } - - this.select( menuitemTpl ); - - menuitemId = $( this.selected ).data( 'menu-item-id' ); - menu_item = this.collection.findWhere( { id: menuitemId } ); - if ( ! menu_item ) { - return; - } - - this.currentMenuControl.addItemToMenu( menu_item.attributes ); - - $( menuitemTpl ).find( '.menu-item-handle' ).addClass( 'item-added' ); - }, - - // Submit handler for keypress and click on custom menu item. - _submitLink: function( event ) { - // Only proceed with keypress if it is Enter. - if ( 'keypress' === event.type && 13 !== event.which ) { - return; - } - - this.submitLink(); - }, - - // Adds the custom menu item to the menu. - submitLink: function() { - var menuItem, - itemName = $( '#custom-menu-item-name' ), - itemUrl = $( '#custom-menu-item-url' ), - url = itemUrl.val().trim(), - urlRegex; - - if ( ! this.currentMenuControl ) { - return; - } - - /* - * Allow URLs including: - * - http://example.com/ - * - //example.com - * - /directory/ - * - ?query-param - * - #target - * - mailto:foo@example.com - * - * Any further validation will be handled on the server when the setting is attempted to be saved, - * so this pattern does not need to be complete. - */ - urlRegex = /^((\w+:)?\/\/\w.*|\w+:(?!\/\/$)|\/|\?|#)/; - - if ( '' === itemName.val() ) { - itemName.addClass( 'invalid' ); - return; - } else if ( ! urlRegex.test( url ) ) { - itemUrl.addClass( 'invalid' ); - return; - } - - menuItem = { - 'title': itemName.val(), - 'url': url, - 'type': 'custom', - 'type_label': api.Menus.data.l10n.custom_label, - 'object': 'custom' - }; - - this.currentMenuControl.addItemToMenu( menuItem ); - - // Reset the custom link form. - itemUrl.val( '' ).attr( 'placeholder', 'https://' ); - itemName.val( '' ); - }, - - /** - * Submit handler for keypress (enter) on field and click on button. - * - * @since 4.7.0 - * @private - * - * @param {jQuery.Event} event Event. - * @returns {void} - */ - _submitNew: function( event ) { - var container; - - // Only proceed with keypress if it is Enter. - if ( 'keypress' === event.type && 13 !== event.which ) { - return; - } - - if ( this.addingNew ) { - return; - } - - container = $( event.target ).closest( '.accordion-section' ); - - this.submitNew( container ); - }, - - /** - * Creates a new object and adds an associated menu item to the menu. - * - * @since 4.7.0 - * @private - * - * @param {jQuery} container - * @returns {void} - */ - submitNew: function( container ) { - var panel = this, - itemName = container.find( '.create-item-input' ), - title = itemName.val(), - dataContainer = container.find( '.available-menu-items-list' ), - itemType = dataContainer.data( 'type' ), - itemObject = dataContainer.data( 'object' ), - itemTypeLabel = dataContainer.data( 'type_label' ), - promise; - - if ( ! this.currentMenuControl ) { - return; - } - - // Only posts are supported currently. - if ( 'post_type' !== itemType ) { - return; - } - - if ( '' === $.trim( itemName.val() ) ) { - itemName.addClass( 'invalid' ); - itemName.focus(); - return; - } else { - itemName.removeClass( 'invalid' ); - container.find( '.accordion-section-title' ).addClass( 'loading' ); - } - - panel.addingNew = true; - itemName.attr( 'disabled', 'disabled' ); - promise = api.Menus.insertAutoDraftPost( { - post_title: title, - post_type: itemObject - } ); - promise.done( function( data ) { - var availableItem, $content, itemElement; - availableItem = new api.Menus.AvailableItemModel( { - 'id': 'post-' + data.post_id, // Used for available menu item Backbone models. - 'title': itemName.val(), - 'type': itemType, - 'type_label': itemTypeLabel, - 'object': itemObject, - 'object_id': data.post_id, - 'url': data.url - } ); - - // Add new item to menu. - panel.currentMenuControl.addItemToMenu( availableItem.attributes ); - - // Add the new item to the list of available items. - api.Menus.availableMenuItemsPanel.collection.add( availableItem ); - $content = container.find( '.available-menu-items-list' ); - itemElement = $( wp.template( 'available-menu-item' )( availableItem.attributes ) ); - itemElement.find( '.menu-item-handle:first' ).addClass( 'item-added' ); - $content.prepend( itemElement ); - $content.scrollTop(); - - // Reset the create content form. - itemName.val( '' ).removeAttr( 'disabled' ); - panel.addingNew = false; - container.find( '.accordion-section-title' ).removeClass( 'loading' ); - } ); - }, - - // Opens the panel. - open: function( menuControl ) { - var panel = this, close; - - this.currentMenuControl = menuControl; - - this.itemSectionHeight(); - - if ( api.section.has( 'publish_settings' ) ) { - api.section( 'publish_settings' ).collapse(); - } - - $( 'body' ).addClass( 'adding-menu-items' ); - - close = function() { - panel.close(); - $( this ).off( 'click', close ); - }; - $( '#customize-preview' ).on( 'click', close ); - - // Collapse all controls. - _( this.currentMenuControl.getMenuItemControls() ).each( function( control ) { - control.collapseForm(); - } ); - - this.$el.find( '.selected' ).removeClass( 'selected' ); - - this.$search.focus(); - }, - - // Closes the panel - close: function( options ) { - options = options || {}; - - if ( options.returnFocus && this.currentMenuControl ) { - this.currentMenuControl.container.find( '.add-new-menu-item' ).focus(); - } - - this.currentMenuControl = null; - this.selected = null; - - $( 'body' ).removeClass( 'adding-menu-items' ); - $( '#available-menu-items .menu-item-handle.item-added' ).removeClass( 'item-added' ); - - this.$search.val( '' ).trigger( 'keyup' ); - }, - - // Add a few keyboard enhancements to the panel. - keyboardAccessible: function( event ) { - var isEnter = ( 13 === event.which ), - isEsc = ( 27 === event.which ), - isBackTab = ( 9 === event.which && event.shiftKey ), - isSearchFocused = $( event.target ).is( this.$search ); - - // If enter pressed but nothing entered, don't do anything - if ( isEnter && ! this.$search.val() ) { - return; - } - - if ( isSearchFocused && isBackTab ) { - this.currentMenuControl.container.find( '.add-new-menu-item' ).focus(); - event.preventDefault(); // Avoid additional back-tab. - } else if ( isEsc ) { - this.close( { returnFocus: true } ); - } - } - }); - - /** - * wp.customize.Menus.MenusPanel - * - * Customizer panel for menus. This is used only for screen options management. - * Note that 'menus' must match the WP_Customize_Menu_Panel::$type. - * - * @class wp.customize.Menus.MenusPanel - * @augments wp.customize.Panel - */ - api.Menus.MenusPanel = api.Panel.extend(/** @lends wp.customize.Menus.MenusPanel.prototype */{ - - attachEvents: function() { - api.Panel.prototype.attachEvents.call( this ); - - var panel = this, - panelMeta = panel.container.find( '.panel-meta' ), - help = panelMeta.find( '.customize-help-toggle' ), - content = panelMeta.find( '.customize-panel-description' ), - options = $( '#screen-options-wrap' ), - button = panelMeta.find( '.customize-screen-options-toggle' ); - button.on( 'click keydown', function( event ) { - if ( api.utils.isKeydownButNotEnterEvent( event ) ) { - return; - } - event.preventDefault(); - - // Hide description - if ( content.not( ':hidden' ) ) { - content.slideUp( 'fast' ); - help.attr( 'aria-expanded', 'false' ); - } - - if ( 'true' === button.attr( 'aria-expanded' ) ) { - button.attr( 'aria-expanded', 'false' ); - panelMeta.removeClass( 'open' ); - panelMeta.removeClass( 'active-menu-screen-options' ); - options.slideUp( 'fast' ); - } else { - button.attr( 'aria-expanded', 'true' ); - panelMeta.addClass( 'open' ); - panelMeta.addClass( 'active-menu-screen-options' ); - options.slideDown( 'fast' ); - } - - return false; - } ); - - // Help toggle - help.on( 'click keydown', function( event ) { - if ( api.utils.isKeydownButNotEnterEvent( event ) ) { - return; - } - event.preventDefault(); - - if ( 'true' === button.attr( 'aria-expanded' ) ) { - button.attr( 'aria-expanded', 'false' ); - help.attr( 'aria-expanded', 'true' ); - panelMeta.addClass( 'open' ); - panelMeta.removeClass( 'active-menu-screen-options' ); - options.slideUp( 'fast' ); - content.slideDown( 'fast' ); - } - } ); - }, - - /** - * Update field visibility when clicking on the field toggles. - */ - ready: function() { - var panel = this; - panel.container.find( '.hide-column-tog' ).click( function() { - panel.saveManageColumnsState(); - }); - - // Inject additional heading into the menu locations section's head container. - api.section( 'menu_locations', function( section ) { - section.headContainer.prepend( - wp.template( 'nav-menu-locations-header' )( api.Menus.data ) - ); - } ); - }, - - /** - * Save hidden column states. - * - * @since 4.3.0 - * @private - * - * @returns {void} - */ - saveManageColumnsState: _.debounce( function() { - var panel = this; - if ( panel._updateHiddenColumnsRequest ) { - panel._updateHiddenColumnsRequest.abort(); - } - - panel._updateHiddenColumnsRequest = wp.ajax.post( 'hidden-columns', { - hidden: panel.hidden(), - screenoptionnonce: $( '#screenoptionnonce' ).val(), - page: 'nav-menus' - } ); - panel._updateHiddenColumnsRequest.always( function() { - panel._updateHiddenColumnsRequest = null; - } ); - }, 2000 ), - - /** - * @deprecated Since 4.7.0 now that the nav_menu sections are responsible for toggling the classes on their own containers. - */ - checked: function() {}, - - /** - * @deprecated Since 4.7.0 now that the nav_menu sections are responsible for toggling the classes on their own containers. - */ - unchecked: function() {}, - - /** - * Get hidden fields. - * - * @since 4.3.0 - * @private - * - * @returns {Array} Fields (columns) that are hidden. - */ - hidden: function() { - return $( '.hide-column-tog' ).not( ':checked' ).map( function() { - var id = this.id; - return id.substring( 0, id.length - 5 ); - }).get().join( ',' ); - } - } ); - - /** - * wp.customize.Menus.MenuSection - * - * Customizer section for menus. This is used only for lazy-loading child controls. - * Note that 'nav_menu' must match the WP_Customize_Menu_Section::$type. - * - * @class wp.customize.Menus.MenuSection - * @augments wp.customize.Section - */ - api.Menus.MenuSection = api.Section.extend(/** @lends wp.customize.Menus.MenuSection.prototype */{ - - /** - * Initialize. - * - * @since 4.3.0 - * - * @param {String} id - * @param {Object} options - */ - initialize: function( id, options ) { - var section = this; - api.Section.prototype.initialize.call( section, id, options ); - section.deferred.initSortables = $.Deferred(); - }, - - /** - * Ready. - */ - ready: function() { - var section = this, fieldActiveToggles, handleFieldActiveToggle; - - if ( 'undefined' === typeof section.params.menu_id ) { - throw new Error( 'params.menu_id was not defined' ); - } - - /* - * Since newly created sections won't be registered in PHP, we need to prevent the - * preview's sending of the activeSections to result in this control - * being deactivated when the preview refreshes. So we can hook onto - * the setting that has the same ID and its presence can dictate - * whether the section is active. - */ - section.active.validate = function() { - if ( ! api.has( section.id ) ) { - return false; - } - return !! api( section.id ).get(); - }; - - section.populateControls(); - - section.navMenuLocationSettings = {}; - section.assignedLocations = new api.Value( [] ); - - api.each(function( setting, id ) { - var matches = id.match( /^nav_menu_locations\[(.+?)]/ ); - if ( matches ) { - section.navMenuLocationSettings[ matches[1] ] = setting; - setting.bind( function() { - section.refreshAssignedLocations(); - }); - } - }); - - section.assignedLocations.bind(function( to ) { - section.updateAssignedLocationsInSectionTitle( to ); - }); - - section.refreshAssignedLocations(); - - api.bind( 'pane-contents-reflowed', function() { - // Skip menus that have been removed. - if ( ! section.contentContainer.parent().length ) { - return; - } - section.container.find( '.menu-item .menu-item-reorder-nav button' ).attr({ 'tabindex': '0', 'aria-hidden': 'false' }); - section.container.find( '.menu-item.move-up-disabled .menus-move-up' ).attr({ 'tabindex': '-1', 'aria-hidden': 'true' }); - section.container.find( '.menu-item.move-down-disabled .menus-move-down' ).attr({ 'tabindex': '-1', 'aria-hidden': 'true' }); - section.container.find( '.menu-item.move-left-disabled .menus-move-left' ).attr({ 'tabindex': '-1', 'aria-hidden': 'true' }); - section.container.find( '.menu-item.move-right-disabled .menus-move-right' ).attr({ 'tabindex': '-1', 'aria-hidden': 'true' }); - } ); - - /** - * Update the active field class for the content container for a given checkbox toggle. - * - * @this {jQuery} - * @returns {void} - */ - handleFieldActiveToggle = function() { - var className = 'field-' + $( this ).val() + '-active'; - section.contentContainer.toggleClass( className, $( this ).prop( 'checked' ) ); - }; - fieldActiveToggles = api.panel( 'nav_menus' ).contentContainer.find( '.metabox-prefs:first' ).find( '.hide-column-tog' ); - fieldActiveToggles.each( handleFieldActiveToggle ); - fieldActiveToggles.on( 'click', handleFieldActiveToggle ); - }, - - populateControls: function() { - var section = this, - menuNameControlId, - menuLocationsControlId, - menuAutoAddControlId, - menuDeleteControlId, - menuControl, - menuNameControl, - menuLocationsControl, - menuAutoAddControl, - menuDeleteControl; - - // Add the control for managing the menu name. - menuNameControlId = section.id + '[name]'; - menuNameControl = api.control( menuNameControlId ); - if ( ! menuNameControl ) { - menuNameControl = new api.controlConstructor.nav_menu_name( menuNameControlId, { - type: 'nav_menu_name', - label: api.Menus.data.l10n.menuNameLabel, - section: section.id, - priority: 0, - settings: { - 'default': section.id - } - } ); - api.control.add( menuNameControl ); - menuNameControl.active.set( true ); - } - - // Add the menu control. - menuControl = api.control( section.id ); - if ( ! menuControl ) { - menuControl = new api.controlConstructor.nav_menu( section.id, { - type: 'nav_menu', - section: section.id, - priority: 998, - settings: { - 'default': section.id - }, - menu_id: section.params.menu_id - } ); - api.control.add( menuControl ); - menuControl.active.set( true ); - } - - // Add the menu locations control. - menuLocationsControlId = section.id + '[locations]'; - menuLocationsControl = api.control( menuLocationsControlId ); - if ( ! menuLocationsControl ) { - menuLocationsControl = new api.controlConstructor.nav_menu_locations( menuLocationsControlId, { - section: section.id, - priority: 999, - settings: { - 'default': section.id - }, - menu_id: section.params.menu_id - } ); - api.control.add( menuLocationsControl.id, menuLocationsControl ); - menuControl.active.set( true ); - } - - // Add the control for managing the menu auto_add. - menuAutoAddControlId = section.id + '[auto_add]'; - menuAutoAddControl = api.control( menuAutoAddControlId ); - if ( ! menuAutoAddControl ) { - menuAutoAddControl = new api.controlConstructor.nav_menu_auto_add( menuAutoAddControlId, { - type: 'nav_menu_auto_add', - label: '', - section: section.id, - priority: 1000, - settings: { - 'default': section.id - } - } ); - api.control.add( menuAutoAddControl ); - menuAutoAddControl.active.set( true ); - } - - // Add the control for deleting the menu - menuDeleteControlId = section.id + '[delete]'; - menuDeleteControl = api.control( menuDeleteControlId ); - if ( ! menuDeleteControl ) { - menuDeleteControl = new api.Control( menuDeleteControlId, { - section: section.id, - priority: 1001, - templateId: 'nav-menu-delete-button' - } ); - api.control.add( menuDeleteControl.id, menuDeleteControl ); - menuDeleteControl.active.set( true ); - menuDeleteControl.deferred.embedded.done( function () { - menuDeleteControl.container.find( 'button' ).on( 'click', function() { - var menuId = section.params.menu_id; - var menuControl = api.Menus.getMenuControl( menuId ); - menuControl.setting.set( false ); - }); - } ); - } - }, - - /** - * - */ - refreshAssignedLocations: function() { - var section = this, - menuTermId = section.params.menu_id, - currentAssignedLocations = []; - _.each( section.navMenuLocationSettings, function( setting, themeLocation ) { - if ( setting() === menuTermId ) { - currentAssignedLocations.push( themeLocation ); - } - }); - section.assignedLocations.set( currentAssignedLocations ); - }, - - /** - * @param {Array} themeLocationSlugs Theme location slugs. - */ - updateAssignedLocationsInSectionTitle: function( themeLocationSlugs ) { - var section = this, - $title; - - $title = section.container.find( '.accordion-section-title:first' ); - $title.find( '.menu-in-location' ).remove(); - _.each( themeLocationSlugs, function( themeLocationSlug ) { - var $label, locationName; - $label = $( '<span class="menu-in-location"></span>' ); - locationName = api.Menus.data.locationSlugMappedToName[ themeLocationSlug ]; - $label.text( api.Menus.data.l10n.menuLocation.replace( '%s', locationName ) ); - $title.append( $label ); - }); - - section.container.toggleClass( 'assigned-to-menu-location', 0 !== themeLocationSlugs.length ); - - }, - - onChangeExpanded: function( expanded, args ) { - var section = this, completeCallback; - - if ( expanded ) { - wpNavMenu.menuList = section.contentContainer; - wpNavMenu.targetList = wpNavMenu.menuList; - - // Add attributes needed by wpNavMenu - $( '#menu-to-edit' ).removeAttr( 'id' ); - wpNavMenu.menuList.attr( 'id', 'menu-to-edit' ).addClass( 'menu' ); - - _.each( api.section( section.id ).controls(), function( control ) { - if ( 'nav_menu_item' === control.params.type ) { - control.actuallyEmbed(); - } - } ); - - // Make sure Sortables is initialized after the section has been expanded to prevent `offset` issues. - if ( args.completeCallback ) { - completeCallback = args.completeCallback; - } - args.completeCallback = function() { - if ( 'resolved' !== section.deferred.initSortables.state() ) { - wpNavMenu.initSortables(); // Depends on menu-to-edit ID being set above. - section.deferred.initSortables.resolve( wpNavMenu.menuList ); // Now MenuControl can extend the sortable. - - // @todo Note that wp.customize.reflowPaneContents() is debounced, so this immediate change will show a slight flicker while priorities get updated. - api.control( 'nav_menu[' + String( section.params.menu_id ) + ']' ).reflowMenuItems(); - } - if ( _.isFunction( completeCallback ) ) { - completeCallback(); - } - }; - } - api.Section.prototype.onChangeExpanded.call( section, expanded, args ); - }, - - /** - * Highlight how a user may create new menu items. - * - * This method reminds the user to create new menu items and how. - * It's exposed this way because this class knows best which UI needs - * highlighted but those expanding this section know more about why and - * when the affordance should be highlighted. - * - * @since 4.9.0 - * - * @returns {void} - */ - highlightNewItemButton: function() { - api.utils.highlightButton( this.contentContainer.find( '.add-new-menu-item' ), { delay: 2000 } ); - } - }); - - /** - * Create a nav menu setting and section. - * - * @since 4.9.0 - * - * @param {string} [name=''] Nav menu name. - * @returns {wp.customize.Menus.MenuSection} Added nav menu. - */ - api.Menus.createNavMenu = function createNavMenu( name ) { - var customizeId, placeholderId, setting; - placeholderId = api.Menus.generatePlaceholderAutoIncrementId(); - - customizeId = 'nav_menu[' + String( placeholderId ) + ']'; - - // Register the menu control setting. - setting = api.create( customizeId, customizeId, {}, { - type: 'nav_menu', - transport: api.Menus.data.settingTransport, - previewer: api.previewer - } ); - setting.set( $.extend( - {}, - api.Menus.data.defaultSettingValues.nav_menu, - { - name: name || '' - } - ) ); - - /* - * Add the menu section (and its controls). - * Note that this will automatically create the required controls - * inside via the Section's ready method. - */ - return api.section.add( new api.Menus.MenuSection( customizeId, { - panel: 'nav_menus', - title: displayNavMenuName( name ), - customizeAction: api.Menus.data.l10n.customizingMenus, - priority: 10, - menu_id: placeholderId - } ) ); - }; - - /** - * wp.customize.Menus.NewMenuSection - * - * Customizer section for new menus. - * - * @class wp.customize.Menus.NewMenuSection - * @augments wp.customize.Section - */ - api.Menus.NewMenuSection = api.Section.extend(/** @lends wp.customize.Menus.NewMenuSection.prototype */{ - - /** - * Add behaviors for the accordion section. - * - * @since 4.3.0 - */ - attachEvents: function() { - var section = this, - container = section.container, - contentContainer = section.contentContainer, - navMenuSettingPattern = /^nav_menu\[/; - - section.headContainer.find( '.accordion-section-title' ).replaceWith( - wp.template( 'nav-menu-create-menu-section-title' ) - ); - - /* - * We have to manually handle section expanded because we do not - * apply the `accordion-section-title` class to this button-driven section. - */ - container.on( 'click', '.customize-add-menu-button', function() { - section.expand(); - }); - - contentContainer.on( 'keydown', '.menu-name-field', function( event ) { - if ( 13 === event.which ) { // Enter. - section.submit(); - } - } ); - contentContainer.on( 'click', '#customize-new-menu-submit', function( event ) { - section.submit(); - event.stopPropagation(); - event.preventDefault(); - } ); - - /** - * Get number of non-deleted nav menus. - * - * @since 4.9.0 - * @returns {number} Count. - */ - function getNavMenuCount() { - var count = 0; - api.each( function( setting ) { - if ( navMenuSettingPattern.test( setting.id ) && false !== setting.get() ) { - count += 1; - } - } ); - return count; - } - - /** - * Update visibility of notice to prompt users to create menus. - * - * @since 4.9.0 - * @returns {void} - */ - function updateNoticeVisibility() { - container.find( '.add-new-menu-notice' ).prop( 'hidden', getNavMenuCount() > 0 ); - } - - /** - * Handle setting addition. - * - * @since 4.9.0 - * @param {wp.customize.Setting} setting - Added setting. - * @returns {void} - */ - function addChangeEventListener( setting ) { - if ( navMenuSettingPattern.test( setting.id ) ) { - setting.bind( updateNoticeVisibility ); - updateNoticeVisibility(); - } - } - - /** - * Handle setting removal. - * - * @since 4.9.0 - * @param {wp.customize.Setting} setting - Removed setting. - * @returns {void} - */ - function removeChangeEventListener( setting ) { - if ( navMenuSettingPattern.test( setting.id ) ) { - setting.unbind( updateNoticeVisibility ); - updateNoticeVisibility(); - } - } - - api.each( addChangeEventListener ); - api.bind( 'add', addChangeEventListener ); - api.bind( 'removed', removeChangeEventListener ); - updateNoticeVisibility(); - - api.Section.prototype.attachEvents.apply( section, arguments ); - }, - - /** - * Set up the control. - * - * @since 4.9.0 - */ - ready: function() { - this.populateControls(); - }, - - /** - * Create the controls for this section. - * - * @since 4.9.0 - */ - populateControls: function() { - var section = this, - menuNameControlId, - menuLocationsControlId, - newMenuSubmitControlId, - menuNameControl, - menuLocationsControl, - newMenuSubmitControl; - - menuNameControlId = section.id + '[name]'; - menuNameControl = api.control( menuNameControlId ); - if ( ! menuNameControl ) { - menuNameControl = new api.controlConstructor.nav_menu_name( menuNameControlId, { - label: api.Menus.data.l10n.menuNameLabel, - description: api.Menus.data.l10n.newMenuNameDescription, - section: section.id, - priority: 0 - } ); - api.control.add( menuNameControl.id, menuNameControl ); - menuNameControl.active.set( true ); - } - - menuLocationsControlId = section.id + '[locations]'; - menuLocationsControl = api.control( menuLocationsControlId ); - if ( ! menuLocationsControl ) { - menuLocationsControl = new api.controlConstructor.nav_menu_locations( menuLocationsControlId, { - section: section.id, - priority: 1, - menu_id: '', - isCreating: true - } ); - api.control.add( menuLocationsControlId, menuLocationsControl ); - menuLocationsControl.active.set( true ); - } - - newMenuSubmitControlId = section.id + '[submit]'; - newMenuSubmitControl = api.control( newMenuSubmitControlId ); - if ( !newMenuSubmitControl ) { - newMenuSubmitControl = new api.Control( newMenuSubmitControlId, { - section: section.id, - priority: 1, - templateId: 'nav-menu-submit-new-button' - } ); - api.control.add( newMenuSubmitControlId, newMenuSubmitControl ); - newMenuSubmitControl.active.set( true ); - } - }, - - /** - * Create the new menu with name and location supplied by the user. - * - * @since 4.9.0 - */ - submit: function() { - var section = this, - contentContainer = section.contentContainer, - nameInput = contentContainer.find( '.menu-name-field' ).first(), - name = nameInput.val(), - menuSection; - - if ( ! name ) { - nameInput.addClass( 'invalid' ); - nameInput.focus(); - return; - } - - menuSection = api.Menus.createNavMenu( name ); - - // Clear name field. - nameInput.val( '' ); - nameInput.removeClass( 'invalid' ); - - contentContainer.find( '.assigned-menu-location input[type=checkbox]' ).each( function() { - var checkbox = $( this ), - navMenuLocationSetting; - - if ( checkbox.prop( 'checked' ) ) { - navMenuLocationSetting = api( 'nav_menu_locations[' + checkbox.data( 'location-id' ) + ']' ); - navMenuLocationSetting.set( menuSection.params.menu_id ); - - // Reset state for next new menu - checkbox.prop( 'checked', false ); - } - } ); - - wp.a11y.speak( api.Menus.data.l10n.menuAdded ); - - // Focus on the new menu section. - menuSection.focus( { - completeCallback: function() { - menuSection.highlightNewItemButton(); - } - } ); - }, - - /** - * Select a default location. - * - * This method selects a single location by default so we can support - * creating a menu for a specific menu location. - * - * @since 4.9.0 - * - * @param {string|null} locationId - The ID of the location to select. `null` clears all selections. - * @returns {void} - */ - selectDefaultLocation: function( locationId ) { - var locationControl = api.control( this.id + '[locations]' ), - locationSelections = {}; - - if ( locationId !== null ) { - locationSelections[ locationId ] = true; - } - - locationControl.setSelections( locationSelections ); - } - }); - - /** - * wp.customize.Menus.MenuLocationControl - * - * Customizer control for menu locations (rendered as a <select>). - * Note that 'nav_menu_location' must match the WP_Customize_Nav_Menu_Location_Control::$type. - * - * @class wp.customize.Menus.MenuLocationControl - * @augments wp.customize.Control - */ - api.Menus.MenuLocationControl = api.Control.extend(/** @lends wp.customize.Menus.MenuLocationControl.prototype */{ - initialize: function( id, options ) { - var control = this, - matches = id.match( /^nav_menu_locations\[(.+?)]/ ); - control.themeLocation = matches[1]; - api.Control.prototype.initialize.call( control, id, options ); - }, - - ready: function() { - var control = this, navMenuIdRegex = /^nav_menu\[(-?\d+)]/; - - // @todo It would be better if this was added directly on the setting itself, as opposed to the control. - control.setting.validate = function( value ) { - if ( '' === value ) { - return 0; - } else { - return parseInt( value, 10 ); - } - }; - - // Create and Edit menu buttons. - control.container.find( '.create-menu' ).on( 'click', function() { - var addMenuSection = api.section( 'add_menu' ); - addMenuSection.selectDefaultLocation( this.dataset.locationId ); - addMenuSection.focus(); - } ); - control.container.find( '.edit-menu' ).on( 'click', function() { - var menuId = control.setting(); - api.section( 'nav_menu[' + menuId + ']' ).focus(); - }); - control.setting.bind( 'change', function() { - var menuIsSelected = 0 !== control.setting(); - control.container.find( '.create-menu' ).toggleClass( 'hidden', menuIsSelected ); - control.container.find( '.edit-menu' ).toggleClass( 'hidden', ! menuIsSelected ); - }); - - // Add/remove menus from the available options when they are added and removed. - api.bind( 'add', function( setting ) { - var option, menuId, matches = setting.id.match( navMenuIdRegex ); - if ( ! matches || false === setting() ) { - return; - } - menuId = matches[1]; - option = new Option( displayNavMenuName( setting().name ), menuId ); - control.container.find( 'select' ).append( option ); - }); - api.bind( 'remove', function( setting ) { - var menuId, matches = setting.id.match( navMenuIdRegex ); - if ( ! matches ) { - return; - } - menuId = parseInt( matches[1], 10 ); - if ( control.setting() === menuId ) { - control.setting.set( '' ); - } - control.container.find( 'option[value=' + menuId + ']' ).remove(); - }); - api.bind( 'change', function( setting ) { - var menuId, matches = setting.id.match( navMenuIdRegex ); - if ( ! matches ) { - return; - } - menuId = parseInt( matches[1], 10 ); - if ( false === setting() ) { - if ( control.setting() === menuId ) { - control.setting.set( '' ); - } - control.container.find( 'option[value=' + menuId + ']' ).remove(); - } else { - control.container.find( 'option[value=' + menuId + ']' ).text( displayNavMenuName( setting().name ) ); - } - }); - } - }); - - api.Menus.MenuItemControl = api.Control.extend(/** @lends wp.customize.Menus.MenuItemControl.prototype */{ - - /** - * wp.customize.Menus.MenuItemControl - * - * Customizer control for menu items. - * Note that 'menu_item' must match the WP_Customize_Menu_Item_Control::$type. - * - * @constructs wp.customize.Menus.MenuItemControl - * @augments wp.customize.Control - * - * @inheritDoc - */ - initialize: function( id, options ) { - var control = this; - control.expanded = new api.Value( false ); - control.expandedArgumentsQueue = []; - control.expanded.bind( function( expanded ) { - var args = control.expandedArgumentsQueue.shift(); - args = $.extend( {}, control.defaultExpandedArguments, args ); - control.onChangeExpanded( expanded, args ); - }); - api.Control.prototype.initialize.call( control, id, options ); - control.active.validate = function() { - var value, section = api.section( control.section() ); - if ( section ) { - value = section.active(); - } else { - value = false; - } - return value; - }; - }, - - /** - * Override the embed() method to do nothing, - * so that the control isn't embedded on load, - * unless the containing section is already expanded. - * - * @since 4.3.0 - */ - embed: function() { - var control = this, - sectionId = control.section(), - section; - if ( ! sectionId ) { - return; - } - section = api.section( sectionId ); - if ( ( section && section.expanded() ) || api.settings.autofocus.control === control.id ) { - control.actuallyEmbed(); - } - }, - - /** - * This function is called in Section.onChangeExpanded() so the control - * will only get embedded when the Section is first expanded. - * - * @since 4.3.0 - */ - actuallyEmbed: function() { - var control = this; - if ( 'resolved' === control.deferred.embedded.state() ) { - return; - } - control.renderContent(); - control.deferred.embedded.resolve(); // This triggers control.ready(). - }, - - /** - * Set up the control. - */ - ready: function() { - if ( 'undefined' === typeof this.params.menu_item_id ) { - throw new Error( 'params.menu_item_id was not defined' ); - } - - this._setupControlToggle(); - this._setupReorderUI(); - this._setupUpdateUI(); - this._setupRemoveUI(); - this._setupLinksUI(); - this._setupTitleUI(); - }, - - /** - * Show/hide the settings when clicking on the menu item handle. - */ - _setupControlToggle: function() { - var control = this; - - this.container.find( '.menu-item-handle' ).on( 'click', function( e ) { - e.preventDefault(); - e.stopPropagation(); - var menuControl = control.getMenuControl(), - isDeleteBtn = $( e.target ).is( '.item-delete, .item-delete *' ), - isAddNewBtn = $( e.target ).is( '.add-new-menu-item, .add-new-menu-item *' ); - - if ( $( 'body' ).hasClass( 'adding-menu-items' ) && ! isDeleteBtn && ! isAddNewBtn ) { - api.Menus.availableMenuItemsPanel.close(); - } - - if ( menuControl.isReordering || menuControl.isSorting ) { - return; - } - control.toggleForm(); - } ); - }, - - /** - * Set up the menu-item-reorder-nav - */ - _setupReorderUI: function() { - var control = this, template, $reorderNav; - - template = wp.template( 'menu-item-reorder-nav' ); - - // Add the menu item reordering elements to the menu item control. - control.container.find( '.item-controls' ).after( template ); - - // Handle clicks for up/down/left-right on the reorder nav. - $reorderNav = control.container.find( '.menu-item-reorder-nav' ); - $reorderNav.find( '.menus-move-up, .menus-move-down, .menus-move-left, .menus-move-right' ).on( 'click', function() { - var moveBtn = $( this ); - moveBtn.focus(); - - var isMoveUp = moveBtn.is( '.menus-move-up' ), - isMoveDown = moveBtn.is( '.menus-move-down' ), - isMoveLeft = moveBtn.is( '.menus-move-left' ), - isMoveRight = moveBtn.is( '.menus-move-right' ); - - if ( isMoveUp ) { - control.moveUp(); - } else if ( isMoveDown ) { - control.moveDown(); - } else if ( isMoveLeft ) { - control.moveLeft(); - } else if ( isMoveRight ) { - control.moveRight(); - } - - moveBtn.focus(); // Re-focus after the container was moved. - } ); - }, - - /** - * Set up event handlers for menu item updating. - */ - _setupUpdateUI: function() { - var control = this, - settingValue = control.setting(), - updateNotifications; - - control.elements = {}; - control.elements.url = new api.Element( control.container.find( '.edit-menu-item-url' ) ); - control.elements.title = new api.Element( control.container.find( '.edit-menu-item-title' ) ); - control.elements.attr_title = new api.Element( control.container.find( '.edit-menu-item-attr-title' ) ); - control.elements.target = new api.Element( control.container.find( '.edit-menu-item-target' ) ); - control.elements.classes = new api.Element( control.container.find( '.edit-menu-item-classes' ) ); - control.elements.xfn = new api.Element( control.container.find( '.edit-menu-item-xfn' ) ); - control.elements.description = new api.Element( control.container.find( '.edit-menu-item-description' ) ); - // @todo allow other elements, added by plugins, to be automatically picked up here; allow additional values to be added to setting array. - - _.each( control.elements, function( element, property ) { - element.bind(function( value ) { - if ( element.element.is( 'input[type=checkbox]' ) ) { - value = ( value ) ? element.element.val() : ''; - } - - var settingValue = control.setting(); - if ( settingValue && settingValue[ property ] !== value ) { - settingValue = _.clone( settingValue ); - settingValue[ property ] = value; - control.setting.set( settingValue ); - } - }); - if ( settingValue ) { - if ( ( property === 'classes' || property === 'xfn' ) && _.isArray( settingValue[ property ] ) ) { - element.set( settingValue[ property ].join( ' ' ) ); - } else { - element.set( settingValue[ property ] ); - } - } - }); - - control.setting.bind(function( to, from ) { - var itemId = control.params.menu_item_id, - followingSiblingItemControls = [], - childrenItemControls = [], - menuControl; - - if ( false === to ) { - menuControl = api.control( 'nav_menu[' + String( from.nav_menu_term_id ) + ']' ); - control.container.remove(); - - _.each( menuControl.getMenuItemControls(), function( otherControl ) { - if ( from.menu_item_parent === otherControl.setting().menu_item_parent && otherControl.setting().position > from.position ) { - followingSiblingItemControls.push( otherControl ); - } else if ( otherControl.setting().menu_item_parent === itemId ) { - childrenItemControls.push( otherControl ); - } - }); - - // Shift all following siblings by the number of children this item has. - _.each( followingSiblingItemControls, function( followingSiblingItemControl ) { - var value = _.clone( followingSiblingItemControl.setting() ); - value.position += childrenItemControls.length; - followingSiblingItemControl.setting.set( value ); - }); - - // Now move the children up to be the new subsequent siblings. - _.each( childrenItemControls, function( childrenItemControl, i ) { - var value = _.clone( childrenItemControl.setting() ); - value.position = from.position + i; - value.menu_item_parent = from.menu_item_parent; - childrenItemControl.setting.set( value ); - }); - - menuControl.debouncedReflowMenuItems(); - } else { - // Update the elements' values to match the new setting properties. - _.each( to, function( value, key ) { - if ( control.elements[ key] ) { - control.elements[ key ].set( to[ key ] ); - } - } ); - control.container.find( '.menu-item-data-parent-id' ).val( to.menu_item_parent ); - - // Handle UI updates when the position or depth (parent) change. - if ( to.position !== from.position || to.menu_item_parent !== from.menu_item_parent ) { - control.getMenuControl().debouncedReflowMenuItems(); - } - } - }); - - // Style the URL field as invalid when there is an invalid_url notification. - updateNotifications = function() { - control.elements.url.element.toggleClass( 'invalid', control.setting.notifications.has( 'invalid_url' ) ); - }; - control.setting.notifications.bind( 'add', updateNotifications ); - control.setting.notifications.bind( 'removed', updateNotifications ); - }, - - /** - * Set up event handlers for menu item deletion. - */ - _setupRemoveUI: function() { - var control = this, $removeBtn; - - // Configure delete button. - $removeBtn = control.container.find( '.item-delete' ); - - $removeBtn.on( 'click', function() { - // Find an adjacent element to add focus to when this menu item goes away - var addingItems = true, $adjacentFocusTarget, $next, $prev; - - if ( ! $( 'body' ).hasClass( 'adding-menu-items' ) ) { - addingItems = false; - } - - $next = control.container.nextAll( '.customize-control-nav_menu_item:visible' ).first(); - $prev = control.container.prevAll( '.customize-control-nav_menu_item:visible' ).first(); - - if ( $next.length ) { - $adjacentFocusTarget = $next.find( false === addingItems ? '.item-edit' : '.item-delete' ).first(); - } else if ( $prev.length ) { - $adjacentFocusTarget = $prev.find( false === addingItems ? '.item-edit' : '.item-delete' ).first(); - } else { - $adjacentFocusTarget = control.container.nextAll( '.customize-control-nav_menu' ).find( '.add-new-menu-item' ).first(); - } - - control.container.slideUp( function() { - control.setting.set( false ); - wp.a11y.speak( api.Menus.data.l10n.itemDeleted ); - $adjacentFocusTarget.focus(); // keyboard accessibility - } ); - - control.setting.set( false ); - } ); - }, - - _setupLinksUI: function() { - var $origBtn; - - // Configure original link. - $origBtn = this.container.find( 'a.original-link' ); - - $origBtn.on( 'click', function( e ) { - e.preventDefault(); - api.previewer.previewUrl( e.target.toString() ); - } ); - }, - - /** - * Update item handle title when changed. - */ - _setupTitleUI: function() { - var control = this, titleEl; - - // Ensure that whitespace is trimmed on blur so placeholder can be shown. - control.container.find( '.edit-menu-item-title' ).on( 'blur', function() { - $( this ).val( $.trim( $( this ).val() ) ); - } ); - - titleEl = control.container.find( '.menu-item-title' ); - control.setting.bind( function( item ) { - var trimmedTitle, titleText; - if ( ! item ) { - return; - } - trimmedTitle = $.trim( item.title ); - - titleText = trimmedTitle || item.original_title || api.Menus.data.l10n.untitled; - - if ( item._invalid ) { - titleText = api.Menus.data.l10n.invalidTitleTpl.replace( '%s', titleText ); - } - - // Don't update to an empty title. - if ( trimmedTitle || item.original_title ) { - titleEl - .text( titleText ) - .removeClass( 'no-title' ); - } else { - titleEl - .text( titleText ) - .addClass( 'no-title' ); - } - } ); - }, - - /** - * - * @returns {number} - */ - getDepth: function() { - var control = this, setting = control.setting(), depth = 0; - if ( ! setting ) { - return 0; - } - while ( setting && setting.menu_item_parent ) { - depth += 1; - control = api.control( 'nav_menu_item[' + setting.menu_item_parent + ']' ); - if ( ! control ) { - break; - } - setting = control.setting(); - } - return depth; - }, - - /** - * Amend the control's params with the data necessary for the JS template just in time. - */ - renderContent: function() { - var control = this, - settingValue = control.setting(), - containerClasses; - - control.params.title = settingValue.title || ''; - control.params.depth = control.getDepth(); - control.container.data( 'item-depth', control.params.depth ); - containerClasses = [ - 'menu-item', - 'menu-item-depth-' + String( control.params.depth ), - 'menu-item-' + settingValue.object, - 'menu-item-edit-inactive' - ]; - - if ( settingValue._invalid ) { - containerClasses.push( 'menu-item-invalid' ); - control.params.title = api.Menus.data.l10n.invalidTitleTpl.replace( '%s', control.params.title ); - } else if ( 'draft' === settingValue.status ) { - containerClasses.push( 'pending' ); - control.params.title = api.Menus.data.pendingTitleTpl.replace( '%s', control.params.title ); - } - - control.params.el_classes = containerClasses.join( ' ' ); - control.params.item_type_label = settingValue.type_label; - control.params.item_type = settingValue.type; - control.params.url = settingValue.url; - control.params.target = settingValue.target; - control.params.attr_title = settingValue.attr_title; - control.params.classes = _.isArray( settingValue.classes ) ? settingValue.classes.join( ' ' ) : settingValue.classes; - control.params.xfn = settingValue.xfn; - control.params.description = settingValue.description; - control.params.parent = settingValue.menu_item_parent; - control.params.original_title = settingValue.original_title || ''; - - control.container.addClass( control.params.el_classes ); - - api.Control.prototype.renderContent.call( control ); - }, - - /*********************************************************************** - * Begin public API methods - **********************************************************************/ - - /** - * @return {wp.customize.controlConstructor.nav_menu|null} - */ - getMenuControl: function() { - var control = this, settingValue = control.setting(); - if ( settingValue && settingValue.nav_menu_term_id ) { - return api.control( 'nav_menu[' + settingValue.nav_menu_term_id + ']' ); - } else { - return null; - } - }, - - /** - * Expand the accordion section containing a control - */ - expandControlSection: function() { - var $section = this.container.closest( '.accordion-section' ); - if ( ! $section.hasClass( 'open' ) ) { - $section.find( '.accordion-section-title:first' ).trigger( 'click' ); - } - }, - - /** - * @since 4.6.0 - * - * @param {Boolean} expanded - * @param {Object} [params] - * @returns {Boolean} false if state already applied - */ - _toggleExpanded: api.Section.prototype._toggleExpanded, - - /** - * @since 4.6.0 - * - * @param {Object} [params] - * @returns {Boolean} false if already expanded - */ - expand: api.Section.prototype.expand, - - /** - * Expand the menu item form control. - * - * @since 4.5.0 Added params.completeCallback. - * - * @param {Object} [params] - Optional params. - * @param {Function} [params.completeCallback] - Function to call when the form toggle has finished animating. - */ - expandForm: function( params ) { - this.expand( params ); - }, - - /** - * @since 4.6.0 - * - * @param {Object} [params] - * @returns {Boolean} false if already collapsed - */ - collapse: api.Section.prototype.collapse, - - /** - * Collapse the menu item form control. - * - * @since 4.5.0 Added params.completeCallback. - * - * @param {Object} [params] - Optional params. - * @param {Function} [params.completeCallback] - Function to call when the form toggle has finished animating. - */ - collapseForm: function( params ) { - this.collapse( params ); - }, - - /** - * Expand or collapse the menu item control. - * - * @deprecated this is poor naming, and it is better to directly set control.expanded( showOrHide ) - * @since 4.5.0 Added params.completeCallback. - * - * @param {boolean} [showOrHide] - If not supplied, will be inverse of current visibility - * @param {Object} [params] - Optional params. - * @param {Function} [params.completeCallback] - Function to call when the form toggle has finished animating. - */ - toggleForm: function( showOrHide, params ) { - if ( typeof showOrHide === 'undefined' ) { - showOrHide = ! this.expanded(); - } - if ( showOrHide ) { - this.expand( params ); - } else { - this.collapse( params ); - } - }, - - /** - * Expand or collapse the menu item control. - * - * @since 4.6.0 - * @param {boolean} [showOrHide] - If not supplied, will be inverse of current visibility - * @param {Object} [params] - Optional params. - * @param {Function} [params.completeCallback] - Function to call when the form toggle has finished animating. - */ - onChangeExpanded: function( showOrHide, params ) { - var self = this, $menuitem, $inside, complete; - - $menuitem = this.container; - $inside = $menuitem.find( '.menu-item-settings:first' ); - if ( 'undefined' === typeof showOrHide ) { - showOrHide = ! $inside.is( ':visible' ); - } - - // Already expanded or collapsed. - if ( $inside.is( ':visible' ) === showOrHide ) { - if ( params && params.completeCallback ) { - params.completeCallback(); - } - return; - } - - if ( showOrHide ) { - // Close all other menu item controls before expanding this one. - api.control.each( function( otherControl ) { - if ( self.params.type === otherControl.params.type && self !== otherControl ) { - otherControl.collapseForm(); - } - } ); - - complete = function() { - $menuitem - .removeClass( 'menu-item-edit-inactive' ) - .addClass( 'menu-item-edit-active' ); - self.container.trigger( 'expanded' ); - - if ( params && params.completeCallback ) { - params.completeCallback(); - } - }; - - $menuitem.find( '.item-edit' ).attr( 'aria-expanded', 'true' ); - $inside.slideDown( 'fast', complete ); - - self.container.trigger( 'expand' ); - } else { - complete = function() { - $menuitem - .addClass( 'menu-item-edit-inactive' ) - .removeClass( 'menu-item-edit-active' ); - self.container.trigger( 'collapsed' ); - - if ( params && params.completeCallback ) { - params.completeCallback(); - } - }; - - self.container.trigger( 'collapse' ); - - $menuitem.find( '.item-edit' ).attr( 'aria-expanded', 'false' ); - $inside.slideUp( 'fast', complete ); - } - }, - - /** - * Expand the containing menu section, expand the form, and focus on - * the first input in the control. - * - * @since 4.5.0 Added params.completeCallback. - * - * @param {Object} [params] - Params object. - * @param {Function} [params.completeCallback] - Optional callback function when focus has completed. - */ - focus: function( params ) { - params = params || {}; - var control = this, originalCompleteCallback = params.completeCallback, focusControl; - - focusControl = function() { - control.expandControlSection(); - - params.completeCallback = function() { - var focusable; - - // Note that we can't use :focusable due to a jQuery UI issue. See: https://github.com/jquery/jquery-ui/pull/1583 - focusable = control.container.find( '.menu-item-settings' ).find( 'input, select, textarea, button, object, a[href], [tabindex]' ).filter( ':visible' ); - focusable.first().focus(); - - if ( originalCompleteCallback ) { - originalCompleteCallback(); - } - }; - - control.expandForm( params ); - }; - - if ( api.section.has( control.section() ) ) { - api.section( control.section() ).expand( { - completeCallback: focusControl - } ); - } else { - focusControl(); - } - }, - - /** - * Move menu item up one in the menu. - */ - moveUp: function() { - this._changePosition( -1 ); - wp.a11y.speak( api.Menus.data.l10n.movedUp ); - }, - - /** - * Move menu item up one in the menu. - */ - moveDown: function() { - this._changePosition( 1 ); - wp.a11y.speak( api.Menus.data.l10n.movedDown ); - }, - /** - * Move menu item and all children up one level of depth. - */ - moveLeft: function() { - this._changeDepth( -1 ); - wp.a11y.speak( api.Menus.data.l10n.movedLeft ); - }, - - /** - * Move menu item and children one level deeper, as a submenu of the previous item. - */ - moveRight: function() { - this._changeDepth( 1 ); - wp.a11y.speak( api.Menus.data.l10n.movedRight ); - }, - - /** - * Note that this will trigger a UI update, causing child items to - * move as well and cardinal order class names to be updated. - * - * @private - * - * @param {Number} offset 1|-1 - */ - _changePosition: function( offset ) { - var control = this, - adjacentSetting, - settingValue = _.clone( control.setting() ), - siblingSettings = [], - realPosition; - - if ( 1 !== offset && -1 !== offset ) { - throw new Error( 'Offset changes by 1 are only supported.' ); - } - - // Skip moving deleted items. - if ( ! control.setting() ) { - return; - } - - // Locate the other items under the same parent (siblings). - _( control.getMenuControl().getMenuItemControls() ).each(function( otherControl ) { - if ( otherControl.setting().menu_item_parent === settingValue.menu_item_parent ) { - siblingSettings.push( otherControl.setting ); - } - }); - siblingSettings.sort(function( a, b ) { - return a().position - b().position; - }); - - realPosition = _.indexOf( siblingSettings, control.setting ); - if ( -1 === realPosition ) { - throw new Error( 'Expected setting to be among siblings.' ); - } - - // Skip doing anything if the item is already at the edge in the desired direction. - if ( ( realPosition === 0 && offset < 0 ) || ( realPosition === siblingSettings.length - 1 && offset > 0 ) ) { - // @todo Should we allow a menu item to be moved up to break it out of a parent? Adopt with previous or following parent? - return; - } - - // Update any adjacent menu item setting to take on this item's position. - adjacentSetting = siblingSettings[ realPosition + offset ]; - if ( adjacentSetting ) { - adjacentSetting.set( $.extend( - _.clone( adjacentSetting() ), - { - position: settingValue.position - } - ) ); - } - - settingValue.position += offset; - control.setting.set( settingValue ); - }, - - /** - * Note that this will trigger a UI update, causing child items to - * move as well and cardinal order class names to be updated. - * - * @private - * - * @param {Number} offset 1|-1 - */ - _changeDepth: function( offset ) { - if ( 1 !== offset && -1 !== offset ) { - throw new Error( 'Offset changes by 1 are only supported.' ); - } - var control = this, - settingValue = _.clone( control.setting() ), - siblingControls = [], - realPosition, - siblingControl, - parentControl; - - // Locate the other items under the same parent (siblings). - _( control.getMenuControl().getMenuItemControls() ).each(function( otherControl ) { - if ( otherControl.setting().menu_item_parent === settingValue.menu_item_parent ) { - siblingControls.push( otherControl ); - } - }); - siblingControls.sort(function( a, b ) { - return a.setting().position - b.setting().position; - }); - - realPosition = _.indexOf( siblingControls, control ); - if ( -1 === realPosition ) { - throw new Error( 'Expected control to be among siblings.' ); - } - - if ( -1 === offset ) { - // Skip moving left an item that is already at the top level. - if ( ! settingValue.menu_item_parent ) { - return; - } - - parentControl = api.control( 'nav_menu_item[' + settingValue.menu_item_parent + ']' ); - - // Make this control the parent of all the following siblings. - _( siblingControls ).chain().slice( realPosition ).each(function( siblingControl, i ) { - siblingControl.setting.set( - $.extend( - {}, - siblingControl.setting(), - { - menu_item_parent: control.params.menu_item_id, - position: i - } - ) - ); - }); - - // Increase the positions of the parent item's subsequent children to make room for this one. - _( control.getMenuControl().getMenuItemControls() ).each(function( otherControl ) { - var otherControlSettingValue, isControlToBeShifted; - isControlToBeShifted = ( - otherControl.setting().menu_item_parent === parentControl.setting().menu_item_parent && - otherControl.setting().position > parentControl.setting().position - ); - if ( isControlToBeShifted ) { - otherControlSettingValue = _.clone( otherControl.setting() ); - otherControl.setting.set( - $.extend( - otherControlSettingValue, - { position: otherControlSettingValue.position + 1 } - ) - ); - } - }); - - // Make this control the following sibling of its parent item. - settingValue.position = parentControl.setting().position + 1; - settingValue.menu_item_parent = parentControl.setting().menu_item_parent; - control.setting.set( settingValue ); - - } else if ( 1 === offset ) { - // Skip moving right an item that doesn't have a previous sibling. - if ( realPosition === 0 ) { - return; - } - - // Make the control the last child of the previous sibling. - siblingControl = siblingControls[ realPosition - 1 ]; - settingValue.menu_item_parent = siblingControl.params.menu_item_id; - settingValue.position = 0; - _( control.getMenuControl().getMenuItemControls() ).each(function( otherControl ) { - if ( otherControl.setting().menu_item_parent === settingValue.menu_item_parent ) { - settingValue.position = Math.max( settingValue.position, otherControl.setting().position ); - } - }); - settingValue.position += 1; - control.setting.set( settingValue ); - } - } - } ); - - /** - * wp.customize.Menus.MenuNameControl - * - * Customizer control for a nav menu's name. - * - * @class wp.customize.Menus.MenuNameControl - * @augments wp.customize.Control - */ - api.Menus.MenuNameControl = api.Control.extend(/** @lends wp.customize.Menus.MenuNameControl.prototype */{ - - ready: function() { - var control = this; - - if ( control.setting ) { - var settingValue = control.setting(); - - control.nameElement = new api.Element( control.container.find( '.menu-name-field' ) ); - - control.nameElement.bind(function( value ) { - var settingValue = control.setting(); - if ( settingValue && settingValue.name !== value ) { - settingValue = _.clone( settingValue ); - settingValue.name = value; - control.setting.set( settingValue ); - } - }); - if ( settingValue ) { - control.nameElement.set( settingValue.name ); - } - - control.setting.bind(function( object ) { - if ( object ) { - control.nameElement.set( object.name ); - } - }); - } - } - }); - - /** - * wp.customize.Menus.MenuLocationsControl - * - * Customizer control for a nav menu's locations. - * - * @since 4.9.0 - * @class wp.customize.Menus.MenuLocationsControl - * @augments wp.customize.Control - */ - api.Menus.MenuLocationsControl = api.Control.extend(/** @lends wp.customize.Menus.MenuLocationsControl.prototype */{ - - /** - * Set up the control. - * - * @since 4.9.0 - */ - ready: function () { - var control = this; - - control.container.find( '.assigned-menu-location' ).each(function() { - var container = $( this ), - checkbox = container.find( 'input[type=checkbox]' ), - element = new api.Element( checkbox ), - navMenuLocationSetting = api( 'nav_menu_locations[' + checkbox.data( 'location-id' ) + ']' ), - isNewMenu = control.params.menu_id === '', - updateCheckbox = isNewMenu ? _.noop : function( checked ) { - element.set( checked ); - }, - updateSetting = isNewMenu ? _.noop : function( checked ) { - navMenuLocationSetting.set( checked ? control.params.menu_id : 0 ); - }, - updateSelectedMenuLabel = function( selectedMenuId ) { - var menuSetting = api( 'nav_menu[' + String( selectedMenuId ) + ']' ); - if ( ! selectedMenuId || ! menuSetting || ! menuSetting() ) { - container.find( '.theme-location-set' ).hide(); - } else { - container.find( '.theme-location-set' ).show().find( 'span' ).text( displayNavMenuName( menuSetting().name ) ); - } - }; - - updateCheckbox( navMenuLocationSetting.get() === control.params.menu_id ); - - checkbox.on( 'change', function() { - // Note: We can't use element.bind( function( checked ){ ... } ) here because it will trigger a change as well. - updateSetting( this.checked ); - } ); - - navMenuLocationSetting.bind( function( selectedMenuId ) { - updateCheckbox( selectedMenuId === control.params.menu_id ); - updateSelectedMenuLabel( selectedMenuId ); - } ); - updateSelectedMenuLabel( navMenuLocationSetting.get() ); - }); - }, - - /** - * Set the selected locations. - * - * This method sets the selected locations and allows us to do things like - * set the default location for a new menu. - * - * @since 4.9.0 - * - * @param {Object.<string,boolean>} selections - A map of location selections. - * @returns {void} - */ - setSelections: function( selections ) { - this.container.find( '.menu-location' ).each( function( i, checkboxNode ) { - var locationId = checkboxNode.dataset.locationId; - checkboxNode.checked = locationId in selections ? selections[ locationId ] : false; - } ); - } - }); - - /** - * wp.customize.Menus.MenuAutoAddControl - * - * Customizer control for a nav menu's auto add. - * - * @class wp.customize.Menus.MenuAutoAddControl - * @augments wp.customize.Control - */ - api.Menus.MenuAutoAddControl = api.Control.extend(/** @lends wp.customize.Menus.MenuAutoAddControl.prototype */{ - - ready: function() { - var control = this, - settingValue = control.setting(); - - /* - * Since the control is not registered in PHP, we need to prevent the - * preview's sending of the activeControls to result in this control - * being deactivated. - */ - control.active.validate = function() { - var value, section = api.section( control.section() ); - if ( section ) { - value = section.active(); - } else { - value = false; - } - return value; - }; - - control.autoAddElement = new api.Element( control.container.find( 'input[type=checkbox].auto_add' ) ); - - control.autoAddElement.bind(function( value ) { - var settingValue = control.setting(); - if ( settingValue && settingValue.name !== value ) { - settingValue = _.clone( settingValue ); - settingValue.auto_add = value; - control.setting.set( settingValue ); - } - }); - if ( settingValue ) { - control.autoAddElement.set( settingValue.auto_add ); - } - - control.setting.bind(function( object ) { - if ( object ) { - control.autoAddElement.set( object.auto_add ); - } - }); - } - - }); - - /** - * wp.customize.Menus.MenuControl - * - * Customizer control for menus. - * Note that 'nav_menu' must match the WP_Menu_Customize_Control::$type - * - * @class wp.customize.Menus.MenuControl - * @augments wp.customize.Control - */ - api.Menus.MenuControl = api.Control.extend(/** @lends wp.customize.Menus.MenuControl.prototype */{ - /** - * Set up the control. - */ - ready: function() { - var control = this, - section = api.section( control.section() ), - menuId = control.params.menu_id, - menu = control.setting(), - name, - widgetTemplate, - select; - - if ( 'undefined' === typeof this.params.menu_id ) { - throw new Error( 'params.menu_id was not defined' ); - } - - /* - * Since the control is not registered in PHP, we need to prevent the - * preview's sending of the activeControls to result in this control - * being deactivated. - */ - control.active.validate = function() { - var value; - if ( section ) { - value = section.active(); - } else { - value = false; - } - return value; - }; - - control.$controlSection = section.headContainer; - control.$sectionContent = control.container.closest( '.accordion-section-content' ); - - this._setupModel(); - - api.section( control.section(), function( section ) { - section.deferred.initSortables.done(function( menuList ) { - control._setupSortable( menuList ); - }); - } ); - - this._setupAddition(); - this._setupTitle(); - - // Add menu to Navigation Menu widgets. - if ( menu ) { - name = displayNavMenuName( menu.name ); - - // Add the menu to the existing controls. - api.control.each( function( widgetControl ) { - if ( ! widgetControl.extended( api.controlConstructor.widget_form ) || 'nav_menu' !== widgetControl.params.widget_id_base ) { - return; - } - widgetControl.container.find( '.nav-menu-widget-form-controls:first' ).show(); - widgetControl.container.find( '.nav-menu-widget-no-menus-message:first' ).hide(); - - select = widgetControl.container.find( 'select' ); - if ( 0 === select.find( 'option[value=' + String( menuId ) + ']' ).length ) { - select.append( new Option( name, menuId ) ); - } - } ); - - // Add the menu to the widget template. - widgetTemplate = $( '#available-widgets-list .widget-tpl:has( input.id_base[ value=nav_menu ] )' ); - widgetTemplate.find( '.nav-menu-widget-form-controls:first' ).show(); - widgetTemplate.find( '.nav-menu-widget-no-menus-message:first' ).hide(); - select = widgetTemplate.find( '.widget-inside select:first' ); - if ( 0 === select.find( 'option[value=' + String( menuId ) + ']' ).length ) { - select.append( new Option( name, menuId ) ); - } - } - - /* - * Wait for menu items to be added. - * Ideally, we'd bind to an event indicating construction is complete, - * but deferring appears to be the best option today. - */ - _.defer( function () { - control.updateInvitationVisibility(); - } ); - }, - - /** - * Update ordering of menu item controls when the setting is updated. - */ - _setupModel: function() { - var control = this, - menuId = control.params.menu_id; - - control.setting.bind( function( to ) { - var name; - if ( false === to ) { - control._handleDeletion(); - } else { - // Update names in the Navigation Menu widgets. - name = displayNavMenuName( to.name ); - api.control.each( function( widgetControl ) { - if ( ! widgetControl.extended( api.controlConstructor.widget_form ) || 'nav_menu' !== widgetControl.params.widget_id_base ) { - return; - } - var select = widgetControl.container.find( 'select' ); - select.find( 'option[value=' + String( menuId ) + ']' ).text( name ); - }); - } - } ); - }, - - /** - * Allow items in each menu to be re-ordered, and for the order to be previewed. - * - * Notice that the UI aspects here are handled by wpNavMenu.initSortables() - * which is called in MenuSection.onChangeExpanded() - * - * @param {object} menuList - The element that has sortable(). - */ - _setupSortable: function( menuList ) { - var control = this; - - if ( ! menuList.is( control.$sectionContent ) ) { - throw new Error( 'Unexpected menuList.' ); - } - - menuList.on( 'sortstart', function() { - control.isSorting = true; - }); - - menuList.on( 'sortstop', function() { - setTimeout( function() { // Next tick. - var menuItemContainerIds = control.$sectionContent.sortable( 'toArray' ), - menuItemControls = [], - position = 0, - priority = 10; - - control.isSorting = false; - - // Reset horizontal scroll position when done dragging. - control.$sectionContent.scrollLeft( 0 ); - - _.each( menuItemContainerIds, function( menuItemContainerId ) { - var menuItemId, menuItemControl, matches; - matches = menuItemContainerId.match( /^customize-control-nav_menu_item-(-?\d+)$/, '' ); - if ( ! matches ) { - return; - } - menuItemId = parseInt( matches[1], 10 ); - menuItemControl = api.control( 'nav_menu_item[' + String( menuItemId ) + ']' ); - if ( menuItemControl ) { - menuItemControls.push( menuItemControl ); - } - } ); - - _.each( menuItemControls, function( menuItemControl ) { - if ( false === menuItemControl.setting() ) { - // Skip deleted items. - return; - } - var setting = _.clone( menuItemControl.setting() ); - position += 1; - priority += 1; - setting.position = position; - menuItemControl.priority( priority ); - - // Note that wpNavMenu will be setting this .menu-item-data-parent-id input's value. - setting.menu_item_parent = parseInt( menuItemControl.container.find( '.menu-item-data-parent-id' ).val(), 10 ); - if ( ! setting.menu_item_parent ) { - setting.menu_item_parent = 0; - } - - menuItemControl.setting.set( setting ); - }); - }); - - }); - control.isReordering = false; - - /** - * Keyboard-accessible reordering. - */ - this.container.find( '.reorder-toggle' ).on( 'click', function() { - control.toggleReordering( ! control.isReordering ); - } ); - }, - - /** - * Set up UI for adding a new menu item. - */ - _setupAddition: function() { - var self = this; - - this.container.find( '.add-new-menu-item' ).on( 'click', function( event ) { - if ( self.$sectionContent.hasClass( 'reordering' ) ) { - return; - } - - if ( ! $( 'body' ).hasClass( 'adding-menu-items' ) ) { - $( this ).attr( 'aria-expanded', 'true' ); - api.Menus.availableMenuItemsPanel.open( self ); - } else { - $( this ).attr( 'aria-expanded', 'false' ); - api.Menus.availableMenuItemsPanel.close(); - event.stopPropagation(); - } - } ); - }, - - _handleDeletion: function() { - var control = this, - section, - menuId = control.params.menu_id, - removeSection, - widgetTemplate, - navMenuCount = 0; - section = api.section( control.section() ); - removeSection = function() { - section.container.remove(); - api.section.remove( section.id ); - }; - - if ( section && section.expanded() ) { - section.collapse({ - completeCallback: function() { - removeSection(); - wp.a11y.speak( api.Menus.data.l10n.menuDeleted ); - api.panel( 'nav_menus' ).focus(); - } - }); - } else { - removeSection(); - } - - api.each(function( setting ) { - if ( /^nav_menu\[/.test( setting.id ) && false !== setting() ) { - navMenuCount += 1; - } - }); - - // Remove the menu from any Navigation Menu widgets. - api.control.each(function( widgetControl ) { - if ( ! widgetControl.extended( api.controlConstructor.widget_form ) || 'nav_menu' !== widgetControl.params.widget_id_base ) { - return; - } - var select = widgetControl.container.find( 'select' ); - if ( select.val() === String( menuId ) ) { - select.prop( 'selectedIndex', 0 ).trigger( 'change' ); - } - - widgetControl.container.find( '.nav-menu-widget-form-controls:first' ).toggle( 0 !== navMenuCount ); - widgetControl.container.find( '.nav-menu-widget-no-menus-message:first' ).toggle( 0 === navMenuCount ); - widgetControl.container.find( 'option[value=' + String( menuId ) + ']' ).remove(); - }); - - // Remove the menu to the nav menu widget template. - widgetTemplate = $( '#available-widgets-list .widget-tpl:has( input.id_base[ value=nav_menu ] )' ); - widgetTemplate.find( '.nav-menu-widget-form-controls:first' ).toggle( 0 !== navMenuCount ); - widgetTemplate.find( '.nav-menu-widget-no-menus-message:first' ).toggle( 0 === navMenuCount ); - widgetTemplate.find( 'option[value=' + String( menuId ) + ']' ).remove(); - }, - - /** - * Update Section Title as menu name is changed. - */ - _setupTitle: function() { - var control = this; - - control.setting.bind( function( menu ) { - if ( ! menu ) { - return; - } - - var section = api.section( control.section() ), - menuId = control.params.menu_id, - controlTitle = section.headContainer.find( '.accordion-section-title' ), - sectionTitle = section.contentContainer.find( '.customize-section-title h3' ), - location = section.headContainer.find( '.menu-in-location' ), - action = sectionTitle.find( '.customize-action' ), - name = displayNavMenuName( menu.name ); - - // Update the control title - controlTitle.text( name ); - if ( location.length ) { - location.appendTo( controlTitle ); - } - - // Update the section title - sectionTitle.text( name ); - if ( action.length ) { - action.prependTo( sectionTitle ); - } - - // Update the nav menu name in location selects. - api.control.each( function( control ) { - if ( /^nav_menu_locations\[/.test( control.id ) ) { - control.container.find( 'option[value=' + menuId + ']' ).text( name ); - } - } ); - - // Update the nav menu name in all location checkboxes. - section.contentContainer.find( '.customize-control-checkbox input' ).each( function() { - if ( $( this ).prop( 'checked' ) ) { - $( '.current-menu-location-name-' + $( this ).data( 'location-id' ) ).text( name ); - } - } ); - } ); - }, - - /*********************************************************************** - * Begin public API methods - **********************************************************************/ - - /** - * Enable/disable the reordering UI - * - * @param {Boolean} showOrHide to enable/disable reordering - */ - toggleReordering: function( showOrHide ) { - var addNewItemBtn = this.container.find( '.add-new-menu-item' ), - reorderBtn = this.container.find( '.reorder-toggle' ), - itemsTitle = this.$sectionContent.find( '.item-title' ); - - showOrHide = Boolean( showOrHide ); - - if ( showOrHide === this.$sectionContent.hasClass( 'reordering' ) ) { - return; - } - - this.isReordering = showOrHide; - this.$sectionContent.toggleClass( 'reordering', showOrHide ); - this.$sectionContent.sortable( this.isReordering ? 'disable' : 'enable' ); - if ( this.isReordering ) { - addNewItemBtn.attr({ 'tabindex': '-1', 'aria-hidden': 'true' }); - reorderBtn.attr( 'aria-label', api.Menus.data.l10n.reorderLabelOff ); - wp.a11y.speak( api.Menus.data.l10n.reorderModeOn ); - itemsTitle.attr( 'aria-hidden', 'false' ); - } else { - addNewItemBtn.removeAttr( 'tabindex aria-hidden' ); - reorderBtn.attr( 'aria-label', api.Menus.data.l10n.reorderLabelOn ); - wp.a11y.speak( api.Menus.data.l10n.reorderModeOff ); - itemsTitle.attr( 'aria-hidden', 'true' ); - } - - if ( showOrHide ) { - _( this.getMenuItemControls() ).each( function( formControl ) { - formControl.collapseForm(); - } ); - } - }, - - /** - * @return {wp.customize.controlConstructor.nav_menu_item[]} - */ - getMenuItemControls: function() { - var menuControl = this, - menuItemControls = [], - menuTermId = menuControl.params.menu_id; - - api.control.each(function( control ) { - if ( 'nav_menu_item' === control.params.type && control.setting() && menuTermId === control.setting().nav_menu_term_id ) { - menuItemControls.push( control ); - } - }); - - return menuItemControls; - }, - - /** - * Make sure that each menu item control has the proper depth. - */ - reflowMenuItems: function() { - var menuControl = this, - menuItemControls = menuControl.getMenuItemControls(), - reflowRecursively; - - reflowRecursively = function( context ) { - var currentMenuItemControls = [], - thisParent = context.currentParent; - _.each( context.menuItemControls, function( menuItemControl ) { - if ( thisParent === menuItemControl.setting().menu_item_parent ) { - currentMenuItemControls.push( menuItemControl ); - // @todo We could remove this item from menuItemControls now, for efficiency. - } - }); - currentMenuItemControls.sort( function( a, b ) { - return a.setting().position - b.setting().position; - }); - - _.each( currentMenuItemControls, function( menuItemControl ) { - // Update position. - context.currentAbsolutePosition += 1; - menuItemControl.priority.set( context.currentAbsolutePosition ); // This will change the sort order. - - // Update depth. - if ( ! menuItemControl.container.hasClass( 'menu-item-depth-' + String( context.currentDepth ) ) ) { - _.each( menuItemControl.container.prop( 'className' ).match( /menu-item-depth-\d+/g ), function( className ) { - menuItemControl.container.removeClass( className ); - }); - menuItemControl.container.addClass( 'menu-item-depth-' + String( context.currentDepth ) ); - } - menuItemControl.container.data( 'item-depth', context.currentDepth ); - - // Process any children items. - context.currentDepth += 1; - context.currentParent = menuItemControl.params.menu_item_id; - reflowRecursively( context ); - context.currentDepth -= 1; - context.currentParent = thisParent; - }); - - // Update class names for reordering controls. - if ( currentMenuItemControls.length ) { - _( currentMenuItemControls ).each(function( menuItemControl ) { - menuItemControl.container.removeClass( 'move-up-disabled move-down-disabled move-left-disabled move-right-disabled' ); - if ( 0 === context.currentDepth ) { - menuItemControl.container.addClass( 'move-left-disabled' ); - } else if ( 10 === context.currentDepth ) { - menuItemControl.container.addClass( 'move-right-disabled' ); - } - }); - - currentMenuItemControls[0].container - .addClass( 'move-up-disabled' ) - .addClass( 'move-right-disabled' ) - .toggleClass( 'move-down-disabled', 1 === currentMenuItemControls.length ); - currentMenuItemControls[ currentMenuItemControls.length - 1 ].container - .addClass( 'move-down-disabled' ) - .toggleClass( 'move-up-disabled', 1 === currentMenuItemControls.length ); - } - }; - - reflowRecursively( { - menuItemControls: menuItemControls, - currentParent: 0, - currentDepth: 0, - currentAbsolutePosition: 0 - } ); - - menuControl.updateInvitationVisibility( menuItemControls ); - menuControl.container.find( '.reorder-toggle' ).toggle( menuItemControls.length > 1 ); - }, - - /** - * Note that this function gets debounced so that when a lot of setting - * changes are made at once, for instance when moving a menu item that - * has child items, this function will only be called once all of the - * settings have been updated. - */ - debouncedReflowMenuItems: _.debounce( function() { - this.reflowMenuItems.apply( this, arguments ); - }, 0 ), - - /** - * Add a new item to this menu. - * - * @param {object} item - Value for the nav_menu_item setting to be created. - * @returns {wp.customize.Menus.controlConstructor.nav_menu_item} The newly-created nav_menu_item control instance. - */ - addItemToMenu: function( item ) { - var menuControl = this, customizeId, settingArgs, setting, menuItemControl, placeholderId, position = 0, priority = 10; - - _.each( menuControl.getMenuItemControls(), function( control ) { - if ( false === control.setting() ) { - return; - } - priority = Math.max( priority, control.priority() ); - if ( 0 === control.setting().menu_item_parent ) { - position = Math.max( position, control.setting().position ); - } - }); - position += 1; - priority += 1; - - item = $.extend( - {}, - api.Menus.data.defaultSettingValues.nav_menu_item, - item, - { - nav_menu_term_id: menuControl.params.menu_id, - original_title: item.title, - position: position - } - ); - delete item.id; // only used by Backbone - - placeholderId = api.Menus.generatePlaceholderAutoIncrementId(); - customizeId = 'nav_menu_item[' + String( placeholderId ) + ']'; - settingArgs = { - type: 'nav_menu_item', - transport: api.Menus.data.settingTransport, - previewer: api.previewer - }; - setting = api.create( customizeId, customizeId, {}, settingArgs ); - setting.set( item ); // Change from initial empty object to actual item to mark as dirty. - - // Add the menu item control. - menuItemControl = new api.controlConstructor.nav_menu_item( customizeId, { - type: 'nav_menu_item', - section: menuControl.id, - priority: priority, - settings: { - 'default': customizeId - }, - menu_item_id: placeholderId - } ); - - api.control.add( menuItemControl ); - setting.preview(); - menuControl.debouncedReflowMenuItems(); - - wp.a11y.speak( api.Menus.data.l10n.itemAdded ); - - return menuItemControl; - }, - - /** - * Show an invitation to add new menu items when there are no menu items. - * - * @since 4.9.0 - * - * @param {wp.customize.controlConstructor.nav_menu_item[]} optionalMenuItemControls - */ - updateInvitationVisibility: function ( optionalMenuItemControls ) { - var menuItemControls = optionalMenuItemControls || this.getMenuItemControls(); - - this.container.find( '.new-menu-item-invitation' ).toggle( menuItemControls.length === 0 ); - } - } ); - - api.Menus.NewMenuControl = api.Control.extend(/** @lends wp.customize.Menus.NewMenuControl.prototype */{ - - /** - * wp.customize.Menus.NewMenuControl - * - * Customizer control for creating new menus and handling deletion of existing menus. - * Note that 'new_menu' must match the WP_Customize_New_Menu_Control::$type. - * - * @constructs wp.customize.Menus.NewMenuControl - * @augments wp.customize.Control - * - * @deprecated 4.9.0 This class is no longer used due to new menu creation UX. - */ - initialize: function() { - if ( 'undefined' !== typeof console && console.warn ) { - console.warn( '[DEPRECATED] wp.customize.NewMenuControl will be removed. Please use wp.customize.Menus.createNavMenu() instead.' ); - } - api.Control.prototype.initialize.apply( this, arguments ); - }, - - /** - * Set up the control. - * - * @deprecated 4.9.0 - */ - ready: function() { - this._bindHandlers(); - }, - - _bindHandlers: function() { - var self = this, - name = $( '#customize-control-new_menu_name input' ), - submit = $( '#create-new-menu-submit' ); - name.on( 'keydown', function( event ) { - if ( 13 === event.which ) { // Enter. - self.submit(); - } - } ); - submit.on( 'click', function( event ) { - self.submit(); - event.stopPropagation(); - event.preventDefault(); - } ); - }, - - /** - * Create the new menu with the name supplied. - * - * @deprecated 4.9.0 - */ - submit: function() { - - var control = this, - container = control.container.closest( '.accordion-section-new-menu' ), - nameInput = container.find( '.menu-name-field' ).first(), - name = nameInput.val(), - menuSection; - - if ( ! name ) { - nameInput.addClass( 'invalid' ); - nameInput.focus(); - return; - } - - menuSection = api.Menus.createNavMenu( name ); - - // Clear name field. - nameInput.val( '' ); - nameInput.removeClass( 'invalid' ); - - wp.a11y.speak( api.Menus.data.l10n.menuAdded ); - - // Focus on the new menu section. - menuSection.focus(); - } - }); - - /** - * Extends wp.customize.controlConstructor with control constructor for - * menu_location, menu_item, nav_menu, and new_menu. - */ - $.extend( api.controlConstructor, { - nav_menu_location: api.Menus.MenuLocationControl, - nav_menu_item: api.Menus.MenuItemControl, - nav_menu: api.Menus.MenuControl, - nav_menu_name: api.Menus.MenuNameControl, - new_menu: api.Menus.NewMenuControl, // @todo Remove in a future release. See #42364. - nav_menu_locations: api.Menus.MenuLocationsControl, - nav_menu_auto_add: api.Menus.MenuAutoAddControl - }); - - /** - * Extends wp.customize.panelConstructor with section constructor for menus. - */ - $.extend( api.panelConstructor, { - nav_menus: api.Menus.MenusPanel - }); - - /** - * Extends wp.customize.sectionConstructor with section constructor for menu. - */ - $.extend( api.sectionConstructor, { - nav_menu: api.Menus.MenuSection, - new_menu: api.Menus.NewMenuSection - }); - - /** - * Init Customizer for menus. - */ - api.bind( 'ready', function() { - - // Set up the menu items panel. - api.Menus.availableMenuItemsPanel = new api.Menus.AvailableMenuItemsPanelView({ - collection: api.Menus.availableMenuItems - }); - - api.bind( 'saved', function( data ) { - if ( data.nav_menu_updates || data.nav_menu_item_updates ) { - api.Menus.applySavedData( data ); - } - } ); - - /* - * Reset the list of posts created in the customizer once published. - * The setting is updated quietly (bypassing events being triggered) - * so that the customized state doesn't become immediately dirty. - */ - api.state( 'changesetStatus' ).bind( function( status ) { - if ( 'publish' === status ) { - api( 'nav_menus_created_posts' )._value = []; - } - } ); - - // Open and focus menu control. - api.previewer.bind( 'focus-nav-menu-item-control', api.Menus.focusMenuItemControl ); - } ); - - /** - * When customize_save comes back with a success, make sure any inserted - * nav menus and items are properly re-added with their newly-assigned IDs. - * - * @alias wp.customize.Menus.applySavedData - * - * @param {object} data - * @param {array} data.nav_menu_updates - * @param {array} data.nav_menu_item_updates - */ - api.Menus.applySavedData = function( data ) { - - var insertedMenuIdMapping = {}, insertedMenuItemIdMapping = {}; - - _( data.nav_menu_updates ).each(function( update ) { - var oldCustomizeId, newCustomizeId, customizeId, oldSetting, newSetting, setting, settingValue, oldSection, newSection, wasSaved, widgetTemplate, navMenuCount, shouldExpandNewSection; - if ( 'inserted' === update.status ) { - if ( ! update.previous_term_id ) { - throw new Error( 'Expected previous_term_id' ); - } - if ( ! update.term_id ) { - throw new Error( 'Expected term_id' ); - } - oldCustomizeId = 'nav_menu[' + String( update.previous_term_id ) + ']'; - if ( ! api.has( oldCustomizeId ) ) { - throw new Error( 'Expected setting to exist: ' + oldCustomizeId ); - } - oldSetting = api( oldCustomizeId ); - if ( ! api.section.has( oldCustomizeId ) ) { - throw new Error( 'Expected control to exist: ' + oldCustomizeId ); - } - oldSection = api.section( oldCustomizeId ); - - settingValue = oldSetting.get(); - if ( ! settingValue ) { - throw new Error( 'Did not expect setting to be empty (deleted).' ); - } - settingValue = $.extend( _.clone( settingValue ), update.saved_value ); - - insertedMenuIdMapping[ update.previous_term_id ] = update.term_id; - newCustomizeId = 'nav_menu[' + String( update.term_id ) + ']'; - newSetting = api.create( newCustomizeId, newCustomizeId, settingValue, { - type: 'nav_menu', - transport: api.Menus.data.settingTransport, - previewer: api.previewer - } ); - - shouldExpandNewSection = oldSection.expanded(); - if ( shouldExpandNewSection ) { - oldSection.collapse(); - } - - // Add the menu section. - newSection = new api.Menus.MenuSection( newCustomizeId, { - panel: 'nav_menus', - title: settingValue.name, - customizeAction: api.Menus.data.l10n.customizingMenus, - type: 'nav_menu', - priority: oldSection.priority.get(), - menu_id: update.term_id - } ); - - // Add new control for the new menu. - api.section.add( newSection ); - - // Update the values for nav menus in Navigation Menu controls. - api.control.each( function( setting ) { - if ( ! setting.extended( api.controlConstructor.widget_form ) || 'nav_menu' !== setting.params.widget_id_base ) { - return; - } - var select, oldMenuOption, newMenuOption; - select = setting.container.find( 'select' ); - oldMenuOption = select.find( 'option[value=' + String( update.previous_term_id ) + ']' ); - newMenuOption = select.find( 'option[value=' + String( update.term_id ) + ']' ); - newMenuOption.prop( 'selected', oldMenuOption.prop( 'selected' ) ); - oldMenuOption.remove(); - } ); - - // Delete the old placeholder nav_menu. - oldSetting.callbacks.disable(); // Prevent setting triggering Customizer dirty state when set. - oldSetting.set( false ); - oldSetting.preview(); - newSetting.preview(); - oldSetting._dirty = false; - - // Remove nav_menu section. - oldSection.container.remove(); - api.section.remove( oldCustomizeId ); - - // Update the nav_menu widget to reflect removed placeholder menu. - navMenuCount = 0; - api.each(function( setting ) { - if ( /^nav_menu\[/.test( setting.id ) && false !== setting() ) { - navMenuCount += 1; - } - }); - widgetTemplate = $( '#available-widgets-list .widget-tpl:has( input.id_base[ value=nav_menu ] )' ); - widgetTemplate.find( '.nav-menu-widget-form-controls:first' ).toggle( 0 !== navMenuCount ); - widgetTemplate.find( '.nav-menu-widget-no-menus-message:first' ).toggle( 0 === navMenuCount ); - widgetTemplate.find( 'option[value=' + String( update.previous_term_id ) + ']' ).remove(); - - // Update the nav_menu_locations[...] controls to remove the placeholder menus from the dropdown options. - wp.customize.control.each(function( control ){ - if ( /^nav_menu_locations\[/.test( control.id ) ) { - control.container.find( 'option[value=' + String( update.previous_term_id ) + ']' ).remove(); - } - }); - - // Update nav_menu_locations to reference the new ID. - api.each( function( setting ) { - var wasSaved = api.state( 'saved' ).get(); - if ( /^nav_menu_locations\[/.test( setting.id ) && setting.get() === update.previous_term_id ) { - setting.set( update.term_id ); - setting._dirty = false; // Not dirty because this is has also just been done on server in WP_Customize_Nav_Menu_Setting::update(). - api.state( 'saved' ).set( wasSaved ); - setting.preview(); - } - } ); - - if ( shouldExpandNewSection ) { - newSection.expand(); - } - } else if ( 'updated' === update.status ) { - customizeId = 'nav_menu[' + String( update.term_id ) + ']'; - if ( ! api.has( customizeId ) ) { - throw new Error( 'Expected setting to exist: ' + customizeId ); - } - - // Make sure the setting gets updated with its sanitized server value (specifically the conflict-resolved name). - setting = api( customizeId ); - if ( ! _.isEqual( update.saved_value, setting.get() ) ) { - wasSaved = api.state( 'saved' ).get(); - setting.set( update.saved_value ); - setting._dirty = false; - api.state( 'saved' ).set( wasSaved ); - } - } - } ); - - // Build up mapping of nav_menu_item placeholder IDs to inserted IDs. - _( data.nav_menu_item_updates ).each(function( update ) { - if ( update.previous_post_id ) { - insertedMenuItemIdMapping[ update.previous_post_id ] = update.post_id; - } - }); - - _( data.nav_menu_item_updates ).each(function( update ) { - var oldCustomizeId, newCustomizeId, oldSetting, newSetting, settingValue, oldControl, newControl; - if ( 'inserted' === update.status ) { - if ( ! update.previous_post_id ) { - throw new Error( 'Expected previous_post_id' ); - } - if ( ! update.post_id ) { - throw new Error( 'Expected post_id' ); - } - oldCustomizeId = 'nav_menu_item[' + String( update.previous_post_id ) + ']'; - if ( ! api.has( oldCustomizeId ) ) { - throw new Error( 'Expected setting to exist: ' + oldCustomizeId ); - } - oldSetting = api( oldCustomizeId ); - if ( ! api.control.has( oldCustomizeId ) ) { - throw new Error( 'Expected control to exist: ' + oldCustomizeId ); - } - oldControl = api.control( oldCustomizeId ); - - settingValue = oldSetting.get(); - if ( ! settingValue ) { - throw new Error( 'Did not expect setting to be empty (deleted).' ); - } - settingValue = _.clone( settingValue ); - - // If the parent menu item was also inserted, update the menu_item_parent to the new ID. - if ( settingValue.menu_item_parent < 0 ) { - if ( ! insertedMenuItemIdMapping[ settingValue.menu_item_parent ] ) { - throw new Error( 'inserted ID for menu_item_parent not available' ); - } - settingValue.menu_item_parent = insertedMenuItemIdMapping[ settingValue.menu_item_parent ]; - } - - // If the menu was also inserted, then make sure it uses the new menu ID for nav_menu_term_id. - if ( insertedMenuIdMapping[ settingValue.nav_menu_term_id ] ) { - settingValue.nav_menu_term_id = insertedMenuIdMapping[ settingValue.nav_menu_term_id ]; - } - - newCustomizeId = 'nav_menu_item[' + String( update.post_id ) + ']'; - newSetting = api.create( newCustomizeId, newCustomizeId, settingValue, { - type: 'nav_menu_item', - transport: api.Menus.data.settingTransport, - previewer: api.previewer - } ); - - // Add the menu control. - newControl = new api.controlConstructor.nav_menu_item( newCustomizeId, { - type: 'nav_menu_item', - menu_id: update.post_id, - section: 'nav_menu[' + String( settingValue.nav_menu_term_id ) + ']', - priority: oldControl.priority.get(), - settings: { - 'default': newCustomizeId - }, - menu_item_id: update.post_id - } ); - - // Remove old control. - oldControl.container.remove(); - api.control.remove( oldCustomizeId ); - - // Add new control to take its place. - api.control.add( newControl ); - - // Delete the placeholder and preview the new setting. - oldSetting.callbacks.disable(); // Prevent setting triggering Customizer dirty state when set. - oldSetting.set( false ); - oldSetting.preview(); - newSetting.preview(); - oldSetting._dirty = false; - - newControl.container.toggleClass( 'menu-item-edit-inactive', oldControl.container.hasClass( 'menu-item-edit-inactive' ) ); - } - }); - - /* - * Update the settings for any nav_menu widgets that had selected a placeholder ID. - */ - _.each( data.widget_nav_menu_updates, function( widgetSettingValue, widgetSettingId ) { - var setting = api( widgetSettingId ); - if ( setting ) { - setting._value = widgetSettingValue; - setting.preview(); // Send to the preview now so that menu refresh will use the inserted menu. - } - }); - }; - - /** - * Focus a menu item control. - * - * @alias wp.customize.Menus.focusMenuItemControl - * - * @param {string} menuItemId - */ - api.Menus.focusMenuItemControl = function( menuItemId ) { - var control = api.Menus.getMenuItemControl( menuItemId ); - if ( control ) { - control.focus(); - } - }; - - /** - * Get the control for a given menu. - * - * @alias wp.customize.Menus.getMenuControl - * - * @param menuId - * @return {wp.customize.controlConstructor.menus[]} - */ - api.Menus.getMenuControl = function( menuId ) { - return api.control( 'nav_menu[' + menuId + ']' ); - }; - - /** - * Given a menu item ID, get the control associated with it. - * - * @alias wp.customize.Menus.getMenuItemControl - * - * @param {string} menuItemId - * @return {object|null} - */ - api.Menus.getMenuItemControl = function( menuItemId ) { - return api.control( menuItemIdToSettingId( menuItemId ) ); - }; - - /** - * @alias wp.customize.Menus~menuItemIdToSettingId - * - * @param {String} menuItemId - */ - function menuItemIdToSettingId( menuItemId ) { - return 'nav_menu_item[' + menuItemId + ']'; - } - - /** - * Apply sanitize_text_field()-like logic to the supplied name, returning a - * "unnammed" fallback string if the name is then empty. - * - * @alias wp.customize.Menus~displayNavMenuName - * - * @param {string} name - * @returns {string} - */ - function displayNavMenuName( name ) { - name = name || ''; - name = wp.sanitize.stripTagsAndEncodeText( name ); // Remove any potential tags from name. - name = $.trim( name ); - return name || api.Menus.data.l10n.unnamed; - } - -})( wp.customize, wp, jQuery ); diff --git a/srcs/wordpress/wp-admin/js/customize-nav-menus.min.js b/srcs/wordpress/wp-admin/js/customize-nav-menus.min.js deleted file mode 100644 index e90d116..0000000 --- a/srcs/wordpress/wp-admin/js/customize-nav-menus.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(v,h,g){"use strict";function d(e){return e=e||"",e=h.sanitize.stripTagsAndEncodeText(e),(e=g.trim(e))||v.Menus.data.l10n.unnamed}wpNavMenu.originalInit=wpNavMenu.init,wpNavMenu.options.menuItemDepthPerLevel=20,wpNavMenu.options.sortableItems="> .customize-control-nav_menu_item",wpNavMenu.options.targetTolerance=10,wpNavMenu.init=function(){this.jQueryExtensions()},v.Menus=v.Menus||{},v.Menus.data={itemTypes:[],l10n:{},settingTransport:"refresh",phpIntMax:0,defaultSettingValues:{nav_menu:{},nav_menu_item:{}},locationSlugMappedToName:{}},"undefined"!=typeof _wpCustomizeNavMenusSettings&&g.extend(v.Menus.data,_wpCustomizeNavMenusSettings),v.Menus.generatePlaceholderAutoIncrementId=function(){return-Math.ceil(v.Menus.data.phpIntMax*Math.random())},v.Menus.AvailableItemModel=Backbone.Model.extend(g.extend({id:null},v.Menus.data.defaultSettingValues.nav_menu_item)),v.Menus.AvailableItemCollection=Backbone.Collection.extend({model:v.Menus.AvailableItemModel,sort_key:"order",comparator:function(e){return-e.get(this.sort_key)},sortByField:function(e){this.sort_key=e,this.sort()}}),v.Menus.availableMenuItems=new v.Menus.AvailableItemCollection(v.Menus.data.availableMenuItems),v.Menus.insertAutoDraftPost=function(n){var e,i=g.Deferred();return(e=h.ajax.post("customize-nav-menus-insert-auto-draft",{"customize-menus-nonce":v.settings.nonce["customize-menus"],wp_customize:"on",customize_changeset_uuid:v.settings.changeset.uuid,params:n})).done(function(t){t.post_id&&(v("nav_menus_created_posts").set(v("nav_menus_created_posts").get().concat([t.post_id])),"page"===n.post_type&&(v.section.has("static_front_page")&&v.section("static_front_page").activate(),v.control.each(function(e){"dropdown-pages"===e.params.type&&e.container.find('select[name^="_customize-dropdown-pages-"]').append(new Option(n.post_title,t.post_id))})),i.resolve(t))}),e.fail(function(e){var t=e||"";void 0!==e.message&&(t=e.message),console.error(t),i.rejectWith(t)}),i.promise()},v.Menus.AvailableMenuItemsPanelView=h.Backbone.View.extend({el:"#available-menu-items",events:{"input #menu-items-search":"debounceSearch","focus .menu-item-tpl":"focus","click .menu-item-tpl":"_submit","click #custom-menu-item-submit":"_submitLink","keypress #custom-menu-item-name":"_submitLink","click .new-content-item .add-content":"_submitNew","keypress .create-item-input":"_submitNew",keydown:"keyboardAccessible"},selected:null,currentMenuControl:null,debounceSearch:null,$search:null,$clearResults:null,searchTerm:"",rendered:!1,pages:{},sectionContent:"",loading:!1,addingNew:!1,initialize:function(){var a=this;v.panel.has("nav_menus")&&(this.$search=g("#menu-items-search"),this.$clearResults=this.$el.find(".clear-results"),this.sectionContent=this.$el.find(".available-menu-items-list"),this.debounceSearch=_.debounce(a.search,500),_.bindAll(this,"close"),g("#customize-controls, .customize-section-back").on("click keydown",function(e){var t=g(e.target).is(".item-delete, .item-delete *"),n=g(e.target).is(".add-new-menu-item, .add-new-menu-item *");!g("body").hasClass("adding-menu-items")||t||n||a.close()}),this.$clearResults.on("click",function(){a.$search.val("").focus().trigger("keyup")}),this.$el.on("input","#custom-menu-item-name.invalid, #custom-menu-item-url.invalid",function(){g(this).removeClass("invalid")}),v.panel("nav_menus").container.bind("expanded",function(){a.rendered||(a.initList(),a.rendered=!0)}),this.sectionContent.scroll(function(){var e=a.$el.find(".accordion-section.open .available-menu-items-list").prop("scrollHeight"),t=a.$el.find(".accordion-section.open").height();if(!a.loading&&g(this).scrollTop()>.75*e-t){var n=g(this).data("type"),i=g(this).data("object");"search"===n?a.searchTerm&&a.doSearch(a.pages.search):a.loadItems([{type:n,object:i}])}}),v.previewer.bind("url",this.close),a.delegateEvents())},search:function(e){var t=g("#available-menu-items-search"),n=g("#available-menu-items .accordion-section").not(t);e&&this.searchTerm!==e.target.value&&(""===e.target.value||t.hasClass("open")?""===e.target.value&&(t.removeClass("open"),n.show(),this.$clearResults.removeClass("is-visible")):(n.fadeOut(100),t.find(".accordion-section-content").slideDown("fast"),t.addClass("open"),this.$clearResults.addClass("is-visible")),this.searchTerm=e.target.value,this.pages.search=1,this.doSearch(1))},doSearch:function(n){var e,i=this,a=g("#available-menu-items-search"),o=a.find(".accordion-section-content"),s=h.template("available-menu-item");if(i.currentRequest&&i.currentRequest.abort(),!(n<0)){if(1<n)a.addClass("loading-more"),o.attr("aria-busy","true"),h.a11y.speak(v.Menus.data.l10n.itemsLoadingMore);else if(""===i.searchTerm)return o.html(""),void h.a11y.speak("");a.addClass("loading"),i.loading=!0,e=v.previewer.query({excludeCustomizedSaved:!0}),_.extend(e,{"customize-menus-nonce":v.settings.nonce["customize-menus"],wp_customize:"on",search:i.searchTerm,page:n}),i.currentRequest=h.ajax.post("search-available-menu-items-customizer",e),i.currentRequest.done(function(e){var t;1===n&&o.empty(),a.removeClass("loading loading-more"),o.attr("aria-busy","false"),a.addClass("open"),i.loading=!1,t=new v.Menus.AvailableItemCollection(e.items),i.collection.add(t.models),t.each(function(e){o.append(s(e.attributes))}),t.length<20?i.pages.search=-1:i.pages.search=i.pages.search+1,t&&1<n?h.a11y.speak(v.Menus.data.l10n.itemsFoundMore.replace("%d",t.length)):t&&1===n&&h.a11y.speak(v.Menus.data.l10n.itemsFound.replace("%d",t.length))}),i.currentRequest.fail(function(e){e.message&&(o.empty().append(g('<li class="nothing-found"></li>').text(e.message)),h.a11y.speak(e.message)),i.pages.search=-1}),i.currentRequest.always(function(){a.removeClass("loading loading-more"),o.attr("aria-busy","false"),i.loading=!1,i.currentRequest=null})}},initList:function(){var t=this;_.each(v.Menus.data.itemTypes,function(e){t.pages[e.type+":"+e.object]=0}),t.loadItems(v.Menus.data.itemTypes)},loadItems:function(e,t){var n,i,a,o,s=this,r=[],u={};o=h.template("available-menu-item"),n=_.isString(e)&&_.isString(t)?[{type:e,object:t}]:e,_.each(n,function(e){var t,n=e.type+":"+e.object;-1!==s.pages[n]&&((t=g("#available-menu-items-"+e.type+"-"+e.object)).find(".accordion-section-title").addClass("loading"),u[n]=t,r.push({object:e.object,type:e.type,page:s.pages[n]}))}),0!==r.length&&(s.loading=!0,i=v.previewer.query({excludeCustomizedSaved:!0}),_.extend(i,{"customize-menus-nonce":v.settings.nonce["customize-menus"],wp_customize:"on",item_types:r}),(a=h.ajax.post("load-available-menu-items-customizer",i)).done(function(e){var n;_.each(e.items,function(e,t){if(0===e.length)return 0===s.pages[t]&&u[t].find(".accordion-section-title").addClass("cannot-expand").removeClass("loading").find(".accordion-section-title > button").prop("tabIndex",-1),void(s.pages[t]=-1);"post_type:page"!==t||u[t].hasClass("open")||u[t].find(".accordion-section-title > button").click(),e=new v.Menus.AvailableItemCollection(e),s.collection.add(e.models),n=u[t].find(".available-menu-items-list"),e.each(function(e){n.append(o(e.attributes))}),s.pages[t]+=1})}),a.fail(function(e){"undefined"!=typeof console&&console.error&&console.error(e)}),a.always(function(){_.each(u,function(e){e.find(".accordion-section-title").removeClass("loading")}),s.loading=!1}))},itemSectionHeight:function(){var e,t,n,i;n=window.innerHeight,e=this.$el.find(".accordion-section:not( #available-menu-items-search ) .accordion-section-content"),t=this.$el.find('.accordion-section:not( #available-menu-items-search ) .available-menu-items-list:not(":only-child")'),120<(i=n-(46*(1+e.length)+14))&&i<290&&(e.css("max-height",i),t.css("max-height",i-60))},select:function(e){this.selected=g(e),this.selected.siblings(".menu-item-tpl").removeClass("selected"),this.selected.addClass("selected")},focus:function(e){this.select(g(e.currentTarget))},_submit:function(e){"keypress"===e.type&&13!==e.which&&32!==e.which||this.submit(g(e.currentTarget))},submit:function(e){var t,n;(e=e||this.selected)&&this.currentMenuControl&&(this.select(e),t=g(this.selected).data("menu-item-id"),(n=this.collection.findWhere({id:t}))&&(this.currentMenuControl.addItemToMenu(n.attributes),g(e).find(".menu-item-handle").addClass("item-added")))},_submitLink:function(e){"keypress"===e.type&&13!==e.which||this.submitLink()},submitLink:function(){var e,t,n=g("#custom-menu-item-name"),i=g("#custom-menu-item-url"),a=i.val().trim();this.currentMenuControl&&(t=/^((\w+:)?\/\/\w.*|\w+:(?!\/\/$)|\/|\?|#)/,""!==n.val()?t.test(a)?(e={title:n.val(),url:a,type:"custom",type_label:v.Menus.data.l10n.custom_label,object:"custom"},this.currentMenuControl.addItemToMenu(e),i.val("").attr("placeholder","https://"),n.val("")):i.addClass("invalid"):n.addClass("invalid"))},_submitNew:function(e){var t;"keypress"===e.type&&13!==e.which||this.addingNew||(t=g(e.target).closest(".accordion-section"),this.submitNew(t))},submitNew:function(a){var o=this,s=a.find(".create-item-input"),e=s.val(),t=a.find(".available-menu-items-list"),r=t.data("type"),u=t.data("object"),d=t.data("type_label");if(this.currentMenuControl&&"post_type"===r){if(""===g.trim(s.val()))return s.addClass("invalid"),void s.focus();s.removeClass("invalid"),a.find(".accordion-section-title").addClass("loading"),o.addingNew=!0,s.attr("disabled","disabled"),v.Menus.insertAutoDraftPost({post_title:e,post_type:u}).done(function(e){var t,n,i;t=new v.Menus.AvailableItemModel({id:"post-"+e.post_id,title:s.val(),type:r,type_label:d,object:u,object_id:e.post_id,url:e.url}),o.currentMenuControl.addItemToMenu(t.attributes),v.Menus.availableMenuItemsPanel.collection.add(t),n=a.find(".available-menu-items-list"),(i=g(h.template("available-menu-item")(t.attributes))).find(".menu-item-handle:first").addClass("item-added"),n.prepend(i),n.scrollTop(),s.val("").removeAttr("disabled"),o.addingNew=!1,a.find(".accordion-section-title").removeClass("loading")})}},open:function(e){var t,n=this;this.currentMenuControl=e,this.itemSectionHeight(),v.section.has("publish_settings")&&v.section("publish_settings").collapse(),g("body").addClass("adding-menu-items"),t=function(){n.close(),g(this).off("click",t)},g("#customize-preview").on("click",t),_(this.currentMenuControl.getMenuItemControls()).each(function(e){e.collapseForm()}),this.$el.find(".selected").removeClass("selected"),this.$search.focus()},close:function(e){(e=e||{}).returnFocus&&this.currentMenuControl&&this.currentMenuControl.container.find(".add-new-menu-item").focus(),this.currentMenuControl=null,this.selected=null,g("body").removeClass("adding-menu-items"),g("#available-menu-items .menu-item-handle.item-added").removeClass("item-added"),this.$search.val("").trigger("keyup")},keyboardAccessible:function(e){var t=13===e.which,n=27===e.which,i=9===e.which&&e.shiftKey,a=g(e.target).is(this.$search);t&&!this.$search.val()||(a&&i?(this.currentMenuControl.container.find(".add-new-menu-item").focus(),e.preventDefault()):n&&this.close({returnFocus:!0}))}}),v.Menus.MenusPanel=v.Panel.extend({attachEvents:function(){v.Panel.prototype.attachEvents.call(this);var t=this.container.find(".panel-meta"),n=t.find(".customize-help-toggle"),i=t.find(".customize-panel-description"),a=g("#screen-options-wrap"),o=t.find(".customize-screen-options-toggle");o.on("click keydown",function(e){if(!v.utils.isKeydownButNotEnterEvent(e))return e.preventDefault(),i.not(":hidden")&&(i.slideUp("fast"),n.attr("aria-expanded","false")),"true"===o.attr("aria-expanded")?(o.attr("aria-expanded","false"),t.removeClass("open"),t.removeClass("active-menu-screen-options"),a.slideUp("fast")):(o.attr("aria-expanded","true"),t.addClass("open"),t.addClass("active-menu-screen-options"),a.slideDown("fast")),!1}),n.on("click keydown",function(e){v.utils.isKeydownButNotEnterEvent(e)||(e.preventDefault(),"true"===o.attr("aria-expanded")&&(o.attr("aria-expanded","false"),n.attr("aria-expanded","true"),t.addClass("open"),t.removeClass("active-menu-screen-options"),a.slideUp("fast"),i.slideDown("fast")))})},ready:function(){var e=this;e.container.find(".hide-column-tog").click(function(){e.saveManageColumnsState()}),v.section("menu_locations",function(e){e.headContainer.prepend(h.template("nav-menu-locations-header")(v.Menus.data))})},saveManageColumnsState:_.debounce(function(){var e=this;e._updateHiddenColumnsRequest&&e._updateHiddenColumnsRequest.abort(),e._updateHiddenColumnsRequest=h.ajax.post("hidden-columns",{hidden:e.hidden(),screenoptionnonce:g("#screenoptionnonce").val(),page:"nav-menus"}),e._updateHiddenColumnsRequest.always(function(){e._updateHiddenColumnsRequest=null})},2e3),checked:function(){},unchecked:function(){},hidden:function(){return g(".hide-column-tog").not(":checked").map(function(){var e=this.id;return e.substring(0,e.length-5)}).get().join(",")}}),v.Menus.MenuSection=v.Section.extend({initialize:function(e,t){v.Section.prototype.initialize.call(this,e,t),this.deferred.initSortables=g.Deferred()},ready:function(){var e,t,i=this;if(void 0===i.params.menu_id)throw new Error("params.menu_id was not defined");i.active.validate=function(){return!!v.has(i.id)&&!!v(i.id).get()},i.populateControls(),i.navMenuLocationSettings={},i.assignedLocations=new v.Value([]),v.each(function(e,t){var n=t.match(/^nav_menu_locations\[(.+?)]/);n&&(i.navMenuLocationSettings[n[1]]=e).bind(function(){i.refreshAssignedLocations()})}),i.assignedLocations.bind(function(e){i.updateAssignedLocationsInSectionTitle(e)}),i.refreshAssignedLocations(),v.bind("pane-contents-reflowed",function(){i.contentContainer.parent().length&&(i.container.find(".menu-item .menu-item-reorder-nav button").attr({tabindex:"0","aria-hidden":"false"}),i.container.find(".menu-item.move-up-disabled .menus-move-up").attr({tabindex:"-1","aria-hidden":"true"}),i.container.find(".menu-item.move-down-disabled .menus-move-down").attr({tabindex:"-1","aria-hidden":"true"}),i.container.find(".menu-item.move-left-disabled .menus-move-left").attr({tabindex:"-1","aria-hidden":"true"}),i.container.find(".menu-item.move-right-disabled .menus-move-right").attr({tabindex:"-1","aria-hidden":"true"}))}),t=function(){var e="field-"+g(this).val()+"-active";i.contentContainer.toggleClass(e,g(this).prop("checked"))},(e=v.panel("nav_menus").contentContainer.find(".metabox-prefs:first").find(".hide-column-tog")).each(t),e.on("click",t)},populateControls:function(){var e,t,n,i,a,o,s,r,u,d=this;e=d.id+"[name]",(o=v.control(e))||(o=new v.controlConstructor.nav_menu_name(e,{type:"nav_menu_name",label:v.Menus.data.l10n.menuNameLabel,section:d.id,priority:0,settings:{default:d.id}}),v.control.add(o),o.active.set(!0)),(a=v.control(d.id))||(a=new v.controlConstructor.nav_menu(d.id,{type:"nav_menu",section:d.id,priority:998,settings:{default:d.id},menu_id:d.params.menu_id}),v.control.add(a),a.active.set(!0)),t=d.id+"[locations]",(s=v.control(t))||(s=new v.controlConstructor.nav_menu_locations(t,{section:d.id,priority:999,settings:{default:d.id},menu_id:d.params.menu_id}),v.control.add(s.id,s),a.active.set(!0)),n=d.id+"[auto_add]",(r=v.control(n))||(r=new v.controlConstructor.nav_menu_auto_add(n,{type:"nav_menu_auto_add",label:"",section:d.id,priority:1e3,settings:{default:d.id}}),v.control.add(r),r.active.set(!0)),i=d.id+"[delete]",(u=v.control(i))||(u=new v.Control(i,{section:d.id,priority:1001,templateId:"nav-menu-delete-button"}),v.control.add(u.id,u),u.active.set(!0),u.deferred.embedded.done(function(){u.container.find("button").on("click",function(){var e=d.params.menu_id;v.Menus.getMenuControl(e).setting.set(!1)})}))},refreshAssignedLocations:function(){var n=this.params.menu_id,i=[];_.each(this.navMenuLocationSettings,function(e,t){e()===n&&i.push(t)}),this.assignedLocations.set(i)},updateAssignedLocationsInSectionTitle:function(e){var i;(i=this.container.find(".accordion-section-title:first")).find(".menu-in-location").remove(),_.each(e,function(e){var t,n;t=g('<span class="menu-in-location"></span>'),n=v.Menus.data.locationSlugMappedToName[e],t.text(v.Menus.data.l10n.menuLocation.replace("%s",n)),i.append(t)}),this.container.toggleClass("assigned-to-menu-location",0!==e.length)},onChangeExpanded:function(e,t){var n,i=this;e&&(wpNavMenu.menuList=i.contentContainer,wpNavMenu.targetList=wpNavMenu.menuList,g("#menu-to-edit").removeAttr("id"),wpNavMenu.menuList.attr("id","menu-to-edit").addClass("menu"),_.each(v.section(i.id).controls(),function(e){"nav_menu_item"===e.params.type&&e.actuallyEmbed()}),t.completeCallback&&(n=t.completeCallback),t.completeCallback=function(){"resolved"!==i.deferred.initSortables.state()&&(wpNavMenu.initSortables(),i.deferred.initSortables.resolve(wpNavMenu.menuList),v.control("nav_menu["+String(i.params.menu_id)+"]").reflowMenuItems()),_.isFunction(n)&&n()}),v.Section.prototype.onChangeExpanded.call(i,e,t)},highlightNewItemButton:function(){v.utils.highlightButton(this.contentContainer.find(".add-new-menu-item"),{delay:2e3})}}),v.Menus.createNavMenu=function(e){var t,n;return n=v.Menus.generatePlaceholderAutoIncrementId(),t="nav_menu["+String(n)+"]",v.create(t,t,{},{type:"nav_menu",transport:v.Menus.data.settingTransport,previewer:v.previewer}).set(g.extend({},v.Menus.data.defaultSettingValues.nav_menu,{name:e||""})),v.section.add(new v.Menus.MenuSection(t,{panel:"nav_menus",title:d(e),customizeAction:v.Menus.data.l10n.customizingMenus,priority:10,menu_id:n}))},v.Menus.NewMenuSection=v.Section.extend({attachEvents:function(){var t=this,e=t.container,n=t.contentContainer,i=/^nav_menu\[/;function a(){e.find(".add-new-menu-notice").prop("hidden",0<function(){var t=0;return v.each(function(e){i.test(e.id)&&!1!==e.get()&&(t+=1)}),t}())}function o(e){i.test(e.id)&&(e.bind(a),a())}t.headContainer.find(".accordion-section-title").replaceWith(h.template("nav-menu-create-menu-section-title")),e.on("click",".customize-add-menu-button",function(){t.expand()}),n.on("keydown",".menu-name-field",function(e){13===e.which&&t.submit()}),n.on("click","#customize-new-menu-submit",function(e){t.submit(),e.stopPropagation(),e.preventDefault()}),v.each(o),v.bind("add",o),v.bind("removed",function(e){i.test(e.id)&&(e.unbind(a),a())}),a(),v.Section.prototype.attachEvents.apply(t,arguments)},ready:function(){this.populateControls()},populateControls:function(){var e,t,n,i,a,o,s=this;e=s.id+"[name]",(i=v.control(e))||(i=new v.controlConstructor.nav_menu_name(e,{label:v.Menus.data.l10n.menuNameLabel,description:v.Menus.data.l10n.newMenuNameDescription,section:s.id,priority:0}),v.control.add(i.id,i),i.active.set(!0)),t=s.id+"[locations]",(a=v.control(t))||(a=new v.controlConstructor.nav_menu_locations(t,{section:s.id,priority:1,menu_id:"",isCreating:!0}),v.control.add(t,a),a.active.set(!0)),n=s.id+"[submit]",(o=v.control(n))||(o=new v.Control(n,{section:s.id,priority:1,templateId:"nav-menu-submit-new-button"}),v.control.add(n,o),o.active.set(!0))},submit:function(){var t,e=this.contentContainer,n=e.find(".menu-name-field").first(),i=n.val();if(!i)return n.addClass("invalid"),void n.focus();t=v.Menus.createNavMenu(i),n.val(""),n.removeClass("invalid"),e.find(".assigned-menu-location input[type=checkbox]").each(function(){var e=g(this);e.prop("checked")&&(v("nav_menu_locations["+e.data("location-id")+"]").set(t.params.menu_id),e.prop("checked",!1))}),h.a11y.speak(v.Menus.data.l10n.menuAdded),t.focus({completeCallback:function(){t.highlightNewItemButton()}})},selectDefaultLocation:function(e){var t=v.control(this.id+"[locations]"),n={};null!==e&&(n[e]=!0),t.setSelections(n)}}),v.Menus.MenuLocationControl=v.Control.extend({initialize:function(e,t){var n=e.match(/^nav_menu_locations\[(.+?)]/);this.themeLocation=n[1],v.Control.prototype.initialize.call(this,e,t)},ready:function(){var a=this,o=/^nav_menu\[(-?\d+)]/;a.setting.validate=function(e){return""===e?0:parseInt(e,10)},a.container.find(".create-menu").on("click",function(){var e=v.section("add_menu");e.selectDefaultLocation(this.dataset.locationId),e.focus()}),a.container.find(".edit-menu").on("click",function(){var e=a.setting();v.section("nav_menu["+e+"]").focus()}),a.setting.bind("change",function(){var e=0!==a.setting();a.container.find(".create-menu").toggleClass("hidden",e),a.container.find(".edit-menu").toggleClass("hidden",!e)}),v.bind("add",function(e){var t,n,i=e.id.match(o);i&&!1!==e()&&(n=i[1],t=new Option(d(e().name),n),a.container.find("select").append(t))}),v.bind("remove",function(e){var t,n=e.id.match(o);n&&(t=parseInt(n[1],10),a.setting()===t&&a.setting.set(""),a.container.find("option[value="+t+"]").remove())}),v.bind("change",function(e){var t,n=e.id.match(o);n&&(t=parseInt(n[1],10),!1===e()?(a.setting()===t&&a.setting.set(""),a.container.find("option[value="+t+"]").remove()):a.container.find("option[value="+t+"]").text(d(e().name)))})}}),v.Menus.MenuItemControl=v.Control.extend({initialize:function(e,t){var n=this;n.expanded=new v.Value(!1),n.expandedArgumentsQueue=[],n.expanded.bind(function(e){var t=n.expandedArgumentsQueue.shift();t=g.extend({},n.defaultExpandedArguments,t),n.onChangeExpanded(e,t)}),v.Control.prototype.initialize.call(n,e,t),n.active.validate=function(){var e=v.section(n.section());return!!e&&e.active()}},embed:function(){var e,t=this.section();t&&((e=v.section(t))&&e.expanded()||v.settings.autofocus.control===this.id)&&this.actuallyEmbed()},actuallyEmbed:function(){"resolved"!==this.deferred.embedded.state()&&(this.renderContent(),this.deferred.embedded.resolve())},ready:function(){if(void 0===this.params.menu_item_id)throw new Error("params.menu_item_id was not defined");this._setupControlToggle(),this._setupReorderUI(),this._setupUpdateUI(),this._setupRemoveUI(),this._setupLinksUI(),this._setupTitleUI()},_setupControlToggle:function(){var a=this;this.container.find(".menu-item-handle").on("click",function(e){e.preventDefault(),e.stopPropagation();var t=a.getMenuControl(),n=g(e.target).is(".item-delete, .item-delete *"),i=g(e.target).is(".add-new-menu-item, .add-new-menu-item *");!g("body").hasClass("adding-menu-items")||n||i||v.Menus.availableMenuItemsPanel.close(),t.isReordering||t.isSorting||a.toggleForm()})},_setupReorderUI:function(){var e,o=this;e=h.template("menu-item-reorder-nav"),o.container.find(".item-controls").after(e),o.container.find(".menu-item-reorder-nav").find(".menus-move-up, .menus-move-down, .menus-move-left, .menus-move-right").on("click",function(){var e=g(this);e.focus();var t=e.is(".menus-move-up"),n=e.is(".menus-move-down"),i=e.is(".menus-move-left"),a=e.is(".menus-move-right");t?o.moveUp():n?o.moveDown():i?o.moveLeft():a&&o.moveRight(),e.focus()})},_setupUpdateUI:function(){var e,s=this,t=s.setting();s.elements={},s.elements.url=new v.Element(s.container.find(".edit-menu-item-url")),s.elements.title=new v.Element(s.container.find(".edit-menu-item-title")),s.elements.attr_title=new v.Element(s.container.find(".edit-menu-item-attr-title")),s.elements.target=new v.Element(s.container.find(".edit-menu-item-target")),s.elements.classes=new v.Element(s.container.find(".edit-menu-item-classes")),s.elements.xfn=new v.Element(s.container.find(".edit-menu-item-xfn")),s.elements.description=new v.Element(s.container.find(".edit-menu-item-description")),_.each(s.elements,function(n,i){n.bind(function(e){n.element.is("input[type=checkbox]")&&(e=e?n.element.val():"");var t=s.setting();t&&t[i]!==e&&((t=_.clone(t))[i]=e,s.setting.set(t))}),t&&("classes"!==i&&"xfn"!==i||!_.isArray(t[i])?n.set(t[i]):n.set(t[i].join(" ")))}),s.setting.bind(function(n,i){var e,t=s.params.menu_item_id,a=[],o=[];!1===n?(e=v.control("nav_menu["+String(i.nav_menu_term_id)+"]"),s.container.remove(),_.each(e.getMenuItemControls(),function(e){i.menu_item_parent===e.setting().menu_item_parent&&e.setting().position>i.position?a.push(e):e.setting().menu_item_parent===t&&o.push(e)}),_.each(a,function(e){var t=_.clone(e.setting());t.position+=o.length,e.setting.set(t)}),_.each(o,function(e,t){var n=_.clone(e.setting());n.position=i.position+t,n.menu_item_parent=i.menu_item_parent,e.setting.set(n)}),e.debouncedReflowMenuItems()):(_.each(n,function(e,t){s.elements[t]&&s.elements[t].set(n[t])}),s.container.find(".menu-item-data-parent-id").val(n.menu_item_parent),n.position===i.position&&n.menu_item_parent===i.menu_item_parent||s.getMenuControl().debouncedReflowMenuItems())}),e=function(){s.elements.url.element.toggleClass("invalid",s.setting.notifications.has("invalid_url"))},s.setting.notifications.bind("add",e),s.setting.notifications.bind("removed",e)},_setupRemoveUI:function(){var a=this;a.container.find(".item-delete").on("click",function(){var e,t,n,i=!0;g("body").hasClass("adding-menu-items")||(i=!1),t=a.container.nextAll(".customize-control-nav_menu_item:visible").first(),n=a.container.prevAll(".customize-control-nav_menu_item:visible").first(),e=t.length?t.find(!1===i?".item-edit":".item-delete").first():n.length?n.find(!1===i?".item-edit":".item-delete").first():a.container.nextAll(".customize-control-nav_menu").find(".add-new-menu-item").first(),a.container.slideUp(function(){a.setting.set(!1),h.a11y.speak(v.Menus.data.l10n.itemDeleted),e.focus()}),a.setting.set(!1)})},_setupLinksUI:function(){this.container.find("a.original-link").on("click",function(e){e.preventDefault(),v.previewer.previewUrl(e.target.toString())})},_setupTitleUI:function(){var i;this.container.find(".edit-menu-item-title").on("blur",function(){g(this).val(g.trim(g(this).val()))}),i=this.container.find(".menu-item-title"),this.setting.bind(function(e){var t,n;e&&(n=(t=g.trim(e.title))||e.original_title||v.Menus.data.l10n.untitled,e._invalid&&(n=v.Menus.data.l10n.invalidTitleTpl.replace("%s",n)),t||e.original_title?i.text(n).removeClass("no-title"):i.text(n).addClass("no-title"))})},getDepth:function(){var e=this,t=e.setting(),n=0;if(!t)return 0;for(;t&&t.menu_item_parent&&(n+=1,e=v.control("nav_menu_item["+t.menu_item_parent+"]"));)t=e.setting();return n},renderContent:function(){var e,t=this,n=t.setting();t.params.title=n.title||"",t.params.depth=t.getDepth(),t.container.data("item-depth",t.params.depth),e=["menu-item","menu-item-depth-"+String(t.params.depth),"menu-item-"+n.object,"menu-item-edit-inactive"],n._invalid?(e.push("menu-item-invalid"),t.params.title=v.Menus.data.l10n.invalidTitleTpl.replace("%s",t.params.title)):"draft"===n.status&&(e.push("pending"),t.params.title=v.Menus.data.pendingTitleTpl.replace("%s",t.params.title)),t.params.el_classes=e.join(" "),t.params.item_type_label=n.type_label,t.params.item_type=n.type,t.params.url=n.url,t.params.target=n.target,t.params.attr_title=n.attr_title,t.params.classes=_.isArray(n.classes)?n.classes.join(" "):n.classes,t.params.xfn=n.xfn,t.params.description=n.description,t.params.parent=n.menu_item_parent,t.params.original_title=n.original_title||"",t.container.addClass(t.params.el_classes),v.Control.prototype.renderContent.call(t)},getMenuControl:function(){var e=this.setting();return e&&e.nav_menu_term_id?v.control("nav_menu["+e.nav_menu_term_id+"]"):null},expandControlSection:function(){var e=this.container.closest(".accordion-section");e.hasClass("open")||e.find(".accordion-section-title:first").trigger("click")},_toggleExpanded:v.Section.prototype._toggleExpanded,expand:v.Section.prototype.expand,expandForm:function(e){this.expand(e)},collapse:v.Section.prototype.collapse,collapseForm:function(e){this.collapse(e)},toggleForm:function(e,t){void 0===e&&(e=!this.expanded()),e?this.expand(t):this.collapse(t)},onChangeExpanded:function(e,t){var n,i,a,o=this;i=(n=this.container).find(".menu-item-settings:first"),void 0===e&&(e=!i.is(":visible")),i.is(":visible")!==e?e?(v.control.each(function(e){o.params.type===e.params.type&&o!==e&&e.collapseForm()}),a=function(){n.removeClass("menu-item-edit-inactive").addClass("menu-item-edit-active"),o.container.trigger("expanded"),t&&t.completeCallback&&t.completeCallback()},n.find(".item-edit").attr("aria-expanded","true"),i.slideDown("fast",a),o.container.trigger("expand")):(a=function(){n.addClass("menu-item-edit-inactive").removeClass("menu-item-edit-active"),o.container.trigger("collapsed"),t&&t.completeCallback&&t.completeCallback()},o.container.trigger("collapse"),n.find(".item-edit").attr("aria-expanded","false"),i.slideUp("fast",a)):t&&t.completeCallback&&t.completeCallback()},focus:function(e){var t,n=this,i=(e=e||{}).completeCallback;t=function(){n.expandControlSection(),e.completeCallback=function(){n.container.find(".menu-item-settings").find("input, select, textarea, button, object, a[href], [tabindex]").filter(":visible").first().focus(),i&&i()},n.expandForm(e)},v.section.has(n.section())?v.section(n.section()).expand({completeCallback:t}):t()},moveUp:function(){this._changePosition(-1),h.a11y.speak(v.Menus.data.l10n.movedUp)},moveDown:function(){this._changePosition(1),h.a11y.speak(v.Menus.data.l10n.movedDown)},moveLeft:function(){this._changeDepth(-1),h.a11y.speak(v.Menus.data.l10n.movedLeft)},moveRight:function(){this._changeDepth(1),h.a11y.speak(v.Menus.data.l10n.movedRight)},_changePosition:function(e){var t,n,i=this,a=_.clone(i.setting()),o=[];if(1!==e&&-1!==e)throw new Error("Offset changes by 1 are only supported.");if(i.setting()){if(_(i.getMenuControl().getMenuItemControls()).each(function(e){e.setting().menu_item_parent===a.menu_item_parent&&o.push(e.setting)}),o.sort(function(e,t){return e().position-t().position}),-1===(n=_.indexOf(o,i.setting)))throw new Error("Expected setting to be among siblings.");0===n&&e<0||n===o.length-1&&0<e||((t=o[n+e])&&t.set(g.extend(_.clone(t()),{position:a.position})),a.position+=e,i.setting.set(a))}},_changeDepth:function(e){if(1!==e&&-1!==e)throw new Error("Offset changes by 1 are only supported.");var t,n,i,a=this,o=_.clone(a.setting()),s=[];if(_(a.getMenuControl().getMenuItemControls()).each(function(e){e.setting().menu_item_parent===o.menu_item_parent&&s.push(e)}),s.sort(function(e,t){return e.setting().position-t.setting().position}),-1===(t=_.indexOf(s,a)))throw new Error("Expected control to be among siblings.");if(-1===e){if(!o.menu_item_parent)return;i=v.control("nav_menu_item["+o.menu_item_parent+"]"),_(s).chain().slice(t).each(function(e,t){e.setting.set(g.extend({},e.setting(),{menu_item_parent:a.params.menu_item_id,position:t}))}),_(a.getMenuControl().getMenuItemControls()).each(function(e){var t;e.setting().menu_item_parent===i.setting().menu_item_parent&&e.setting().position>i.setting().position&&(t=_.clone(e.setting()),e.setting.set(g.extend(t,{position:t.position+1})))}),o.position=i.setting().position+1,o.menu_item_parent=i.setting().menu_item_parent,a.setting.set(o)}else if(1===e){if(0===t)return;n=s[t-1],o.menu_item_parent=n.params.menu_item_id,o.position=0,_(a.getMenuControl().getMenuItemControls()).each(function(e){e.setting().menu_item_parent===o.menu_item_parent&&(o.position=Math.max(o.position,e.setting().position))}),o.position+=1,a.setting.set(o)}}}),v.Menus.MenuNameControl=v.Control.extend({ready:function(){var n=this;if(n.setting){var e=n.setting();n.nameElement=new v.Element(n.container.find(".menu-name-field")),n.nameElement.bind(function(e){var t=n.setting();t&&t.name!==e&&((t=_.clone(t)).name=e,n.setting.set(t))}),e&&n.nameElement.set(e.name),n.setting.bind(function(e){e&&n.nameElement.set(e.name)})}}}),v.Menus.MenuLocationsControl=v.Control.extend({ready:function(){var u=this;u.container.find(".assigned-menu-location").each(function(){function t(e){var t=v("nav_menu["+String(e)+"]");e&&t&&t()?n.find(".theme-location-set").show().find("span").text(d(t().name)):n.find(".theme-location-set").hide()}var n=g(this),e=n.find("input[type=checkbox]"),i=new v.Element(e),a=v("nav_menu_locations["+e.data("location-id")+"]"),o=""===u.params.menu_id,s=o?_.noop:function(e){i.set(e)},r=o?_.noop:function(e){a.set(e?u.params.menu_id:0)};s(a.get()===u.params.menu_id),e.on("change",function(){r(this.checked)}),a.bind(function(e){s(e===u.params.menu_id),t(e)}),t(a.get())})},setSelections:function(i){this.container.find(".menu-location").each(function(e,t){var n=t.dataset.locationId;t.checked=n in i&&i[n]})}}),v.Menus.MenuAutoAddControl=v.Control.extend({ready:function(){var n=this,e=n.setting();n.active.validate=function(){var e=v.section(n.section());return!!e&&e.active()},n.autoAddElement=new v.Element(n.container.find("input[type=checkbox].auto_add")),n.autoAddElement.bind(function(e){var t=n.setting();t&&t.name!==e&&((t=_.clone(t)).auto_add=e,n.setting.set(t))}),e&&n.autoAddElement.set(e.auto_add),n.setting.bind(function(e){e&&n.autoAddElement.set(e.auto_add)})}}),v.Menus.MenuControl=v.Control.extend({ready:function(){var t,e,n,i=this,a=v.section(i.section()),o=i.params.menu_id,s=i.setting();if(void 0===this.params.menu_id)throw new Error("params.menu_id was not defined");i.active.validate=function(){return!!a&&a.active()},i.$controlSection=a.headContainer,i.$sectionContent=i.container.closest(".accordion-section-content"),this._setupModel(),v.section(i.section(),function(e){e.deferred.initSortables.done(function(e){i._setupSortable(e)})}),this._setupAddition(),this._setupTitle(),s&&(t=d(s.name),v.control.each(function(e){e.extended(v.controlConstructor.widget_form)&&"nav_menu"===e.params.widget_id_base&&(e.container.find(".nav-menu-widget-form-controls:first").show(),e.container.find(".nav-menu-widget-no-menus-message:first").hide(),0===(n=e.container.find("select")).find("option[value="+String(o)+"]").length&&n.append(new Option(t,o)))}),(e=g("#available-widgets-list .widget-tpl:has( input.id_base[ value=nav_menu ] )")).find(".nav-menu-widget-form-controls:first").show(),e.find(".nav-menu-widget-no-menus-message:first").hide(),0===(n=e.find(".widget-inside select:first")).find("option[value="+String(o)+"]").length&&n.append(new Option(t,o))),_.defer(function(){i.updateInvitationVisibility()})},_setupModel:function(){var n=this,i=n.params.menu_id;n.setting.bind(function(e){var t;!1===e?n._handleDeletion():(t=d(e.name),v.control.each(function(e){e.extended(v.controlConstructor.widget_form)&&"nav_menu"===e.params.widget_id_base&&e.container.find("select").find("option[value="+String(i)+"]").text(t)}))})},_setupSortable:function(e){var t=this;if(!e.is(t.$sectionContent))throw new Error("Unexpected menuList.");e.on("sortstart",function(){t.isSorting=!0}),e.on("sortstop",function(){setTimeout(function(){var e=t.$sectionContent.sortable("toArray"),a=[],n=0,i=10;t.isSorting=!1,t.$sectionContent.scrollLeft(0),_.each(e,function(e){var t,n,i;(i=e.match(/^customize-control-nav_menu_item-(-?\d+)$/,""))&&(t=parseInt(i[1],10),(n=v.control("nav_menu_item["+String(t)+"]"))&&a.push(n))}),_.each(a,function(e){if(!1!==e.setting()){var t=_.clone(e.setting());n+=1,i+=1,t.position=n,e.priority(i),t.menu_item_parent=parseInt(e.container.find(".menu-item-data-parent-id").val(),10),t.menu_item_parent||(t.menu_item_parent=0),e.setting.set(t)}})})}),t.isReordering=!1,this.container.find(".reorder-toggle").on("click",function(){t.toggleReordering(!t.isReordering)})},_setupAddition:function(){var t=this;this.container.find(".add-new-menu-item").on("click",function(e){t.$sectionContent.hasClass("reordering")||(g("body").hasClass("adding-menu-items")?(g(this).attr("aria-expanded","false"),v.Menus.availableMenuItemsPanel.close(),e.stopPropagation()):(g(this).attr("aria-expanded","true"),v.Menus.availableMenuItemsPanel.open(t)))})},_handleDeletion:function(){var e,t,n,i=this.params.menu_id,a=0;e=v.section(this.section()),t=function(){e.container.remove(),v.section.remove(e.id)},e&&e.expanded()?e.collapse({completeCallback:function(){t(),h.a11y.speak(v.Menus.data.l10n.menuDeleted),v.panel("nav_menus").focus()}}):t(),v.each(function(e){/^nav_menu\[/.test(e.id)&&!1!==e()&&(a+=1)}),v.control.each(function(e){if(e.extended(v.controlConstructor.widget_form)&&"nav_menu"===e.params.widget_id_base){var t=e.container.find("select");t.val()===String(i)&&t.prop("selectedIndex",0).trigger("change"),e.container.find(".nav-menu-widget-form-controls:first").toggle(0!==a),e.container.find(".nav-menu-widget-no-menus-message:first").toggle(0===a),e.container.find("option[value="+String(i)+"]").remove()}}),(n=g("#available-widgets-list .widget-tpl:has( input.id_base[ value=nav_menu ] )")).find(".nav-menu-widget-form-controls:first").toggle(0!==a),n.find(".nav-menu-widget-no-menus-message:first").toggle(0===a),n.find("option[value="+String(i)+"]").remove()},_setupTitle:function(){var u=this;u.setting.bind(function(e){if(e){var t=v.section(u.section()),n=u.params.menu_id,i=t.headContainer.find(".accordion-section-title"),a=t.contentContainer.find(".customize-section-title h3"),o=t.headContainer.find(".menu-in-location"),s=a.find(".customize-action"),r=d(e.name);i.text(r),o.length&&o.appendTo(i),a.text(r),s.length&&s.prependTo(a),v.control.each(function(e){/^nav_menu_locations\[/.test(e.id)&&e.container.find("option[value="+n+"]").text(r)}),t.contentContainer.find(".customize-control-checkbox input").each(function(){g(this).prop("checked")&&g(".current-menu-location-name-"+g(this).data("location-id")).text(r)})}})},toggleReordering:function(e){var t=this.container.find(".add-new-menu-item"),n=this.container.find(".reorder-toggle"),i=this.$sectionContent.find(".item-title");(e=Boolean(e))!==this.$sectionContent.hasClass("reordering")&&(this.isReordering=e,this.$sectionContent.toggleClass("reordering",e),this.$sectionContent.sortable(this.isReordering?"disable":"enable"),this.isReordering?(t.attr({tabindex:"-1","aria-hidden":"true"}),n.attr("aria-label",v.Menus.data.l10n.reorderLabelOff),h.a11y.speak(v.Menus.data.l10n.reorderModeOn),i.attr("aria-hidden","false")):(t.removeAttr("tabindex aria-hidden"),n.attr("aria-label",v.Menus.data.l10n.reorderLabelOn),h.a11y.speak(v.Menus.data.l10n.reorderModeOff),i.attr("aria-hidden","true")),e&&_(this.getMenuItemControls()).each(function(e){e.collapseForm()}))},getMenuItemControls:function(){var t=[],n=this.params.menu_id;return v.control.each(function(e){"nav_menu_item"===e.params.type&&e.setting()&&n===e.setting().nav_menu_term_id&&t.push(e)}),t},reflowMenuItems:function(){var e,t=this.getMenuItemControls();(e=function(n){var t=[],i=n.currentParent;_.each(n.menuItemControls,function(e){i===e.setting().menu_item_parent&&t.push(e)}),t.sort(function(e,t){return e.setting().position-t.setting().position}),_.each(t,function(t){n.currentAbsolutePosition+=1,t.priority.set(n.currentAbsolutePosition),t.container.hasClass("menu-item-depth-"+String(n.currentDepth))||(_.each(t.container.prop("className").match(/menu-item-depth-\d+/g),function(e){t.container.removeClass(e)}),t.container.addClass("menu-item-depth-"+String(n.currentDepth))),t.container.data("item-depth",n.currentDepth),n.currentDepth+=1,n.currentParent=t.params.menu_item_id,e(n),n.currentDepth-=1,n.currentParent=i}),t.length&&(_(t).each(function(e){e.container.removeClass("move-up-disabled move-down-disabled move-left-disabled move-right-disabled"),0===n.currentDepth?e.container.addClass("move-left-disabled"):10===n.currentDepth&&e.container.addClass("move-right-disabled")}),t[0].container.addClass("move-up-disabled").addClass("move-right-disabled").toggleClass("move-down-disabled",1===t.length),t[t.length-1].container.addClass("move-down-disabled").toggleClass("move-up-disabled",1===t.length))})({menuItemControls:t,currentParent:0,currentDepth:0,currentAbsolutePosition:0}),this.updateInvitationVisibility(t),this.container.find(".reorder-toggle").toggle(1<t.length)},debouncedReflowMenuItems:_.debounce(function(){this.reflowMenuItems.apply(this,arguments)},0),addItemToMenu:function(e){var t,n,i,a,o,s=0,r=10;return _.each(this.getMenuItemControls(),function(e){!1!==e.setting()&&(r=Math.max(r,e.priority()),0===e.setting().menu_item_parent&&(s=Math.max(s,e.setting().position)))}),s+=1,r+=1,delete(e=g.extend({},v.Menus.data.defaultSettingValues.nav_menu_item,e,{nav_menu_term_id:this.params.menu_id,original_title:e.title,position:s})).id,o=v.Menus.generatePlaceholderAutoIncrementId(),t="nav_menu_item["+String(o)+"]",n={type:"nav_menu_item",transport:v.Menus.data.settingTransport,previewer:v.previewer},(i=v.create(t,t,{},n)).set(e),a=new v.controlConstructor.nav_menu_item(t,{type:"nav_menu_item",section:this.id,priority:r,settings:{default:t},menu_item_id:o}),v.control.add(a),i.preview(),this.debouncedReflowMenuItems(),h.a11y.speak(v.Menus.data.l10n.itemAdded),a},updateInvitationVisibility:function(e){var t=e||this.getMenuItemControls();this.container.find(".new-menu-item-invitation").toggle(0===t.length)}}),v.Menus.NewMenuControl=v.Control.extend({initialize:function(){"undefined"!=typeof console&&console.warn&&console.warn("[DEPRECATED] wp.customize.NewMenuControl will be removed. Please use wp.customize.Menus.createNavMenu() instead."),v.Control.prototype.initialize.apply(this,arguments)},ready:function(){this._bindHandlers()},_bindHandlers:function(){var t=this,e=g("#customize-control-new_menu_name input"),n=g("#create-new-menu-submit");e.on("keydown",function(e){13===e.which&&t.submit()}),n.on("click",function(e){t.submit(),e.stopPropagation(),e.preventDefault()})},submit:function(){var e,t=this.container.closest(".accordion-section-new-menu").find(".menu-name-field").first(),n=t.val();if(!n)return t.addClass("invalid"),void t.focus();e=v.Menus.createNavMenu(n),t.val(""),t.removeClass("invalid"),h.a11y.speak(v.Menus.data.l10n.menuAdded),e.focus()}}),g.extend(v.controlConstructor,{nav_menu_location:v.Menus.MenuLocationControl,nav_menu_item:v.Menus.MenuItemControl,nav_menu:v.Menus.MenuControl,nav_menu_name:v.Menus.MenuNameControl,new_menu:v.Menus.NewMenuControl,nav_menu_locations:v.Menus.MenuLocationsControl,nav_menu_auto_add:v.Menus.MenuAutoAddControl}),g.extend(v.panelConstructor,{nav_menus:v.Menus.MenusPanel}),g.extend(v.sectionConstructor,{nav_menu:v.Menus.MenuSection,new_menu:v.Menus.NewMenuSection}),v.bind("ready",function(){v.Menus.availableMenuItemsPanel=new v.Menus.AvailableMenuItemsPanelView({collection:v.Menus.availableMenuItems}),v.bind("saved",function(e){(e.nav_menu_updates||e.nav_menu_item_updates)&&v.Menus.applySavedData(e)}),v.state("changesetStatus").bind(function(e){"publish"===e&&(v("nav_menus_created_posts")._value=[])}),v.previewer.bind("focus-nav-menu-item-control",v.Menus.focusMenuItemControl)}),v.Menus.applySavedData=function(e){var f={},u={};_(e.nav_menu_updates).each(function(i){var e,t,n,a,o,s,r,u,d,c,l,m,p;if("inserted"===i.status){if(!i.previous_term_id)throw new Error("Expected previous_term_id");if(!i.term_id)throw new Error("Expected term_id");if(e="nav_menu["+String(i.previous_term_id)+"]",!v.has(e))throw new Error("Expected setting to exist: "+e);if(a=v(e),!v.section.has(e))throw new Error("Expected control to exist: "+e);if(u=v.section(e),!(r=a.get()))throw new Error("Did not expect setting to be empty (deleted).");r=g.extend(_.clone(r),i.saved_value),f[i.previous_term_id]=i.term_id,t="nav_menu["+String(i.term_id)+"]",o=v.create(t,t,r,{type:"nav_menu",transport:v.Menus.data.settingTransport,previewer:v.previewer}),(p=u.expanded())&&u.collapse(),d=new v.Menus.MenuSection(t,{panel:"nav_menus",title:r.name,customizeAction:v.Menus.data.l10n.customizingMenus,type:"nav_menu",priority:u.priority.get(),menu_id:i.term_id}),v.section.add(d),v.control.each(function(e){var t,n;e.extended(v.controlConstructor.widget_form)&&"nav_menu"===e.params.widget_id_base&&(n=(t=e.container.find("select")).find("option[value="+String(i.previous_term_id)+"]"),t.find("option[value="+String(i.term_id)+"]").prop("selected",n.prop("selected")),n.remove())}),a.callbacks.disable(),a.set(!1),a.preview(),o.preview(),a._dirty=!1,u.container.remove(),v.section.remove(e),m=0,v.each(function(e){/^nav_menu\[/.test(e.id)&&!1!==e()&&(m+=1)}),(l=g("#available-widgets-list .widget-tpl:has( input.id_base[ value=nav_menu ] )")).find(".nav-menu-widget-form-controls:first").toggle(0!==m),l.find(".nav-menu-widget-no-menus-message:first").toggle(0===m),l.find("option[value="+String(i.previous_term_id)+"]").remove(),h.customize.control.each(function(e){/^nav_menu_locations\[/.test(e.id)&&e.container.find("option[value="+String(i.previous_term_id)+"]").remove()}),v.each(function(e){var t=v.state("saved").get();/^nav_menu_locations\[/.test(e.id)&&e.get()===i.previous_term_id&&(e.set(i.term_id),e._dirty=!1,v.state("saved").set(t),e.preview())}),p&&d.expand()}else if("updated"===i.status){if(n="nav_menu["+String(i.term_id)+"]",!v.has(n))throw new Error("Expected setting to exist: "+n);s=v(n),_.isEqual(i.saved_value,s.get())||(c=v.state("saved").get(),s.set(i.saved_value),s._dirty=!1,v.state("saved").set(c))}}),_(e.nav_menu_item_updates).each(function(e){e.previous_post_id&&(u[e.previous_post_id]=e.post_id)}),_(e.nav_menu_item_updates).each(function(e){var t,n,i,a,o,s,r;if("inserted"===e.status){if(!e.previous_post_id)throw new Error("Expected previous_post_id");if(!e.post_id)throw new Error("Expected post_id");if(t="nav_menu_item["+String(e.previous_post_id)+"]",!v.has(t))throw new Error("Expected setting to exist: "+t);if(i=v(t),!v.control.has(t))throw new Error("Expected control to exist: "+t);if(s=v.control(t),!(o=i.get()))throw new Error("Did not expect setting to be empty (deleted).");if((o=_.clone(o)).menu_item_parent<0){if(!u[o.menu_item_parent])throw new Error("inserted ID for menu_item_parent not available");o.menu_item_parent=u[o.menu_item_parent]}f[o.nav_menu_term_id]&&(o.nav_menu_term_id=f[o.nav_menu_term_id]),n="nav_menu_item["+String(e.post_id)+"]",a=v.create(n,n,o,{type:"nav_menu_item",transport:v.Menus.data.settingTransport,previewer:v.previewer}),r=new v.controlConstructor.nav_menu_item(n,{type:"nav_menu_item",menu_id:e.post_id,section:"nav_menu["+String(o.nav_menu_term_id)+"]",priority:s.priority.get(),settings:{default:n},menu_item_id:e.post_id}),s.container.remove(),v.control.remove(t),v.control.add(r),i.callbacks.disable(),i.set(!1),i.preview(),a.preview(),i._dirty=!1,r.container.toggleClass("menu-item-edit-inactive",s.container.hasClass("menu-item-edit-inactive"))}}),_.each(e.widget_nav_menu_updates,function(e,t){var n=v(t);n&&(n._value=e,n.preview())})},v.Menus.focusMenuItemControl=function(e){var t=v.Menus.getMenuItemControl(e);t&&t.focus()},v.Menus.getMenuControl=function(e){return v.control("nav_menu["+e+"]")},v.Menus.getMenuItemControl=function(e){return v.control(function(e){return"nav_menu_item["+e+"]"}(e))}}(wp.customize,wp,jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/customize-widgets.js b/srcs/wordpress/wp-admin/js/customize-widgets.js deleted file mode 100644 index 1506a31..0000000 --- a/srcs/wordpress/wp-admin/js/customize-widgets.js +++ /dev/null @@ -1,2368 +0,0 @@ -/** - * @output wp-admin/js/customize-widgets.js - */ - -/* global _wpCustomizeWidgetsSettings */ -(function( wp, $ ){ - - if ( ! wp || ! wp.customize ) { return; } - - // Set up our namespace... - var api = wp.customize, - l10n; - - /** - * @namespace wp.customize.Widgets - */ - api.Widgets = api.Widgets || {}; - api.Widgets.savedWidgetIds = {}; - - // Link settings - api.Widgets.data = _wpCustomizeWidgetsSettings || {}; - l10n = api.Widgets.data.l10n; - - /** - * wp.customize.Widgets.WidgetModel - * - * A single widget model. - * - * @class wp.customize.Widgets.WidgetModel - * @augments Backbone.Model - */ - api.Widgets.WidgetModel = Backbone.Model.extend(/** @lends wp.customize.Widgets.WidgetModel.prototype */{ - id: null, - temp_id: null, - classname: null, - control_tpl: null, - description: null, - is_disabled: null, - is_multi: null, - multi_number: null, - name: null, - id_base: null, - transport: null, - params: [], - width: null, - height: null, - search_matched: true - }); - - /** - * wp.customize.Widgets.WidgetCollection - * - * Collection for widget models. - * - * @class wp.customize.Widgets.WidgetCollection - * @augments Backbone.Collection - */ - api.Widgets.WidgetCollection = Backbone.Collection.extend(/** @lends wp.customize.Widgets.WidgetCollection.prototype */{ - model: api.Widgets.WidgetModel, - - // Controls searching on the current widget collection - // and triggers an update event - doSearch: function( value ) { - - // Don't do anything if we've already done this search - // Useful because the search handler fires multiple times per keystroke - if ( this.terms === value ) { - return; - } - - // Updates terms with the value passed - this.terms = value; - - // If we have terms, run a search... - if ( this.terms.length > 0 ) { - this.search( this.terms ); - } - - // If search is blank, set all the widgets as they matched the search to reset the views. - if ( this.terms === '' ) { - this.each( function ( widget ) { - widget.set( 'search_matched', true ); - } ); - } - }, - - // Performs a search within the collection - // @uses RegExp - search: function( term ) { - var match, haystack; - - // Escape the term string for RegExp meta characters - term = term.replace( /[-\/\\^$*+?.()|[\]{}]/g, '\\$&' ); - - // Consider spaces as word delimiters and match the whole string - // so matching terms can be combined - term = term.replace( / /g, ')(?=.*' ); - match = new RegExp( '^(?=.*' + term + ').+', 'i' ); - - this.each( function ( data ) { - haystack = [ data.get( 'name' ), data.get( 'id' ), data.get( 'description' ) ].join( ' ' ); - data.set( 'search_matched', match.test( haystack ) ); - } ); - } - }); - api.Widgets.availableWidgets = new api.Widgets.WidgetCollection( api.Widgets.data.availableWidgets ); - - /** - * wp.customize.Widgets.SidebarModel - * - * A single sidebar model. - * - * @class wp.customize.Widgets.SidebarModel - * @augments Backbone.Model - */ - api.Widgets.SidebarModel = Backbone.Model.extend(/** @lends wp.customize.Widgets.SidebarModel.prototype */{ - after_title: null, - after_widget: null, - before_title: null, - before_widget: null, - 'class': null, - description: null, - id: null, - name: null, - is_rendered: false - }); - - /** - * wp.customize.Widgets.SidebarCollection - * - * Collection for sidebar models. - * - * @class wp.customize.Widgets.SidebarCollection - * @augments Backbone.Collection - */ - api.Widgets.SidebarCollection = Backbone.Collection.extend(/** @lends wp.customize.Widgets.SidebarCollection.prototype */{ - model: api.Widgets.SidebarModel - }); - api.Widgets.registeredSidebars = new api.Widgets.SidebarCollection( api.Widgets.data.registeredSidebars ); - - api.Widgets.AvailableWidgetsPanelView = wp.Backbone.View.extend(/** @lends wp.customize.Widgets.AvailableWidgetsPanelView.prototype */{ - - el: '#available-widgets', - - events: { - 'input #widgets-search': 'search', - 'focus .widget-tpl' : 'focus', - 'click .widget-tpl' : '_submit', - 'keypress .widget-tpl' : '_submit', - 'keydown' : 'keyboardAccessible' - }, - - // Cache current selected widget - selected: null, - - // Cache sidebar control which has opened panel - currentSidebarControl: null, - $search: null, - $clearResults: null, - searchMatchesCount: null, - - /** - * View class for the available widgets panel. - * - * @constructs wp.customize.Widgets.AvailableWidgetsPanelView - * @augments wp.Backbone.View - */ - initialize: function() { - var self = this; - - this.$search = $( '#widgets-search' ); - - this.$clearResults = this.$el.find( '.clear-results' ); - - _.bindAll( this, 'close' ); - - this.listenTo( this.collection, 'change', this.updateList ); - - this.updateList(); - - // Set the initial search count to the number of available widgets. - this.searchMatchesCount = this.collection.length; - - // If the available widgets panel is open and the customize controls are - // interacted with (i.e. available widgets panel is blurred) then close the - // available widgets panel. Also close on back button click. - $( '#customize-controls, #available-widgets .customize-section-title' ).on( 'click keydown', function( e ) { - var isAddNewBtn = $( e.target ).is( '.add-new-widget, .add-new-widget *' ); - if ( $( 'body' ).hasClass( 'adding-widget' ) && ! isAddNewBtn ) { - self.close(); - } - } ); - - // Clear the search results and trigger a new search. - this.$clearResults.on( 'click', function() { - self.$search.val( '' ).focus(); - self.collection.doSearch( '' ); - } ); - - // Close the panel if the URL in the preview changes - api.previewer.bind( 'url', this.close ); - }, - - /** - * Performs a search and handles selected widget. - */ - search: _.debounce( function( event ) { - var firstVisible; - - this.collection.doSearch( event.target.value ); - // Update the search matches count. - this.updateSearchMatchesCount(); - // Announce how many search results. - this.announceSearchMatches(); - - // Remove a widget from being selected if it is no longer visible - if ( this.selected && ! this.selected.is( ':visible' ) ) { - this.selected.removeClass( 'selected' ); - this.selected = null; - } - - // If a widget was selected but the filter value has been cleared out, clear selection - if ( this.selected && ! event.target.value ) { - this.selected.removeClass( 'selected' ); - this.selected = null; - } - - // If a filter has been entered and a widget hasn't been selected, select the first one shown - if ( ! this.selected && event.target.value ) { - firstVisible = this.$el.find( '> .widget-tpl:visible:first' ); - if ( firstVisible.length ) { - this.select( firstVisible ); - } - } - - // Toggle the clear search results button. - if ( '' !== event.target.value ) { - this.$clearResults.addClass( 'is-visible' ); - } else if ( '' === event.target.value ) { - this.$clearResults.removeClass( 'is-visible' ); - } - - // Set a CSS class on the search container when there are no search results. - if ( ! this.searchMatchesCount ) { - this.$el.addClass( 'no-widgets-found' ); - } else { - this.$el.removeClass( 'no-widgets-found' ); - } - }, 500 ), - - /** - * Updates the count of the available widgets that have the `search_matched` attribute. - */ - updateSearchMatchesCount: function() { - this.searchMatchesCount = this.collection.where({ search_matched: true }).length; - }, - - /** - * Sends a message to the aria-live region to announce how many search results. - */ - announceSearchMatches: function() { - var message = l10n.widgetsFound.replace( '%d', this.searchMatchesCount ) ; - - if ( ! this.searchMatchesCount ) { - message = l10n.noWidgetsFound; - } - - wp.a11y.speak( message ); - }, - - /** - * Changes visibility of available widgets. - */ - updateList: function() { - this.collection.each( function( widget ) { - var widgetTpl = $( '#widget-tpl-' + widget.id ); - widgetTpl.toggle( widget.get( 'search_matched' ) && ! widget.get( 'is_disabled' ) ); - if ( widget.get( 'is_disabled' ) && widgetTpl.is( this.selected ) ) { - this.selected = null; - } - } ); - }, - - /** - * Highlights a widget. - */ - select: function( widgetTpl ) { - this.selected = $( widgetTpl ); - this.selected.siblings( '.widget-tpl' ).removeClass( 'selected' ); - this.selected.addClass( 'selected' ); - }, - - /** - * Highlights a widget on focus. - */ - focus: function( event ) { - this.select( $( event.currentTarget ) ); - }, - - /** - * Handles submit for keypress and click on widget. - */ - _submit: function( event ) { - // Only proceed with keypress if it is Enter or Spacebar - if ( event.type === 'keypress' && ( event.which !== 13 && event.which !== 32 ) ) { - return; - } - - this.submit( $( event.currentTarget ) ); - }, - - /** - * Adds a selected widget to the sidebar. - */ - submit: function( widgetTpl ) { - var widgetId, widget, widgetFormControl; - - if ( ! widgetTpl ) { - widgetTpl = this.selected; - } - - if ( ! widgetTpl || ! this.currentSidebarControl ) { - return; - } - - this.select( widgetTpl ); - - widgetId = $( this.selected ).data( 'widget-id' ); - widget = this.collection.findWhere( { id: widgetId } ); - if ( ! widget ) { - return; - } - - widgetFormControl = this.currentSidebarControl.addWidget( widget.get( 'id_base' ) ); - if ( widgetFormControl ) { - widgetFormControl.focus(); - } - - this.close(); - }, - - /** - * Opens the panel. - */ - open: function( sidebarControl ) { - this.currentSidebarControl = sidebarControl; - - // Wide widget controls appear over the preview, and so they need to be collapsed when the panel opens - _( this.currentSidebarControl.getWidgetFormControls() ).each( function( control ) { - if ( control.params.is_wide ) { - control.collapseForm(); - } - } ); - - if ( api.section.has( 'publish_settings' ) ) { - api.section( 'publish_settings' ).collapse(); - } - - $( 'body' ).addClass( 'adding-widget' ); - - this.$el.find( '.selected' ).removeClass( 'selected' ); - - // Reset search - this.collection.doSearch( '' ); - - if ( ! api.settings.browser.mobile ) { - this.$search.focus(); - } - }, - - /** - * Closes the panel. - */ - close: function( options ) { - options = options || {}; - - if ( options.returnFocus && this.currentSidebarControl ) { - this.currentSidebarControl.container.find( '.add-new-widget' ).focus(); - } - - this.currentSidebarControl = null; - this.selected = null; - - $( 'body' ).removeClass( 'adding-widget' ); - - this.$search.val( '' ); - }, - - /** - * Adds keyboard accessiblity to the panel. - */ - keyboardAccessible: function( event ) { - var isEnter = ( event.which === 13 ), - isEsc = ( event.which === 27 ), - isDown = ( event.which === 40 ), - isUp = ( event.which === 38 ), - isTab = ( event.which === 9 ), - isShift = ( event.shiftKey ), - selected = null, - firstVisible = this.$el.find( '> .widget-tpl:visible:first' ), - lastVisible = this.$el.find( '> .widget-tpl:visible:last' ), - isSearchFocused = $( event.target ).is( this.$search ), - isLastWidgetFocused = $( event.target ).is( '.widget-tpl:visible:last' ); - - if ( isDown || isUp ) { - if ( isDown ) { - if ( isSearchFocused ) { - selected = firstVisible; - } else if ( this.selected && this.selected.nextAll( '.widget-tpl:visible' ).length !== 0 ) { - selected = this.selected.nextAll( '.widget-tpl:visible:first' ); - } - } else if ( isUp ) { - if ( isSearchFocused ) { - selected = lastVisible; - } else if ( this.selected && this.selected.prevAll( '.widget-tpl:visible' ).length !== 0 ) { - selected = this.selected.prevAll( '.widget-tpl:visible:first' ); - } - } - - this.select( selected ); - - if ( selected ) { - selected.focus(); - } else { - this.$search.focus(); - } - - return; - } - - // If enter pressed but nothing entered, don't do anything - if ( isEnter && ! this.$search.val() ) { - return; - } - - if ( isEnter ) { - this.submit(); - } else if ( isEsc ) { - this.close( { returnFocus: true } ); - } - - if ( this.currentSidebarControl && isTab && ( isShift && isSearchFocused || ! isShift && isLastWidgetFocused ) ) { - this.currentSidebarControl.container.find( '.add-new-widget' ).focus(); - event.preventDefault(); - } - } - }); - - /** - * Handlers for the widget-synced event, organized by widget ID base. - * Other widgets may provide their own update handlers by adding - * listeners for the widget-synced event. - * - * @alias wp.customize.Widgets.formSyncHandlers - */ - api.Widgets.formSyncHandlers = { - - /** - * @param {jQuery.Event} e - * @param {jQuery} widget - * @param {String} newForm - */ - rss: function( e, widget, newForm ) { - var oldWidgetError = widget.find( '.widget-error:first' ), - newWidgetError = $( '<div>' + newForm + '</div>' ).find( '.widget-error:first' ); - - if ( oldWidgetError.length && newWidgetError.length ) { - oldWidgetError.replaceWith( newWidgetError ); - } else if ( oldWidgetError.length ) { - oldWidgetError.remove(); - } else if ( newWidgetError.length ) { - widget.find( '.widget-content:first' ).prepend( newWidgetError ); - } - } - }; - - api.Widgets.WidgetControl = api.Control.extend(/** @lends wp.customize.Widgets.WidgetControl.prototype */{ - defaultExpandedArguments: { - duration: 'fast', - completeCallback: $.noop - }, - - /** - * wp.customize.Widgets.WidgetControl - * - * Customizer control for widgets. - * Note that 'widget_form' must match the WP_Widget_Form_Customize_Control::$type - * - * @since 4.1.0 - * - * @constructs wp.customize.Widgets.WidgetControl - * @augments wp.customize.Control - */ - initialize: function( id, options ) { - var control = this; - - control.widgetControlEmbedded = false; - control.widgetContentEmbedded = false; - control.expanded = new api.Value( false ); - control.expandedArgumentsQueue = []; - control.expanded.bind( function( expanded ) { - var args = control.expandedArgumentsQueue.shift(); - args = $.extend( {}, control.defaultExpandedArguments, args ); - control.onChangeExpanded( expanded, args ); - }); - control.altNotice = true; - - api.Control.prototype.initialize.call( control, id, options ); - }, - - /** - * Set up the control. - * - * @since 3.9.0 - */ - ready: function() { - var control = this; - - /* - * Embed a placeholder once the section is expanded. The full widget - * form content will be embedded once the control itself is expanded, - * and at this point the widget-added event will be triggered. - */ - if ( ! control.section() ) { - control.embedWidgetControl(); - } else { - api.section( control.section(), function( section ) { - var onExpanded = function( isExpanded ) { - if ( isExpanded ) { - control.embedWidgetControl(); - section.expanded.unbind( onExpanded ); - } - }; - if ( section.expanded() ) { - onExpanded( true ); - } else { - section.expanded.bind( onExpanded ); - } - } ); - } - }, - - /** - * Embed the .widget element inside the li container. - * - * @since 4.4.0 - */ - embedWidgetControl: function() { - var control = this, widgetControl; - - if ( control.widgetControlEmbedded ) { - return; - } - control.widgetControlEmbedded = true; - - widgetControl = $( control.params.widget_control ); - control.container.append( widgetControl ); - - control._setupModel(); - control._setupWideWidget(); - control._setupControlToggle(); - - control._setupWidgetTitle(); - control._setupReorderUI(); - control._setupHighlightEffects(); - control._setupUpdateUI(); - control._setupRemoveUI(); - }, - - /** - * Embed the actual widget form inside of .widget-content and finally trigger the widget-added event. - * - * @since 4.4.0 - */ - embedWidgetContent: function() { - var control = this, widgetContent; - - control.embedWidgetControl(); - if ( control.widgetContentEmbedded ) { - return; - } - control.widgetContentEmbedded = true; - - // Update the notification container element now that the widget content has been embedded. - control.notifications.container = control.getNotificationsContainerElement(); - control.notifications.render(); - - widgetContent = $( control.params.widget_content ); - control.container.find( '.widget-content:first' ).append( widgetContent ); - - /* - * Trigger widget-added event so that plugins can attach any event - * listeners and dynamic UI elements. - */ - $( document ).trigger( 'widget-added', [ control.container.find( '.widget:first' ) ] ); - - }, - - /** - * Handle changes to the setting - */ - _setupModel: function() { - var self = this, rememberSavedWidgetId; - - // Remember saved widgets so we know which to trash (move to inactive widgets sidebar) - rememberSavedWidgetId = function() { - api.Widgets.savedWidgetIds[self.params.widget_id] = true; - }; - api.bind( 'ready', rememberSavedWidgetId ); - api.bind( 'saved', rememberSavedWidgetId ); - - this._updateCount = 0; - this.isWidgetUpdating = false; - this.liveUpdateMode = true; - - // Update widget whenever model changes - this.setting.bind( function( to, from ) { - if ( ! _( from ).isEqual( to ) && ! self.isWidgetUpdating ) { - self.updateWidget( { instance: to } ); - } - } ); - }, - - /** - * Add special behaviors for wide widget controls - */ - _setupWideWidget: function() { - var self = this, $widgetInside, $widgetForm, $customizeSidebar, - $themeControlsContainer, positionWidget; - - if ( ! this.params.is_wide || $( window ).width() <= 640 /* max-width breakpoint in customize-controls.css */ ) { - return; - } - - $widgetInside = this.container.find( '.widget-inside' ); - $widgetForm = $widgetInside.find( '> .form' ); - $customizeSidebar = $( '.wp-full-overlay-sidebar-content:first' ); - this.container.addClass( 'wide-widget-control' ); - - this.container.find( '.form:first' ).css( { - 'max-width': this.params.width, - 'min-height': this.params.height - } ); - - /** - * Keep the widget-inside positioned so the top of fixed-positioned - * element is at the same top position as the widget-top. When the - * widget-top is scrolled out of view, keep the widget-top in view; - * likewise, don't allow the widget to drop off the bottom of the window. - * If a widget is too tall to fit in the window, don't let the height - * exceed the window height so that the contents of the widget control - * will become scrollable (overflow:auto). - */ - positionWidget = function() { - var offsetTop = self.container.offset().top, - windowHeight = $( window ).height(), - formHeight = $widgetForm.outerHeight(), - top; - $widgetInside.css( 'max-height', windowHeight ); - top = Math.max( - 0, // prevent top from going off screen - Math.min( - Math.max( offsetTop, 0 ), // distance widget in panel is from top of screen - windowHeight - formHeight // flush up against bottom of screen - ) - ); - $widgetInside.css( 'top', top ); - }; - - $themeControlsContainer = $( '#customize-theme-controls' ); - this.container.on( 'expand', function() { - positionWidget(); - $customizeSidebar.on( 'scroll', positionWidget ); - $( window ).on( 'resize', positionWidget ); - $themeControlsContainer.on( 'expanded collapsed', positionWidget ); - } ); - this.container.on( 'collapsed', function() { - $customizeSidebar.off( 'scroll', positionWidget ); - $( window ).off( 'resize', positionWidget ); - $themeControlsContainer.off( 'expanded collapsed', positionWidget ); - } ); - - // Reposition whenever a sidebar's widgets are changed - api.each( function( setting ) { - if ( 0 === setting.id.indexOf( 'sidebars_widgets[' ) ) { - setting.bind( function() { - if ( self.container.hasClass( 'expanded' ) ) { - positionWidget(); - } - } ); - } - } ); - }, - - /** - * Show/hide the control when clicking on the form title, when clicking - * the close button - */ - _setupControlToggle: function() { - var self = this, $closeBtn; - - this.container.find( '.widget-top' ).on( 'click', function( e ) { - e.preventDefault(); - var sidebarWidgetsControl = self.getSidebarWidgetsControl(); - if ( sidebarWidgetsControl.isReordering ) { - return; - } - self.expanded( ! self.expanded() ); - } ); - - $closeBtn = this.container.find( '.widget-control-close' ); - $closeBtn.on( 'click', function() { - self.collapse(); - self.container.find( '.widget-top .widget-action:first' ).focus(); // keyboard accessibility - } ); - }, - - /** - * Update the title of the form if a title field is entered - */ - _setupWidgetTitle: function() { - var self = this, updateTitle; - - updateTitle = function() { - var title = self.setting().title, - inWidgetTitle = self.container.find( '.in-widget-title' ); - - if ( title ) { - inWidgetTitle.text( ': ' + title ); - } else { - inWidgetTitle.text( '' ); - } - }; - this.setting.bind( updateTitle ); - updateTitle(); - }, - - /** - * Set up the widget-reorder-nav - */ - _setupReorderUI: function() { - var self = this, selectSidebarItem, $moveWidgetArea, - $reorderNav, updateAvailableSidebars, template; - - /** - * select the provided sidebar list item in the move widget area - * - * @param {jQuery} li - */ - selectSidebarItem = function( li ) { - li.siblings( '.selected' ).removeClass( 'selected' ); - li.addClass( 'selected' ); - var isSelfSidebar = ( li.data( 'id' ) === self.params.sidebar_id ); - self.container.find( '.move-widget-btn' ).prop( 'disabled', isSelfSidebar ); - }; - - /** - * Add the widget reordering elements to the widget control - */ - this.container.find( '.widget-title-action' ).after( $( api.Widgets.data.tpl.widgetReorderNav ) ); - - - template = _.template( api.Widgets.data.tpl.moveWidgetArea ); - $moveWidgetArea = $( template( { - sidebars: _( api.Widgets.registeredSidebars.toArray() ).pluck( 'attributes' ) - } ) - ); - this.container.find( '.widget-top' ).after( $moveWidgetArea ); - - /** - * Update available sidebars when their rendered state changes - */ - updateAvailableSidebars = function() { - var $sidebarItems = $moveWidgetArea.find( 'li' ), selfSidebarItem, - renderedSidebarCount = 0; - - selfSidebarItem = $sidebarItems.filter( function(){ - return $( this ).data( 'id' ) === self.params.sidebar_id; - } ); - - $sidebarItems.each( function() { - var li = $( this ), - sidebarId, sidebar, sidebarIsRendered; - - sidebarId = li.data( 'id' ); - sidebar = api.Widgets.registeredSidebars.get( sidebarId ); - sidebarIsRendered = sidebar.get( 'is_rendered' ); - - li.toggle( sidebarIsRendered ); - - if ( sidebarIsRendered ) { - renderedSidebarCount += 1; - } - - if ( li.hasClass( 'selected' ) && ! sidebarIsRendered ) { - selectSidebarItem( selfSidebarItem ); - } - } ); - - if ( renderedSidebarCount > 1 ) { - self.container.find( '.move-widget' ).show(); - } else { - self.container.find( '.move-widget' ).hide(); - } - }; - - updateAvailableSidebars(); - api.Widgets.registeredSidebars.on( 'change:is_rendered', updateAvailableSidebars ); - - /** - * Handle clicks for up/down/move on the reorder nav - */ - $reorderNav = this.container.find( '.widget-reorder-nav' ); - $reorderNav.find( '.move-widget, .move-widget-down, .move-widget-up' ).each( function() { - $( this ).prepend( self.container.find( '.widget-title' ).text() + ': ' ); - } ).on( 'click keypress', function( event ) { - if ( event.type === 'keypress' && ( event.which !== 13 && event.which !== 32 ) ) { - return; - } - $( this ).focus(); - - if ( $( this ).is( '.move-widget' ) ) { - self.toggleWidgetMoveArea(); - } else { - var isMoveDown = $( this ).is( '.move-widget-down' ), - isMoveUp = $( this ).is( '.move-widget-up' ), - i = self.getWidgetSidebarPosition(); - - if ( ( isMoveUp && i === 0 ) || ( isMoveDown && i === self.getSidebarWidgetsControl().setting().length - 1 ) ) { - return; - } - - if ( isMoveUp ) { - self.moveUp(); - wp.a11y.speak( l10n.widgetMovedUp ); - } else { - self.moveDown(); - wp.a11y.speak( l10n.widgetMovedDown ); - } - - $( this ).focus(); // re-focus after the container was moved - } - } ); - - /** - * Handle selecting a sidebar to move to - */ - this.container.find( '.widget-area-select' ).on( 'click keypress', 'li', function( event ) { - if ( event.type === 'keypress' && ( event.which !== 13 && event.which !== 32 ) ) { - return; - } - event.preventDefault(); - selectSidebarItem( $( this ) ); - } ); - - /** - * Move widget to another sidebar - */ - this.container.find( '.move-widget-btn' ).click( function() { - self.getSidebarWidgetsControl().toggleReordering( false ); - - var oldSidebarId = self.params.sidebar_id, - newSidebarId = self.container.find( '.widget-area-select li.selected' ).data( 'id' ), - oldSidebarWidgetsSetting, newSidebarWidgetsSetting, - oldSidebarWidgetIds, newSidebarWidgetIds, i; - - oldSidebarWidgetsSetting = api( 'sidebars_widgets[' + oldSidebarId + ']' ); - newSidebarWidgetsSetting = api( 'sidebars_widgets[' + newSidebarId + ']' ); - oldSidebarWidgetIds = Array.prototype.slice.call( oldSidebarWidgetsSetting() ); - newSidebarWidgetIds = Array.prototype.slice.call( newSidebarWidgetsSetting() ); - - i = self.getWidgetSidebarPosition(); - oldSidebarWidgetIds.splice( i, 1 ); - newSidebarWidgetIds.push( self.params.widget_id ); - - oldSidebarWidgetsSetting( oldSidebarWidgetIds ); - newSidebarWidgetsSetting( newSidebarWidgetIds ); - - self.focus(); - } ); - }, - - /** - * Highlight widgets in preview when interacted with in the Customizer - */ - _setupHighlightEffects: function() { - var self = this; - - // Highlight whenever hovering or clicking over the form - this.container.on( 'mouseenter click', function() { - self.setting.previewer.send( 'highlight-widget', self.params.widget_id ); - } ); - - // Highlight when the setting is updated - this.setting.bind( function() { - self.setting.previewer.send( 'highlight-widget', self.params.widget_id ); - } ); - }, - - /** - * Set up event handlers for widget updating - */ - _setupUpdateUI: function() { - var self = this, $widgetRoot, $widgetContent, - $saveBtn, updateWidgetDebounced, formSyncHandler; - - $widgetRoot = this.container.find( '.widget:first' ); - $widgetContent = $widgetRoot.find( '.widget-content:first' ); - - // Configure update button - $saveBtn = this.container.find( '.widget-control-save' ); - $saveBtn.val( l10n.saveBtnLabel ); - $saveBtn.attr( 'title', l10n.saveBtnTooltip ); - $saveBtn.removeClass( 'button-primary' ); - $saveBtn.on( 'click', function( e ) { - e.preventDefault(); - self.updateWidget( { disable_form: true } ); // @todo disable_form is unused? - } ); - - updateWidgetDebounced = _.debounce( function() { - self.updateWidget(); - }, 250 ); - - // Trigger widget form update when hitting Enter within an input - $widgetContent.on( 'keydown', 'input', function( e ) { - if ( 13 === e.which ) { // Enter - e.preventDefault(); - self.updateWidget( { ignoreActiveElement: true } ); - } - } ); - - // Handle widgets that support live previews - $widgetContent.on( 'change input propertychange', ':input', function( e ) { - if ( ! self.liveUpdateMode ) { - return; - } - if ( e.type === 'change' || ( this.checkValidity && this.checkValidity() ) ) { - updateWidgetDebounced(); - } - } ); - - // Remove loading indicators when the setting is saved and the preview updates - this.setting.previewer.channel.bind( 'synced', function() { - self.container.removeClass( 'previewer-loading' ); - } ); - - api.previewer.bind( 'widget-updated', function( updatedWidgetId ) { - if ( updatedWidgetId === self.params.widget_id ) { - self.container.removeClass( 'previewer-loading' ); - } - } ); - - formSyncHandler = api.Widgets.formSyncHandlers[ this.params.widget_id_base ]; - if ( formSyncHandler ) { - $( document ).on( 'widget-synced', function( e, widget ) { - if ( $widgetRoot.is( widget ) ) { - formSyncHandler.apply( document, arguments ); - } - } ); - } - }, - - /** - * Update widget control to indicate whether it is currently rendered. - * - * Overrides api.Control.toggle() - * - * @since 4.1.0 - * - * @param {Boolean} active - * @param {Object} args - * @param {function} args.completeCallback - */ - onChangeActive: function ( active, args ) { - // Note: there is a second 'args' parameter being passed, merged on top of this.defaultActiveArguments - this.container.toggleClass( 'widget-rendered', active ); - if ( args.completeCallback ) { - args.completeCallback(); - } - }, - - /** - * Set up event handlers for widget removal - */ - _setupRemoveUI: function() { - var self = this, $removeBtn, replaceDeleteWithRemove; - - // Configure remove button - $removeBtn = this.container.find( '.widget-control-remove' ); - $removeBtn.on( 'click', function() { - // Find an adjacent element to add focus to when this widget goes away - var $adjacentFocusTarget; - if ( self.container.next().is( '.customize-control-widget_form' ) ) { - $adjacentFocusTarget = self.container.next().find( '.widget-action:first' ); - } else if ( self.container.prev().is( '.customize-control-widget_form' ) ) { - $adjacentFocusTarget = self.container.prev().find( '.widget-action:first' ); - } else { - $adjacentFocusTarget = self.container.next( '.customize-control-sidebar_widgets' ).find( '.add-new-widget:first' ); - } - - self.container.slideUp( function() { - var sidebarsWidgetsControl = api.Widgets.getSidebarWidgetControlContainingWidget( self.params.widget_id ), - sidebarWidgetIds, i; - - if ( ! sidebarsWidgetsControl ) { - return; - } - - sidebarWidgetIds = sidebarsWidgetsControl.setting().slice(); - i = _.indexOf( sidebarWidgetIds, self.params.widget_id ); - if ( -1 === i ) { - return; - } - - sidebarWidgetIds.splice( i, 1 ); - sidebarsWidgetsControl.setting( sidebarWidgetIds ); - - $adjacentFocusTarget.focus(); // keyboard accessibility - } ); - } ); - - replaceDeleteWithRemove = function() { - $removeBtn.text( l10n.removeBtnLabel ); // wp_widget_control() outputs the button as "Delete" - $removeBtn.attr( 'title', l10n.removeBtnTooltip ); - }; - - if ( this.params.is_new ) { - api.bind( 'saved', replaceDeleteWithRemove ); - } else { - replaceDeleteWithRemove(); - } - }, - - /** - * Find all inputs in a widget container that should be considered when - * comparing the loaded form with the sanitized form, whose fields will - * be aligned to copy the sanitized over. The elements returned by this - * are passed into this._getInputsSignature(), and they are iterated - * over when copying sanitized values over to the form loaded. - * - * @param {jQuery} container element in which to look for inputs - * @returns {jQuery} inputs - * @private - */ - _getInputs: function( container ) { - return $( container ).find( ':input[name]' ); - }, - - /** - * Iterate over supplied inputs and create a signature string for all of them together. - * This string can be used to compare whether or not the form has all of the same fields. - * - * @param {jQuery} inputs - * @returns {string} - * @private - */ - _getInputsSignature: function( inputs ) { - var inputsSignatures = _( inputs ).map( function( input ) { - var $input = $( input ), signatureParts; - - if ( $input.is( ':checkbox, :radio' ) ) { - signatureParts = [ $input.attr( 'id' ), $input.attr( 'name' ), $input.prop( 'value' ) ]; - } else { - signatureParts = [ $input.attr( 'id' ), $input.attr( 'name' ) ]; - } - - return signatureParts.join( ',' ); - } ); - - return inputsSignatures.join( ';' ); - }, - - /** - * Get the state for an input depending on its type. - * - * @param {jQuery|Element} input - * @returns {string|boolean|array|*} - * @private - */ - _getInputState: function( input ) { - input = $( input ); - if ( input.is( ':radio, :checkbox' ) ) { - return input.prop( 'checked' ); - } else if ( input.is( 'select[multiple]' ) ) { - return input.find( 'option:selected' ).map( function () { - return $( this ).val(); - } ).get(); - } else { - return input.val(); - } - }, - - /** - * Update an input's state based on its type. - * - * @param {jQuery|Element} input - * @param {string|boolean|array|*} state - * @private - */ - _setInputState: function ( input, state ) { - input = $( input ); - if ( input.is( ':radio, :checkbox' ) ) { - input.prop( 'checked', state ); - } else if ( input.is( 'select[multiple]' ) ) { - if ( ! $.isArray( state ) ) { - state = []; - } else { - // Make sure all state items are strings since the DOM value is a string - state = _.map( state, function ( value ) { - return String( value ); - } ); - } - input.find( 'option' ).each( function () { - $( this ).prop( 'selected', -1 !== _.indexOf( state, String( this.value ) ) ); - } ); - } else { - input.val( state ); - } - }, - - /*********************************************************************** - * Begin public API methods - **********************************************************************/ - - /** - * @return {wp.customize.controlConstructor.sidebar_widgets[]} - */ - getSidebarWidgetsControl: function() { - var settingId, sidebarWidgetsControl; - - settingId = 'sidebars_widgets[' + this.params.sidebar_id + ']'; - sidebarWidgetsControl = api.control( settingId ); - - if ( ! sidebarWidgetsControl ) { - return; - } - - return sidebarWidgetsControl; - }, - - /** - * Submit the widget form via Ajax and get back the updated instance, - * along with the new widget control form to render. - * - * @param {object} [args] - * @param {Object|null} [args.instance=null] When the model changes, the instance is sent here; otherwise, the inputs from the form are used - * @param {Function|null} [args.complete=null] Function which is called when the request finishes. Context is bound to the control. First argument is any error. Following arguments are for success. - * @param {Boolean} [args.ignoreActiveElement=false] Whether or not updating a field will be deferred if focus is still on the element. - */ - updateWidget: function( args ) { - var self = this, instanceOverride, completeCallback, $widgetRoot, $widgetContent, - updateNumber, params, data, $inputs, processing, jqxhr, isChanged; - - // The updateWidget logic requires that the form fields to be fully present. - self.embedWidgetContent(); - - args = $.extend( { - instance: null, - complete: null, - ignoreActiveElement: false - }, args ); - - instanceOverride = args.instance; - completeCallback = args.complete; - - this._updateCount += 1; - updateNumber = this._updateCount; - - $widgetRoot = this.container.find( '.widget:first' ); - $widgetContent = $widgetRoot.find( '.widget-content:first' ); - - // Remove a previous error message - $widgetContent.find( '.widget-error' ).remove(); - - this.container.addClass( 'widget-form-loading' ); - this.container.addClass( 'previewer-loading' ); - processing = api.state( 'processing' ); - processing( processing() + 1 ); - - if ( ! this.liveUpdateMode ) { - this.container.addClass( 'widget-form-disabled' ); - } - - params = {}; - params.action = 'update-widget'; - params.wp_customize = 'on'; - params.nonce = api.settings.nonce['update-widget']; - params.customize_theme = api.settings.theme.stylesheet; - params.customized = wp.customize.previewer.query().customized; - - data = $.param( params ); - $inputs = this._getInputs( $widgetContent ); - - // Store the value we're submitting in data so that when the response comes back, - // we know if it got sanitized; if there is no difference in the sanitized value, - // then we do not need to touch the UI and mess up the user's ongoing editing. - $inputs.each( function() { - $( this ).data( 'state' + updateNumber, self._getInputState( this ) ); - } ); - - if ( instanceOverride ) { - data += '&' + $.param( { 'sanitized_widget_setting': JSON.stringify( instanceOverride ) } ); - } else { - data += '&' + $inputs.serialize(); - } - data += '&' + $widgetContent.find( '~ :input' ).serialize(); - - if ( this._previousUpdateRequest ) { - this._previousUpdateRequest.abort(); - } - jqxhr = $.post( wp.ajax.settings.url, data ); - this._previousUpdateRequest = jqxhr; - - jqxhr.done( function( r ) { - var message, sanitizedForm, $sanitizedInputs, hasSameInputsInResponse, - isLiveUpdateAborted = false; - - // Check if the user is logged out. - if ( '0' === r ) { - api.previewer.preview.iframe.hide(); - api.previewer.login().done( function() { - self.updateWidget( args ); - api.previewer.preview.iframe.show(); - } ); - return; - } - - // Check for cheaters. - if ( '-1' === r ) { - api.previewer.cheatin(); - return; - } - - if ( r.success ) { - sanitizedForm = $( '<div>' + r.data.form + '</div>' ); - $sanitizedInputs = self._getInputs( sanitizedForm ); - hasSameInputsInResponse = self._getInputsSignature( $inputs ) === self._getInputsSignature( $sanitizedInputs ); - - // Restore live update mode if sanitized fields are now aligned with the existing fields - if ( hasSameInputsInResponse && ! self.liveUpdateMode ) { - self.liveUpdateMode = true; - self.container.removeClass( 'widget-form-disabled' ); - self.container.find( 'input[name="savewidget"]' ).hide(); - } - - // Sync sanitized field states to existing fields if they are aligned - if ( hasSameInputsInResponse && self.liveUpdateMode ) { - $inputs.each( function( i ) { - var $input = $( this ), - $sanitizedInput = $( $sanitizedInputs[i] ), - submittedState, sanitizedState, canUpdateState; - - submittedState = $input.data( 'state' + updateNumber ); - sanitizedState = self._getInputState( $sanitizedInput ); - $input.data( 'sanitized', sanitizedState ); - - canUpdateState = ( ! _.isEqual( submittedState, sanitizedState ) && ( args.ignoreActiveElement || ! $input.is( document.activeElement ) ) ); - if ( canUpdateState ) { - self._setInputState( $input, sanitizedState ); - } - } ); - - $( document ).trigger( 'widget-synced', [ $widgetRoot, r.data.form ] ); - - // Otherwise, if sanitized fields are not aligned with existing fields, disable live update mode if enabled - } else if ( self.liveUpdateMode ) { - self.liveUpdateMode = false; - self.container.find( 'input[name="savewidget"]' ).show(); - isLiveUpdateAborted = true; - - // Otherwise, replace existing form with the sanitized form - } else { - $widgetContent.html( r.data.form ); - - self.container.removeClass( 'widget-form-disabled' ); - - $( document ).trigger( 'widget-updated', [ $widgetRoot ] ); - } - - /** - * If the old instance is identical to the new one, there is nothing new - * needing to be rendered, and so we can preempt the event for the - * preview finishing loading. - */ - isChanged = ! isLiveUpdateAborted && ! _( self.setting() ).isEqual( r.data.instance ); - if ( isChanged ) { - self.isWidgetUpdating = true; // suppress triggering another updateWidget - self.setting( r.data.instance ); - self.isWidgetUpdating = false; - } else { - // no change was made, so stop the spinner now instead of when the preview would updates - self.container.removeClass( 'previewer-loading' ); - } - - if ( completeCallback ) { - completeCallback.call( self, null, { noChange: ! isChanged, ajaxFinished: true } ); - } - } else { - // General error message - message = l10n.error; - - if ( r.data && r.data.message ) { - message = r.data.message; - } - - if ( completeCallback ) { - completeCallback.call( self, message ); - } else { - $widgetContent.prepend( '<p class="widget-error"><strong>' + message + '</strong></p>' ); - } - } - } ); - - jqxhr.fail( function( jqXHR, textStatus ) { - if ( completeCallback ) { - completeCallback.call( self, textStatus ); - } - } ); - - jqxhr.always( function() { - self.container.removeClass( 'widget-form-loading' ); - - $inputs.each( function() { - $( this ).removeData( 'state' + updateNumber ); - } ); - - processing( processing() - 1 ); - } ); - }, - - /** - * Expand the accordion section containing a control - */ - expandControlSection: function() { - api.Control.prototype.expand.call( this ); - }, - - /** - * @since 4.1.0 - * - * @param {Boolean} expanded - * @param {Object} [params] - * @returns {Boolean} false if state already applied - */ - _toggleExpanded: api.Section.prototype._toggleExpanded, - - /** - * @since 4.1.0 - * - * @param {Object} [params] - * @returns {Boolean} false if already expanded - */ - expand: api.Section.prototype.expand, - - /** - * Expand the widget form control - * - * @deprecated 4.1.0 Use this.expand() instead. - */ - expandForm: function() { - this.expand(); - }, - - /** - * @since 4.1.0 - * - * @param {Object} [params] - * @returns {Boolean} false if already collapsed - */ - collapse: api.Section.prototype.collapse, - - /** - * Collapse the widget form control - * - * @deprecated 4.1.0 Use this.collapse() instead. - */ - collapseForm: function() { - this.collapse(); - }, - - /** - * Expand or collapse the widget control - * - * @deprecated this is poor naming, and it is better to directly set control.expanded( showOrHide ) - * - * @param {boolean|undefined} [showOrHide] If not supplied, will be inverse of current visibility - */ - toggleForm: function( showOrHide ) { - if ( typeof showOrHide === 'undefined' ) { - showOrHide = ! this.expanded(); - } - this.expanded( showOrHide ); - }, - - /** - * Respond to change in the expanded state. - * - * @param {Boolean} expanded - * @param {Object} args merged on top of this.defaultActiveArguments - */ - onChangeExpanded: function ( expanded, args ) { - var self = this, $widget, $inside, complete, prevComplete, expandControl, $toggleBtn; - - self.embedWidgetControl(); // Make sure the outer form is embedded so that the expanded state can be set in the UI. - if ( expanded ) { - self.embedWidgetContent(); - } - - // If the expanded state is unchanged only manipulate container expanded states - if ( args.unchanged ) { - if ( expanded ) { - api.Control.prototype.expand.call( self, { - completeCallback: args.completeCallback - }); - } - return; - } - - $widget = this.container.find( 'div.widget:first' ); - $inside = $widget.find( '.widget-inside:first' ); - $toggleBtn = this.container.find( '.widget-top button.widget-action' ); - - expandControl = function() { - - // Close all other widget controls before expanding this one - api.control.each( function( otherControl ) { - if ( self.params.type === otherControl.params.type && self !== otherControl ) { - otherControl.collapse(); - } - } ); - - complete = function() { - self.container.removeClass( 'expanding' ); - self.container.addClass( 'expanded' ); - $widget.addClass( 'open' ); - $toggleBtn.attr( 'aria-expanded', 'true' ); - self.container.trigger( 'expanded' ); - }; - if ( args.completeCallback ) { - prevComplete = complete; - complete = function () { - prevComplete(); - args.completeCallback(); - }; - } - - if ( self.params.is_wide ) { - $inside.fadeIn( args.duration, complete ); - } else { - $inside.slideDown( args.duration, complete ); - } - - self.container.trigger( 'expand' ); - self.container.addClass( 'expanding' ); - }; - - if ( expanded ) { - if ( api.section.has( self.section() ) ) { - api.section( self.section() ).expand( { - completeCallback: expandControl - } ); - } else { - expandControl(); - } - } else { - complete = function() { - self.container.removeClass( 'collapsing' ); - self.container.removeClass( 'expanded' ); - $widget.removeClass( 'open' ); - $toggleBtn.attr( 'aria-expanded', 'false' ); - self.container.trigger( 'collapsed' ); - }; - if ( args.completeCallback ) { - prevComplete = complete; - complete = function () { - prevComplete(); - args.completeCallback(); - }; - } - - self.container.trigger( 'collapse' ); - self.container.addClass( 'collapsing' ); - - if ( self.params.is_wide ) { - $inside.fadeOut( args.duration, complete ); - } else { - $inside.slideUp( args.duration, function() { - $widget.css( { width:'', margin:'' } ); - complete(); - } ); - } - } - }, - - /** - * Get the position (index) of the widget in the containing sidebar - * - * @returns {Number} - */ - getWidgetSidebarPosition: function() { - var sidebarWidgetIds, position; - - sidebarWidgetIds = this.getSidebarWidgetsControl().setting(); - position = _.indexOf( sidebarWidgetIds, this.params.widget_id ); - - if ( position === -1 ) { - return; - } - - return position; - }, - - /** - * Move widget up one in the sidebar - */ - moveUp: function() { - this._moveWidgetByOne( -1 ); - }, - - /** - * Move widget up one in the sidebar - */ - moveDown: function() { - this._moveWidgetByOne( 1 ); - }, - - /** - * @private - * - * @param {Number} offset 1|-1 - */ - _moveWidgetByOne: function( offset ) { - var i, sidebarWidgetsSetting, sidebarWidgetIds, adjacentWidgetId; - - i = this.getWidgetSidebarPosition(); - - sidebarWidgetsSetting = this.getSidebarWidgetsControl().setting; - sidebarWidgetIds = Array.prototype.slice.call( sidebarWidgetsSetting() ); // clone - adjacentWidgetId = sidebarWidgetIds[i + offset]; - sidebarWidgetIds[i + offset] = this.params.widget_id; - sidebarWidgetIds[i] = adjacentWidgetId; - - sidebarWidgetsSetting( sidebarWidgetIds ); - }, - - /** - * Toggle visibility of the widget move area - * - * @param {Boolean} [showOrHide] - */ - toggleWidgetMoveArea: function( showOrHide ) { - var self = this, $moveWidgetArea; - - $moveWidgetArea = this.container.find( '.move-widget-area' ); - - if ( typeof showOrHide === 'undefined' ) { - showOrHide = ! $moveWidgetArea.hasClass( 'active' ); - } - - if ( showOrHide ) { - // reset the selected sidebar - $moveWidgetArea.find( '.selected' ).removeClass( 'selected' ); - - $moveWidgetArea.find( 'li' ).filter( function() { - return $( this ).data( 'id' ) === self.params.sidebar_id; - } ).addClass( 'selected' ); - - this.container.find( '.move-widget-btn' ).prop( 'disabled', true ); - } - - $moveWidgetArea.toggleClass( 'active', showOrHide ); - }, - - /** - * Highlight the widget control and section - */ - highlightSectionAndControl: function() { - var $target; - - if ( this.container.is( ':hidden' ) ) { - $target = this.container.closest( '.control-section' ); - } else { - $target = this.container; - } - - $( '.highlighted' ).removeClass( 'highlighted' ); - $target.addClass( 'highlighted' ); - - setTimeout( function() { - $target.removeClass( 'highlighted' ); - }, 500 ); - } - } ); - - /** - * wp.customize.Widgets.WidgetsPanel - * - * Customizer panel containing the widget area sections. - * - * @since 4.4.0 - * - * @class wp.customize.Widgets.WidgetsPanel - * @augments wp.customize.Panel - */ - api.Widgets.WidgetsPanel = api.Panel.extend(/** @lends wp.customize.Widgets.WigetsPanel.prototype */{ - - /** - * Add and manage the display of the no-rendered-areas notice. - * - * @since 4.4.0 - */ - ready: function () { - var panel = this; - - api.Panel.prototype.ready.call( panel ); - - panel.deferred.embedded.done(function() { - var panelMetaContainer, noticeContainer, updateNotice, getActiveSectionCount, shouldShowNotice; - panelMetaContainer = panel.container.find( '.panel-meta' ); - - // @todo This should use the Notifications API introduced to panels. See <https://core.trac.wordpress.org/ticket/38794>. - noticeContainer = $( '<div></div>', { - 'class': 'no-widget-areas-rendered-notice' - }); - panelMetaContainer.append( noticeContainer ); - - /** - * Get the number of active sections in the panel. - * - * @return {number} Number of active sidebar sections. - */ - getActiveSectionCount = function() { - return _.filter( panel.sections(), function( section ) { - return 'sidebar' === section.params.type && section.active(); - } ).length; - }; - - /** - * Determine whether or not the notice should be displayed. - * - * @return {boolean} - */ - shouldShowNotice = function() { - var activeSectionCount = getActiveSectionCount(); - if ( 0 === activeSectionCount ) { - return true; - } else { - return activeSectionCount !== api.Widgets.data.registeredSidebars.length; - } - }; - - /** - * Update the notice. - * - * @returns {void} - */ - updateNotice = function() { - var activeSectionCount = getActiveSectionCount(), someRenderedMessage, nonRenderedAreaCount, registeredAreaCount; - noticeContainer.empty(); - - registeredAreaCount = api.Widgets.data.registeredSidebars.length; - if ( activeSectionCount !== registeredAreaCount ) { - - if ( 0 !== activeSectionCount ) { - nonRenderedAreaCount = registeredAreaCount - activeSectionCount; - someRenderedMessage = l10n.someAreasShown[ nonRenderedAreaCount ]; - } else { - someRenderedMessage = l10n.noAreasShown; - } - if ( someRenderedMessage ) { - noticeContainer.append( $( '<p></p>', { - text: someRenderedMessage - } ) ); - } - - noticeContainer.append( $( '<p></p>', { - text: l10n.navigatePreview - } ) ); - } - }; - updateNotice(); - - /* - * Set the initial visibility state for rendered notice. - * Update the visibility of the notice whenever a reflow happens. - */ - noticeContainer.toggle( shouldShowNotice() ); - api.previewer.deferred.active.done( function () { - noticeContainer.toggle( shouldShowNotice() ); - }); - api.bind( 'pane-contents-reflowed', function() { - var duration = ( 'resolved' === api.previewer.deferred.active.state() ) ? 'fast' : 0; - updateNotice(); - if ( shouldShowNotice() ) { - noticeContainer.slideDown( duration ); - } else { - noticeContainer.slideUp( duration ); - } - }); - }); - }, - - /** - * Allow an active widgets panel to be contextually active even when it has no active sections (widget areas). - * - * This ensures that the widgets panel appears even when there are no - * sidebars displayed on the URL currently being previewed. - * - * @since 4.4.0 - * - * @returns {boolean} - */ - isContextuallyActive: function() { - var panel = this; - return panel.active(); - } - }); - - /** - * wp.customize.Widgets.SidebarSection - * - * Customizer section representing a widget area widget - * - * @since 4.1.0 - * - * @class wp.customize.Widgets.SidebarSection - * @augments wp.customize.Section - */ - api.Widgets.SidebarSection = api.Section.extend(/** @lends wp.customize.Widgets.SidebarSection.prototype */{ - - /** - * Sync the section's active state back to the Backbone model's is_rendered attribute - * - * @since 4.1.0 - */ - ready: function () { - var section = this, registeredSidebar; - api.Section.prototype.ready.call( this ); - registeredSidebar = api.Widgets.registeredSidebars.get( section.params.sidebarId ); - section.active.bind( function ( active ) { - registeredSidebar.set( 'is_rendered', active ); - }); - registeredSidebar.set( 'is_rendered', section.active() ); - } - }); - - /** - * wp.customize.Widgets.SidebarControl - * - * Customizer control for widgets. - * Note that 'sidebar_widgets' must match the WP_Widget_Area_Customize_Control::$type - * - * @since 3.9.0 - * - * @class wp.customize.Widgets.SidebarControl - * @augments wp.customize.Control - */ - api.Widgets.SidebarControl = api.Control.extend(/** @lends wp.customize.Widgets.SidebarControl.prototype */{ - - /** - * Set up the control - */ - ready: function() { - this.$controlSection = this.container.closest( '.control-section' ); - this.$sectionContent = this.container.closest( '.accordion-section-content' ); - - this._setupModel(); - this._setupSortable(); - this._setupAddition(); - this._applyCardinalOrderClassNames(); - }, - - /** - * Update ordering of widget control forms when the setting is updated - */ - _setupModel: function() { - var self = this; - - this.setting.bind( function( newWidgetIds, oldWidgetIds ) { - var widgetFormControls, removedWidgetIds, priority; - - removedWidgetIds = _( oldWidgetIds ).difference( newWidgetIds ); - - // Filter out any persistent widget IDs for widgets which have been deactivated - newWidgetIds = _( newWidgetIds ).filter( function( newWidgetId ) { - var parsedWidgetId = parseWidgetId( newWidgetId ); - - return !! api.Widgets.availableWidgets.findWhere( { id_base: parsedWidgetId.id_base } ); - } ); - - widgetFormControls = _( newWidgetIds ).map( function( widgetId ) { - var widgetFormControl = api.Widgets.getWidgetFormControlForWidget( widgetId ); - - if ( ! widgetFormControl ) { - widgetFormControl = self.addWidget( widgetId ); - } - - return widgetFormControl; - } ); - - // Sort widget controls to their new positions - widgetFormControls.sort( function( a, b ) { - var aIndex = _.indexOf( newWidgetIds, a.params.widget_id ), - bIndex = _.indexOf( newWidgetIds, b.params.widget_id ); - return aIndex - bIndex; - }); - - priority = 0; - _( widgetFormControls ).each( function ( control ) { - control.priority( priority ); - control.section( self.section() ); - priority += 1; - }); - self.priority( priority ); // Make sure sidebar control remains at end - - // Re-sort widget form controls (including widgets form other sidebars newly moved here) - self._applyCardinalOrderClassNames(); - - // If the widget was dragged into the sidebar, make sure the sidebar_id param is updated - _( widgetFormControls ).each( function( widgetFormControl ) { - widgetFormControl.params.sidebar_id = self.params.sidebar_id; - } ); - - // Cleanup after widget removal - _( removedWidgetIds ).each( function( removedWidgetId ) { - - // Using setTimeout so that when moving a widget to another sidebar, the other sidebars_widgets settings get a chance to update - setTimeout( function() { - var removedControl, wasDraggedToAnotherSidebar, inactiveWidgets, removedIdBase, - widget, isPresentInAnotherSidebar = false; - - // Check if the widget is in another sidebar - api.each( function( otherSetting ) { - if ( otherSetting.id === self.setting.id || 0 !== otherSetting.id.indexOf( 'sidebars_widgets[' ) || otherSetting.id === 'sidebars_widgets[wp_inactive_widgets]' ) { - return; - } - - var otherSidebarWidgets = otherSetting(), i; - - i = _.indexOf( otherSidebarWidgets, removedWidgetId ); - if ( -1 !== i ) { - isPresentInAnotherSidebar = true; - } - } ); - - // If the widget is present in another sidebar, abort! - if ( isPresentInAnotherSidebar ) { - return; - } - - removedControl = api.Widgets.getWidgetFormControlForWidget( removedWidgetId ); - - // Detect if widget control was dragged to another sidebar - wasDraggedToAnotherSidebar = removedControl && $.contains( document, removedControl.container[0] ) && ! $.contains( self.$sectionContent[0], removedControl.container[0] ); - - // Delete any widget form controls for removed widgets - if ( removedControl && ! wasDraggedToAnotherSidebar ) { - api.control.remove( removedControl.id ); - removedControl.container.remove(); - } - - // Move widget to inactive widgets sidebar (move it to trash) if has been previously saved - // This prevents the inactive widgets sidebar from overflowing with throwaway widgets - if ( api.Widgets.savedWidgetIds[removedWidgetId] ) { - inactiveWidgets = api.value( 'sidebars_widgets[wp_inactive_widgets]' )().slice(); - inactiveWidgets.push( removedWidgetId ); - api.value( 'sidebars_widgets[wp_inactive_widgets]' )( _( inactiveWidgets ).unique() ); - } - - // Make old single widget available for adding again - removedIdBase = parseWidgetId( removedWidgetId ).id_base; - widget = api.Widgets.availableWidgets.findWhere( { id_base: removedIdBase } ); - if ( widget && ! widget.get( 'is_multi' ) ) { - widget.set( 'is_disabled', false ); - } - } ); - - } ); - } ); - }, - - /** - * Allow widgets in sidebar to be re-ordered, and for the order to be previewed - */ - _setupSortable: function() { - var self = this; - - this.isReordering = false; - - /** - * Update widget order setting when controls are re-ordered - */ - this.$sectionContent.sortable( { - items: '> .customize-control-widget_form', - handle: '.widget-top', - axis: 'y', - tolerance: 'pointer', - connectWith: '.accordion-section-content:has(.customize-control-sidebar_widgets)', - update: function() { - var widgetContainerIds = self.$sectionContent.sortable( 'toArray' ), widgetIds; - - widgetIds = $.map( widgetContainerIds, function( widgetContainerId ) { - return $( '#' + widgetContainerId ).find( ':input[name=widget-id]' ).val(); - } ); - - self.setting( widgetIds ); - } - } ); - - /** - * Expand other Customizer sidebar section when dragging a control widget over it, - * allowing the control to be dropped into another section - */ - this.$controlSection.find( '.accordion-section-title' ).droppable({ - accept: '.customize-control-widget_form', - over: function() { - var section = api.section( self.section.get() ); - section.expand({ - allowMultiple: true, // Prevent the section being dragged from to be collapsed - completeCallback: function () { - // @todo It is not clear when refreshPositions should be called on which sections, or if it is even needed - api.section.each( function ( otherSection ) { - if ( otherSection.container.find( '.customize-control-sidebar_widgets' ).length ) { - otherSection.container.find( '.accordion-section-content:first' ).sortable( 'refreshPositions' ); - } - } ); - } - }); - } - }); - - /** - * Keyboard-accessible reordering - */ - this.container.find( '.reorder-toggle' ).on( 'click', function() { - self.toggleReordering( ! self.isReordering ); - } ); - }, - - /** - * Set up UI for adding a new widget - */ - _setupAddition: function() { - var self = this; - - this.container.find( '.add-new-widget' ).on( 'click', function() { - var addNewWidgetBtn = $( this ); - - if ( self.$sectionContent.hasClass( 'reordering' ) ) { - return; - } - - if ( ! $( 'body' ).hasClass( 'adding-widget' ) ) { - addNewWidgetBtn.attr( 'aria-expanded', 'true' ); - api.Widgets.availableWidgetsPanel.open( self ); - } else { - addNewWidgetBtn.attr( 'aria-expanded', 'false' ); - api.Widgets.availableWidgetsPanel.close(); - } - } ); - }, - - /** - * Add classes to the widget_form controls to assist with styling - */ - _applyCardinalOrderClassNames: function() { - var widgetControls = []; - _.each( this.setting(), function ( widgetId ) { - var widgetControl = api.Widgets.getWidgetFormControlForWidget( widgetId ); - if ( widgetControl ) { - widgetControls.push( widgetControl ); - } - }); - - if ( 0 === widgetControls.length || ( 1 === api.Widgets.registeredSidebars.length && widgetControls.length <= 1 ) ) { - this.container.find( '.reorder-toggle' ).hide(); - return; - } else { - this.container.find( '.reorder-toggle' ).show(); - } - - $( widgetControls ).each( function () { - $( this.container ) - .removeClass( 'first-widget' ) - .removeClass( 'last-widget' ) - .find( '.move-widget-down, .move-widget-up' ).prop( 'tabIndex', 0 ); - }); - - _.first( widgetControls ).container - .addClass( 'first-widget' ) - .find( '.move-widget-up' ).prop( 'tabIndex', -1 ); - - _.last( widgetControls ).container - .addClass( 'last-widget' ) - .find( '.move-widget-down' ).prop( 'tabIndex', -1 ); - }, - - - /*********************************************************************** - * Begin public API methods - **********************************************************************/ - - /** - * Enable/disable the reordering UI - * - * @param {Boolean} showOrHide to enable/disable reordering - * - * @todo We should have a reordering state instead and rename this to onChangeReordering - */ - toggleReordering: function( showOrHide ) { - var addNewWidgetBtn = this.$sectionContent.find( '.add-new-widget' ), - reorderBtn = this.container.find( '.reorder-toggle' ), - widgetsTitle = this.$sectionContent.find( '.widget-title' ); - - showOrHide = Boolean( showOrHide ); - - if ( showOrHide === this.$sectionContent.hasClass( 'reordering' ) ) { - return; - } - - this.isReordering = showOrHide; - this.$sectionContent.toggleClass( 'reordering', showOrHide ); - - if ( showOrHide ) { - _( this.getWidgetFormControls() ).each( function( formControl ) { - formControl.collapse(); - } ); - - addNewWidgetBtn.attr({ 'tabindex': '-1', 'aria-hidden': 'true' }); - reorderBtn.attr( 'aria-label', l10n.reorderLabelOff ); - wp.a11y.speak( l10n.reorderModeOn ); - // Hide widget titles while reordering: title is already in the reorder controls. - widgetsTitle.attr( 'aria-hidden', 'true' ); - } else { - addNewWidgetBtn.removeAttr( 'tabindex aria-hidden' ); - reorderBtn.attr( 'aria-label', l10n.reorderLabelOn ); - wp.a11y.speak( l10n.reorderModeOff ); - widgetsTitle.attr( 'aria-hidden', 'false' ); - } - }, - - /** - * Get the widget_form Customize controls associated with the current sidebar. - * - * @since 3.9.0 - * @return {wp.customize.controlConstructor.widget_form[]} - */ - getWidgetFormControls: function() { - var formControls = []; - - _( this.setting() ).each( function( widgetId ) { - var settingId = widgetIdToSettingId( widgetId ), - formControl = api.control( settingId ); - if ( formControl ) { - formControls.push( formControl ); - } - } ); - - return formControls; - }, - - /** - * @param {string} widgetId or an id_base for adding a previously non-existing widget - * @returns {object|false} widget_form control instance, or false on error - */ - addWidget: function( widgetId ) { - var self = this, controlHtml, $widget, controlType = 'widget_form', controlContainer, controlConstructor, - parsedWidgetId = parseWidgetId( widgetId ), - widgetNumber = parsedWidgetId.number, - widgetIdBase = parsedWidgetId.id_base, - widget = api.Widgets.availableWidgets.findWhere( {id_base: widgetIdBase} ), - settingId, isExistingWidget, widgetFormControl, sidebarWidgets, settingArgs, setting; - - if ( ! widget ) { - return false; - } - - if ( widgetNumber && ! widget.get( 'is_multi' ) ) { - return false; - } - - // Set up new multi widget - if ( widget.get( 'is_multi' ) && ! widgetNumber ) { - widget.set( 'multi_number', widget.get( 'multi_number' ) + 1 ); - widgetNumber = widget.get( 'multi_number' ); - } - - controlHtml = $.trim( $( '#widget-tpl-' + widget.get( 'id' ) ).html() ); - if ( widget.get( 'is_multi' ) ) { - controlHtml = controlHtml.replace( /<[^<>]+>/g, function( m ) { - return m.replace( /__i__|%i%/g, widgetNumber ); - } ); - } else { - widget.set( 'is_disabled', true ); // Prevent single widget from being added again now - } - - $widget = $( controlHtml ); - - controlContainer = $( '<li/>' ) - .addClass( 'customize-control' ) - .addClass( 'customize-control-' + controlType ) - .append( $widget ); - - // Remove icon which is visible inside the panel - controlContainer.find( '> .widget-icon' ).remove(); - - if ( widget.get( 'is_multi' ) ) { - controlContainer.find( 'input[name="widget_number"]' ).val( widgetNumber ); - controlContainer.find( 'input[name="multi_number"]' ).val( widgetNumber ); - } - - widgetId = controlContainer.find( '[name="widget-id"]' ).val(); - - controlContainer.hide(); // to be slid-down below - - settingId = 'widget_' + widget.get( 'id_base' ); - if ( widget.get( 'is_multi' ) ) { - settingId += '[' + widgetNumber + ']'; - } - controlContainer.attr( 'id', 'customize-control-' + settingId.replace( /\]/g, '' ).replace( /\[/g, '-' ) ); - - // Only create setting if it doesn't already exist (if we're adding a pre-existing inactive widget) - isExistingWidget = api.has( settingId ); - if ( ! isExistingWidget ) { - settingArgs = { - transport: api.Widgets.data.selectiveRefreshableWidgets[ widget.get( 'id_base' ) ] ? 'postMessage' : 'refresh', - previewer: this.setting.previewer - }; - setting = api.create( settingId, settingId, '', settingArgs ); - setting.set( {} ); // mark dirty, changing from '' to {} - } - - controlConstructor = api.controlConstructor[controlType]; - widgetFormControl = new controlConstructor( settingId, { - settings: { - 'default': settingId - }, - content: controlContainer, - sidebar_id: self.params.sidebar_id, - widget_id: widgetId, - widget_id_base: widget.get( 'id_base' ), - type: controlType, - is_new: ! isExistingWidget, - width: widget.get( 'width' ), - height: widget.get( 'height' ), - is_wide: widget.get( 'is_wide' ) - } ); - api.control.add( widgetFormControl ); - - // Make sure widget is removed from the other sidebars - api.each( function( otherSetting ) { - if ( otherSetting.id === self.setting.id ) { - return; - } - - if ( 0 !== otherSetting.id.indexOf( 'sidebars_widgets[' ) ) { - return; - } - - var otherSidebarWidgets = otherSetting().slice(), - i = _.indexOf( otherSidebarWidgets, widgetId ); - - if ( -1 !== i ) { - otherSidebarWidgets.splice( i ); - otherSetting( otherSidebarWidgets ); - } - } ); - - // Add widget to this sidebar - sidebarWidgets = this.setting().slice(); - if ( -1 === _.indexOf( sidebarWidgets, widgetId ) ) { - sidebarWidgets.push( widgetId ); - this.setting( sidebarWidgets ); - } - - controlContainer.slideDown( function() { - if ( isExistingWidget ) { - widgetFormControl.updateWidget( { - instance: widgetFormControl.setting() - } ); - } - } ); - - return widgetFormControl; - } - } ); - - // Register models for custom panel, section, and control types - $.extend( api.panelConstructor, { - widgets: api.Widgets.WidgetsPanel - }); - $.extend( api.sectionConstructor, { - sidebar: api.Widgets.SidebarSection - }); - $.extend( api.controlConstructor, { - widget_form: api.Widgets.WidgetControl, - sidebar_widgets: api.Widgets.SidebarControl - }); - - /** - * Init Customizer for widgets. - */ - api.bind( 'ready', function() { - // Set up the widgets panel - api.Widgets.availableWidgetsPanel = new api.Widgets.AvailableWidgetsPanelView({ - collection: api.Widgets.availableWidgets - }); - - // Highlight widget control - api.previewer.bind( 'highlight-widget-control', api.Widgets.highlightWidgetFormControl ); - - // Open and focus widget control - api.previewer.bind( 'focus-widget-control', api.Widgets.focusWidgetFormControl ); - } ); - - /** - * Highlight a widget control. - * - * @param {string} widgetId - */ - api.Widgets.highlightWidgetFormControl = function( widgetId ) { - var control = api.Widgets.getWidgetFormControlForWidget( widgetId ); - - if ( control ) { - control.highlightSectionAndControl(); - } - }, - - /** - * Focus a widget control. - * - * @param {string} widgetId - */ - api.Widgets.focusWidgetFormControl = function( widgetId ) { - var control = api.Widgets.getWidgetFormControlForWidget( widgetId ); - - if ( control ) { - control.focus(); - } - }, - - /** - * Given a widget control, find the sidebar widgets control that contains it. - * @param {string} widgetId - * @return {object|null} - */ - api.Widgets.getSidebarWidgetControlContainingWidget = function( widgetId ) { - var foundControl = null; - - // @todo this can use widgetIdToSettingId(), then pass into wp.customize.control( x ).getSidebarWidgetsControl() - api.control.each( function( control ) { - if ( control.params.type === 'sidebar_widgets' && -1 !== _.indexOf( control.setting(), widgetId ) ) { - foundControl = control; - } - } ); - - return foundControl; - }; - - /** - * Given a widget ID for a widget appearing in the preview, get the widget form control associated with it. - * - * @param {string} widgetId - * @return {object|null} - */ - api.Widgets.getWidgetFormControlForWidget = function( widgetId ) { - var foundControl = null; - - // @todo We can just use widgetIdToSettingId() here - api.control.each( function( control ) { - if ( control.params.type === 'widget_form' && control.params.widget_id === widgetId ) { - foundControl = control; - } - } ); - - return foundControl; - }; - - /** - * Initialize Edit Menu button in Nav Menu widget. - */ - $( document ).on( 'widget-added', function( event, widgetContainer ) { - var parsedWidgetId, widgetControl, navMenuSelect, editMenuButton; - parsedWidgetId = parseWidgetId( widgetContainer.find( '> .widget-inside > .form > .widget-id' ).val() ); - if ( 'nav_menu' !== parsedWidgetId.id_base ) { - return; - } - widgetControl = api.control( 'widget_nav_menu[' + String( parsedWidgetId.number ) + ']' ); - if ( ! widgetControl ) { - return; - } - navMenuSelect = widgetContainer.find( 'select[name*="nav_menu"]' ); - editMenuButton = widgetContainer.find( '.edit-selected-nav-menu > button' ); - if ( 0 === navMenuSelect.length || 0 === editMenuButton.length ) { - return; - } - navMenuSelect.on( 'change', function() { - if ( api.section.has( 'nav_menu[' + navMenuSelect.val() + ']' ) ) { - editMenuButton.parent().show(); - } else { - editMenuButton.parent().hide(); - } - }); - editMenuButton.on( 'click', function() { - var section = api.section( 'nav_menu[' + navMenuSelect.val() + ']' ); - if ( section ) { - focusConstructWithBreadcrumb( section, widgetControl ); - } - } ); - } ); - - /** - * Focus (expand) one construct and then focus on another construct after the first is collapsed. - * - * This overrides the back button to serve the purpose of breadcrumb navigation. - * - * @param {wp.customize.Section|wp.customize.Panel|wp.customize.Control} focusConstruct - The object to initially focus. - * @param {wp.customize.Section|wp.customize.Panel|wp.customize.Control} returnConstruct - The object to return focus. - */ - function focusConstructWithBreadcrumb( focusConstruct, returnConstruct ) { - focusConstruct.focus(); - function onceCollapsed( isExpanded ) { - if ( ! isExpanded ) { - focusConstruct.expanded.unbind( onceCollapsed ); - returnConstruct.focus(); - } - } - focusConstruct.expanded.bind( onceCollapsed ); - } - - /** - * @param {String} widgetId - * @returns {Object} - */ - function parseWidgetId( widgetId ) { - var matches, parsed = { - number: null, - id_base: null - }; - - matches = widgetId.match( /^(.+)-(\d+)$/ ); - if ( matches ) { - parsed.id_base = matches[1]; - parsed.number = parseInt( matches[2], 10 ); - } else { - // likely an old single widget - parsed.id_base = widgetId; - } - - return parsed; - } - - /** - * @param {String} widgetId - * @returns {String} settingId - */ - function widgetIdToSettingId( widgetId ) { - var parsed = parseWidgetId( widgetId ), settingId; - - settingId = 'widget_' + parsed.id_base; - if ( parsed.number ) { - settingId += '[' + parsed.number + ']'; - } - - return settingId; - } - -})( window.wp, jQuery ); diff --git a/srcs/wordpress/wp-admin/js/customize-widgets.min.js b/srcs/wordpress/wp-admin/js/customize-widgets.min.js deleted file mode 100644 index b40a7fe..0000000 --- a/srcs/wordpress/wp-admin/js/customize-widgets.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(p,m){if(p&&p.customize){var f,v=p.customize;v.Widgets=v.Widgets||{},v.Widgets.savedWidgetIds={},v.Widgets.data=_wpCustomizeWidgetsSettings||{},f=v.Widgets.data.l10n,v.Widgets.WidgetModel=Backbone.Model.extend({id:null,temp_id:null,classname:null,control_tpl:null,description:null,is_disabled:null,is_multi:null,multi_number:null,name:null,id_base:null,transport:null,params:[],width:null,height:null,search_matched:!0}),v.Widgets.WidgetCollection=Backbone.Collection.extend({model:v.Widgets.WidgetModel,doSearch:function(e){this.terms!==e&&(this.terms=e,0<this.terms.length&&this.search(this.terms),""===this.terms&&this.each(function(e){e.set("search_matched",!0)}))},search:function(e){var t,i;e=(e=e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")).replace(/ /g,")(?=.*"),t=new RegExp("^(?=.*"+e+").+","i"),this.each(function(e){i=[e.get("name"),e.get("id"),e.get("description")].join(" "),e.set("search_matched",t.test(i))})}}),v.Widgets.availableWidgets=new v.Widgets.WidgetCollection(v.Widgets.data.availableWidgets),v.Widgets.SidebarModel=Backbone.Model.extend({after_title:null,after_widget:null,before_title:null,before_widget:null,class:null,description:null,id:null,name:null,is_rendered:!1}),v.Widgets.SidebarCollection=Backbone.Collection.extend({model:v.Widgets.SidebarModel}),v.Widgets.registeredSidebars=new v.Widgets.SidebarCollection(v.Widgets.data.registeredSidebars),v.Widgets.AvailableWidgetsPanelView=p.Backbone.View.extend({el:"#available-widgets",events:{"input #widgets-search":"search","focus .widget-tpl":"focus","click .widget-tpl":"_submit","keypress .widget-tpl":"_submit",keydown:"keyboardAccessible"},selected:null,currentSidebarControl:null,$search:null,$clearResults:null,searchMatchesCount:null,initialize:function(){var i=this;this.$search=m("#widgets-search"),this.$clearResults=this.$el.find(".clear-results"),_.bindAll(this,"close"),this.listenTo(this.collection,"change",this.updateList),this.updateList(),this.searchMatchesCount=this.collection.length,m("#customize-controls, #available-widgets .customize-section-title").on("click keydown",function(e){var t=m(e.target).is(".add-new-widget, .add-new-widget *");m("body").hasClass("adding-widget")&&!t&&i.close()}),this.$clearResults.on("click",function(){i.$search.val("").focus(),i.collection.doSearch("")}),v.previewer.bind("url",this.close)},search:_.debounce(function(e){var t;this.collection.doSearch(e.target.value),this.updateSearchMatchesCount(),this.announceSearchMatches(),this.selected&&!this.selected.is(":visible")&&(this.selected.removeClass("selected"),this.selected=null),this.selected&&!e.target.value&&(this.selected.removeClass("selected"),this.selected=null),!this.selected&&e.target.value&&(t=this.$el.find("> .widget-tpl:visible:first")).length&&this.select(t),""!==e.target.value?this.$clearResults.addClass("is-visible"):""===e.target.value&&this.$clearResults.removeClass("is-visible"),this.searchMatchesCount?this.$el.removeClass("no-widgets-found"):this.$el.addClass("no-widgets-found")},500),updateSearchMatchesCount:function(){this.searchMatchesCount=this.collection.where({search_matched:!0}).length},announceSearchMatches:function(){var e=f.widgetsFound.replace("%d",this.searchMatchesCount);this.searchMatchesCount||(e=f.noWidgetsFound),p.a11y.speak(e)},updateList:function(){this.collection.each(function(e){var t=m("#widget-tpl-"+e.id);t.toggle(e.get("search_matched")&&!e.get("is_disabled")),e.get("is_disabled")&&t.is(this.selected)&&(this.selected=null)})},select:function(e){this.selected=m(e),this.selected.siblings(".widget-tpl").removeClass("selected"),this.selected.addClass("selected")},focus:function(e){this.select(m(e.currentTarget))},_submit:function(e){"keypress"===e.type&&13!==e.which&&32!==e.which||this.submit(m(e.currentTarget))},submit:function(e){var t,i,n;(e=e||this.selected)&&this.currentSidebarControl&&(this.select(e),t=m(this.selected).data("widget-id"),(i=this.collection.findWhere({id:t}))&&((n=this.currentSidebarControl.addWidget(i.get("id_base")))&&n.focus(),this.close()))},open:function(e){this.currentSidebarControl=e,_(this.currentSidebarControl.getWidgetFormControls()).each(function(e){e.params.is_wide&&e.collapseForm()}),v.section.has("publish_settings")&&v.section("publish_settings").collapse(),m("body").addClass("adding-widget"),this.$el.find(".selected").removeClass("selected"),this.collection.doSearch(""),v.settings.browser.mobile||this.$search.focus()},close:function(e){(e=e||{}).returnFocus&&this.currentSidebarControl&&this.currentSidebarControl.container.find(".add-new-widget").focus(),this.currentSidebarControl=null,this.selected=null,m("body").removeClass("adding-widget"),this.$search.val("")},keyboardAccessible:function(e){var t=13===e.which,i=27===e.which,n=40===e.which,s=38===e.which,d=9===e.which,a=e.shiftKey,o=null,r=this.$el.find("> .widget-tpl:visible:first"),c=this.$el.find("> .widget-tpl:visible:last"),l=m(e.target).is(this.$search),g=m(e.target).is(".widget-tpl:visible:last");if(n||s)return n?l?o=r:this.selected&&0!==this.selected.nextAll(".widget-tpl:visible").length&&(o=this.selected.nextAll(".widget-tpl:visible:first")):s&&(l?o=c:this.selected&&0!==this.selected.prevAll(".widget-tpl:visible").length&&(o=this.selected.prevAll(".widget-tpl:visible:first"))),this.select(o),void(o?o.focus():this.$search.focus());t&&!this.$search.val()||(t?this.submit():i&&this.close({returnFocus:!0}),this.currentSidebarControl&&d&&(a&&l||!a&&g)&&(this.currentSidebarControl.container.find(".add-new-widget").focus(),e.preventDefault()))}}),v.Widgets.formSyncHandlers={rss:function(e,t,i){var n=t.find(".widget-error:first"),s=m("<div>"+i+"</div>").find(".widget-error:first");n.length&&s.length?n.replaceWith(s):n.length?n.remove():s.length&&t.find(".widget-content:first").prepend(s)}},v.Widgets.WidgetControl=v.Control.extend({defaultExpandedArguments:{duration:"fast",completeCallback:m.noop},initialize:function(e,t){var i=this;i.widgetControlEmbedded=!1,i.widgetContentEmbedded=!1,i.expanded=new v.Value(!1),i.expandedArgumentsQueue=[],i.expanded.bind(function(e){var t=i.expandedArgumentsQueue.shift();t=m.extend({},i.defaultExpandedArguments,t),i.onChangeExpanded(e,t)}),i.altNotice=!0,v.Control.prototype.initialize.call(i,e,t)},ready:function(){var n=this;n.section()?v.section(n.section(),function(t){var i=function(e){e&&(n.embedWidgetControl(),t.expanded.unbind(i))};t.expanded()?i(!0):t.expanded.bind(i)}):n.embedWidgetControl()},embedWidgetControl:function(){var e,t=this;t.widgetControlEmbedded||(t.widgetControlEmbedded=!0,e=m(t.params.widget_control),t.container.append(e),t._setupModel(),t._setupWideWidget(),t._setupControlToggle(),t._setupWidgetTitle(),t._setupReorderUI(),t._setupHighlightEffects(),t._setupUpdateUI(),t._setupRemoveUI())},embedWidgetContent:function(){var e,t=this;t.embedWidgetControl(),t.widgetContentEmbedded||(t.widgetContentEmbedded=!0,t.notifications.container=t.getNotificationsContainerElement(),t.notifications.render(),e=m(t.params.widget_content),t.container.find(".widget-content:first").append(e),m(document).trigger("widget-added",[t.container.find(".widget:first")]))},_setupModel:function(){var e,i=this;e=function(){v.Widgets.savedWidgetIds[i.params.widget_id]=!0},v.bind("ready",e),v.bind("saved",e),this._updateCount=0,this.isWidgetUpdating=!1,this.liveUpdateMode=!0,this.setting.bind(function(e,t){_(t).isEqual(e)||i.isWidgetUpdating||i.updateWidget({instance:e})})},_setupWideWidget:function(){var s,d,e,t,i,a=this;!this.params.is_wide||m(window).width()<=640||(s=this.container.find(".widget-inside"),d=s.find("> .form"),e=m(".wp-full-overlay-sidebar-content:first"),this.container.addClass("wide-widget-control"),this.container.find(".form:first").css({"max-width":this.params.width,"min-height":this.params.height}),i=function(){var e,t=a.container.offset().top,i=m(window).height(),n=d.outerHeight();s.css("max-height",i),e=Math.max(0,Math.min(Math.max(t,0),i-n)),s.css("top",e)},t=m("#customize-theme-controls"),this.container.on("expand",function(){i(),e.on("scroll",i),m(window).on("resize",i),t.on("expanded collapsed",i)}),this.container.on("collapsed",function(){e.off("scroll",i),m(window).off("resize",i),t.off("expanded collapsed",i)}),v.each(function(e){0===e.id.indexOf("sidebars_widgets[")&&e.bind(function(){a.container.hasClass("expanded")&&i()})}))},_setupControlToggle:function(){var t=this;this.container.find(".widget-top").on("click",function(e){e.preventDefault(),t.getSidebarWidgetsControl().isReordering||t.expanded(!t.expanded())}),this.container.find(".widget-control-close").on("click",function(){t.collapse(),t.container.find(".widget-top .widget-action:first").focus()})},_setupWidgetTitle:function(){var e,i=this;e=function(){var e=i.setting().title,t=i.container.find(".in-widget-title");e?t.text(": "+e):t.text("")},this.setting.bind(e),e()},_setupReorderUI:function(){var d,t,e,i,o=this;d=function(e){e.siblings(".selected").removeClass("selected"),e.addClass("selected");var t=e.data("id")===o.params.sidebar_id;o.container.find(".move-widget-btn").prop("disabled",t)},this.container.find(".widget-title-action").after(m(v.Widgets.data.tpl.widgetReorderNav)),i=_.template(v.Widgets.data.tpl.moveWidgetArea),t=m(i({sidebars:_(v.Widgets.registeredSidebars.toArray()).pluck("attributes")})),this.container.find(".widget-top").after(t),(e=function(){var n,e=t.find("li"),s=0;n=e.filter(function(){return m(this).data("id")===o.params.sidebar_id}),e.each(function(){var e,t,i=m(this);e=i.data("id"),t=v.Widgets.registeredSidebars.get(e).get("is_rendered"),i.toggle(t),t&&(s+=1),i.hasClass("selected")&&!t&&d(n)}),1<s?o.container.find(".move-widget").show():o.container.find(".move-widget").hide()})(),v.Widgets.registeredSidebars.on("change:is_rendered",e),this.container.find(".widget-reorder-nav").find(".move-widget, .move-widget-down, .move-widget-up").each(function(){m(this).prepend(o.container.find(".widget-title").text()+": ")}).on("click keypress",function(e){if("keypress"!==e.type||13===e.which||32===e.which)if(m(this).focus(),m(this).is(".move-widget"))o.toggleWidgetMoveArea();else{var t=m(this).is(".move-widget-down"),i=m(this).is(".move-widget-up"),n=o.getWidgetSidebarPosition();if(i&&0===n||t&&n===o.getSidebarWidgetsControl().setting().length-1)return;i?(o.moveUp(),p.a11y.speak(f.widgetMovedUp)):(o.moveDown(),p.a11y.speak(f.widgetMovedDown)),m(this).focus()}}),this.container.find(".widget-area-select").on("click keypress","li",function(e){"keypress"===e.type&&13!==e.which&&32!==e.which||(e.preventDefault(),d(m(this)))}),this.container.find(".move-widget-btn").click(function(){o.getSidebarWidgetsControl().toggleReordering(!1);var e,t,i,n,s,d=o.params.sidebar_id,a=o.container.find(".widget-area-select li.selected").data("id");e=v("sidebars_widgets["+d+"]"),t=v("sidebars_widgets["+a+"]"),i=Array.prototype.slice.call(e()),n=Array.prototype.slice.call(t()),s=o.getWidgetSidebarPosition(),i.splice(s,1),n.push(o.params.widget_id),e(i),t(n),o.focus()})},_setupHighlightEffects:function(){var e=this;this.container.on("mouseenter click",function(){e.setting.previewer.send("highlight-widget",e.params.widget_id)}),this.setting.bind(function(){e.setting.previewer.send("highlight-widget",e.params.widget_id)})},_setupUpdateUI:function(){var i,e,t,n,s,d=this;e=(i=this.container.find(".widget:first")).find(".widget-content:first"),(t=this.container.find(".widget-control-save")).val(f.saveBtnLabel),t.attr("title",f.saveBtnTooltip),t.removeClass("button-primary"),t.on("click",function(e){e.preventDefault(),d.updateWidget({disable_form:!0})}),n=_.debounce(function(){d.updateWidget()},250),e.on("keydown","input",function(e){13===e.which&&(e.preventDefault(),d.updateWidget({ignoreActiveElement:!0}))}),e.on("change input propertychange",":input",function(e){d.liveUpdateMode&&("change"===e.type||this.checkValidity&&this.checkValidity())&&n()}),this.setting.previewer.channel.bind("synced",function(){d.container.removeClass("previewer-loading")}),v.previewer.bind("widget-updated",function(e){e===d.params.widget_id&&d.container.removeClass("previewer-loading")}),(s=v.Widgets.formSyncHandlers[this.params.widget_id_base])&&m(document).on("widget-synced",function(e,t){i.is(t)&&s.apply(document,arguments)})},onChangeActive:function(e,t){this.container.toggleClass("widget-rendered",e),t.completeCallback&&t.completeCallback()},_setupRemoveUI:function(){var e,t,s=this;(e=this.container.find(".widget-control-remove")).on("click",function(){var n;n=s.container.next().is(".customize-control-widget_form")?s.container.next().find(".widget-action:first"):s.container.prev().is(".customize-control-widget_form")?s.container.prev().find(".widget-action:first"):s.container.next(".customize-control-sidebar_widgets").find(".add-new-widget:first"),s.container.slideUp(function(){var e,t,i=v.Widgets.getSidebarWidgetControlContainingWidget(s.params.widget_id);i&&(e=i.setting().slice(),-1!==(t=_.indexOf(e,s.params.widget_id))&&(e.splice(t,1),i.setting(e),n.focus()))})}),t=function(){e.text(f.removeBtnLabel),e.attr("title",f.removeBtnTooltip)},this.params.is_new?v.bind("saved",t):t()},_getInputs:function(e){return m(e).find(":input[name]")},_getInputsSignature:function(e){return _(e).map(function(e){var t=m(e);return(t.is(":checkbox, :radio")?[t.attr("id"),t.attr("name"),t.prop("value")]:[t.attr("id"),t.attr("name")]).join(",")}).join(";")},_getInputState:function(e){return(e=m(e)).is(":radio, :checkbox")?e.prop("checked"):e.is("select[multiple]")?e.find("option:selected").map(function(){return m(this).val()}).get():e.val()},_setInputState:function(e,t){(e=m(e)).is(":radio, :checkbox")?e.prop("checked",t):e.is("select[multiple]")?(t=m.isArray(t)?_.map(t,function(e){return String(e)}):[],e.find("option").each(function(){m(this).prop("selected",-1!==_.indexOf(t,String(this.value)))})):e.val(t)},getSidebarWidgetsControl:function(){var e,t;if(e="sidebars_widgets["+this.params.sidebar_id+"]",t=v.control(e))return t},updateWidget:function(a){var e,o,r,c,l,t,i,g,n,s,u,h=this;h.embedWidgetContent(),e=(a=m.extend({instance:null,complete:null,ignoreActiveElement:!1},a)).instance,o=a.complete,this._updateCount+=1,l=this._updateCount,r=this.container.find(".widget:first"),(c=r.find(".widget-content:first")).find(".widget-error").remove(),this.container.addClass("widget-form-loading"),this.container.addClass("previewer-loading"),(n=v.state("processing"))(n()+1),this.liveUpdateMode||this.container.addClass("widget-form-disabled"),(t={action:"update-widget",wp_customize:"on"}).nonce=v.settings.nonce["update-widget"],t.customize_theme=v.settings.theme.stylesheet,t.customized=p.customize.previewer.query().customized,i=m.param(t),(g=this._getInputs(c)).each(function(){m(this).data("state"+l,h._getInputState(this))}),i+=e?"&"+m.param({sanitized_widget_setting:JSON.stringify(e)}):"&"+g.serialize(),i+="&"+c.find("~ :input").serialize(),this._previousUpdateRequest&&this._previousUpdateRequest.abort(),s=m.post(p.ajax.settings.url,i),(this._previousUpdateRequest=s).done(function(e){var t,i,d,n,s=!1;if("0"===e)return v.previewer.preview.iframe.hide(),void v.previewer.login().done(function(){h.updateWidget(a),v.previewer.preview.iframe.show()});"-1"!==e?e.success?(i=m("<div>"+e.data.form+"</div>"),d=h._getInputs(i),(n=h._getInputsSignature(g)===h._getInputsSignature(d))&&!h.liveUpdateMode&&(h.liveUpdateMode=!0,h.container.removeClass("widget-form-disabled"),h.container.find('input[name="savewidget"]').hide()),n&&h.liveUpdateMode?(g.each(function(e){var t,i,n=m(this),s=m(d[e]);t=n.data("state"+l),i=h._getInputState(s),n.data("sanitized",i),_.isEqual(t,i)||!a.ignoreActiveElement&&n.is(document.activeElement)||h._setInputState(n,i)}),m(document).trigger("widget-synced",[r,e.data.form])):h.liveUpdateMode?(h.liveUpdateMode=!1,h.container.find('input[name="savewidget"]').show(),s=!0):(c.html(e.data.form),h.container.removeClass("widget-form-disabled"),m(document).trigger("widget-updated",[r])),(u=!s&&!_(h.setting()).isEqual(e.data.instance))?(h.isWidgetUpdating=!0,h.setting(e.data.instance),h.isWidgetUpdating=!1):h.container.removeClass("previewer-loading"),o&&o.call(h,null,{noChange:!u,ajaxFinished:!0})):(t=f.error,e.data&&e.data.message&&(t=e.data.message),o?o.call(h,t):c.prepend('<p class="widget-error"><strong>'+t+"</strong></p>")):v.previewer.cheatin()}),s.fail(function(e,t){o&&o.call(h,t)}),s.always(function(){h.container.removeClass("widget-form-loading"),g.each(function(){m(this).removeData("state"+l)}),n(n()-1)})},expandControlSection:function(){v.Control.prototype.expand.call(this)},_toggleExpanded:v.Section.prototype._toggleExpanded,expand:v.Section.prototype.expand,expandForm:function(){this.expand()},collapse:v.Section.prototype.collapse,collapseForm:function(){this.collapse()},toggleForm:function(e){void 0===e&&(e=!this.expanded()),this.expanded(e)},onChangeExpanded:function(e,t){var i,n,s,d,a,o,r=this;r.embedWidgetControl(),e&&r.embedWidgetContent(),t.unchanged?e&&v.Control.prototype.expand.call(r,{completeCallback:t.completeCallback}):(i=this.container.find("div.widget:first"),n=i.find(".widget-inside:first"),o=this.container.find(".widget-top button.widget-action"),a=function(){v.control.each(function(e){r.params.type===e.params.type&&r!==e&&e.collapse()}),s=function(){r.container.removeClass("expanding"),r.container.addClass("expanded"),i.addClass("open"),o.attr("aria-expanded","true"),r.container.trigger("expanded")},t.completeCallback&&(d=s,s=function(){d(),t.completeCallback()}),r.params.is_wide?n.fadeIn(t.duration,s):n.slideDown(t.duration,s),r.container.trigger("expand"),r.container.addClass("expanding")},e?v.section.has(r.section())?v.section(r.section()).expand({completeCallback:a}):a():(s=function(){r.container.removeClass("collapsing"),r.container.removeClass("expanded"),i.removeClass("open"),o.attr("aria-expanded","false"),r.container.trigger("collapsed")},t.completeCallback&&(d=s,s=function(){d(),t.completeCallback()}),r.container.trigger("collapse"),r.container.addClass("collapsing"),r.params.is_wide?n.fadeOut(t.duration,s):n.slideUp(t.duration,function(){i.css({width:"",margin:""}),s()})))},getWidgetSidebarPosition:function(){var e,t;if(e=this.getSidebarWidgetsControl().setting(),-1!==(t=_.indexOf(e,this.params.widget_id)))return t},moveUp:function(){this._moveWidgetByOne(-1)},moveDown:function(){this._moveWidgetByOne(1)},_moveWidgetByOne:function(e){var t,i,n,s;t=this.getWidgetSidebarPosition(),i=this.getSidebarWidgetsControl().setting,s=(n=Array.prototype.slice.call(i()))[t+e],n[t+e]=this.params.widget_id,n[t]=s,i(n)},toggleWidgetMoveArea:function(e){var t,i=this;t=this.container.find(".move-widget-area"),void 0===e&&(e=!t.hasClass("active")),e&&(t.find(".selected").removeClass("selected"),t.find("li").filter(function(){return m(this).data("id")===i.params.sidebar_id}).addClass("selected"),this.container.find(".move-widget-btn").prop("disabled",!0)),t.toggleClass("active",e)},highlightSectionAndControl:function(){var e;e=this.container.is(":hidden")?this.container.closest(".control-section"):this.container,m(".highlighted").removeClass("highlighted"),e.addClass("highlighted"),setTimeout(function(){e.removeClass("highlighted")},500)}}),v.Widgets.WidgetsPanel=v.Panel.extend({ready:function(){var n=this;v.Panel.prototype.ready.call(n),n.deferred.embedded.done(function(){var e,s,t,d,i;e=n.container.find(".panel-meta"),s=m("<div></div>",{class:"no-widget-areas-rendered-notice"}),e.append(s),d=function(){return _.filter(n.sections(),function(e){return"sidebar"===e.params.type&&e.active()}).length},i=function(){var e=d();return 0===e||e!==v.Widgets.data.registeredSidebars.length},(t=function(){var e,t,i,n=d();s.empty(),n!==(i=v.Widgets.data.registeredSidebars.length)&&((e=0!==n?(t=i-n,f.someAreasShown[t]):f.noAreasShown)&&s.append(m("<p></p>",{text:e})),s.append(m("<p></p>",{text:f.navigatePreview})))})(),s.toggle(i()),v.previewer.deferred.active.done(function(){s.toggle(i())}),v.bind("pane-contents-reflowed",function(){var e="resolved"===v.previewer.deferred.active.state()?"fast":0;t(),i()?s.slideDown(e):s.slideUp(e)})})},isContextuallyActive:function(){return this.active()}}),v.Widgets.SidebarSection=v.Section.extend({ready:function(){var t;v.Section.prototype.ready.call(this),t=v.Widgets.registeredSidebars.get(this.params.sidebarId),this.active.bind(function(e){t.set("is_rendered",e)}),t.set("is_rendered",this.active())}}),v.Widgets.SidebarControl=v.Control.extend({ready:function(){this.$controlSection=this.container.closest(".control-section"),this.$sectionContent=this.container.closest(".accordion-section-content"),this._setupModel(),this._setupSortable(),this._setupAddition(),this._applyCardinalOrderClassNames()},_setupModel:function(){var o=this;this.setting.bind(function(i,e){var t,n,s;n=_(e).difference(i),i=_(i).filter(function(e){var t=w(e);return!!v.Widgets.availableWidgets.findWhere({id_base:t.id_base})}),(t=_(i).map(function(e){var t=v.Widgets.getWidgetFormControlForWidget(e);return t=t||o.addWidget(e)})).sort(function(e,t){return _.indexOf(i,e.params.widget_id)-_.indexOf(i,t.params.widget_id)}),s=0,_(t).each(function(e){e.priority(s),e.section(o.section()),s+=1}),o.priority(s),o._applyCardinalOrderClassNames(),_(t).each(function(e){e.params.sidebar_id=o.params.sidebar_id}),_(n).each(function(a){setTimeout(function(){var e,t,i,n,s,d=!1;v.each(function(e){if(e.id!==o.setting.id&&0===e.id.indexOf("sidebars_widgets[")&&"sidebars_widgets[wp_inactive_widgets]"!==e.id){var t=e();-1!==_.indexOf(t,a)&&(d=!0)}}),d||(t=(e=v.Widgets.getWidgetFormControlForWidget(a))&&m.contains(document,e.container[0])&&!m.contains(o.$sectionContent[0],e.container[0]),e&&!t&&(v.control.remove(e.id),e.container.remove()),v.Widgets.savedWidgetIds[a]&&((i=v.value("sidebars_widgets[wp_inactive_widgets]")().slice()).push(a),v.value("sidebars_widgets[wp_inactive_widgets]")(_(i).unique())),n=w(a).id_base,(s=v.Widgets.availableWidgets.findWhere({id_base:n}))&&!s.get("is_multi")&&s.set("is_disabled",!1))})})})},_setupSortable:function(){var i=this;this.isReordering=!1,this.$sectionContent.sortable({items:"> .customize-control-widget_form",handle:".widget-top",axis:"y",tolerance:"pointer",connectWith:".accordion-section-content:has(.customize-control-sidebar_widgets)",update:function(){var e,t=i.$sectionContent.sortable("toArray");e=m.map(t,function(e){return m("#"+e).find(":input[name=widget-id]").val()}),i.setting(e)}}),this.$controlSection.find(".accordion-section-title").droppable({accept:".customize-control-widget_form",over:function(){v.section(i.section.get()).expand({allowMultiple:!0,completeCallback:function(){v.section.each(function(e){e.container.find(".customize-control-sidebar_widgets").length&&e.container.find(".accordion-section-content:first").sortable("refreshPositions")})}})}}),this.container.find(".reorder-toggle").on("click",function(){i.toggleReordering(!i.isReordering)})},_setupAddition:function(){var t=this;this.container.find(".add-new-widget").on("click",function(){var e=m(this);t.$sectionContent.hasClass("reordering")||(m("body").hasClass("adding-widget")?(e.attr("aria-expanded","false"),v.Widgets.availableWidgetsPanel.close()):(e.attr("aria-expanded","true"),v.Widgets.availableWidgetsPanel.open(t)))})},_applyCardinalOrderClassNames:function(){var i=[];_.each(this.setting(),function(e){var t=v.Widgets.getWidgetFormControlForWidget(e);t&&i.push(t)}),0===i.length||1===v.Widgets.registeredSidebars.length&&i.length<=1?this.container.find(".reorder-toggle").hide():(this.container.find(".reorder-toggle").show(),m(i).each(function(){m(this.container).removeClass("first-widget").removeClass("last-widget").find(".move-widget-down, .move-widget-up").prop("tabIndex",0)}),_.first(i).container.addClass("first-widget").find(".move-widget-up").prop("tabIndex",-1),_.last(i).container.addClass("last-widget").find(".move-widget-down").prop("tabIndex",-1))},toggleReordering:function(e){var t=this.$sectionContent.find(".add-new-widget"),i=this.container.find(".reorder-toggle"),n=this.$sectionContent.find(".widget-title");(e=Boolean(e))!==this.$sectionContent.hasClass("reordering")&&(this.isReordering=e,this.$sectionContent.toggleClass("reordering",e),e?(_(this.getWidgetFormControls()).each(function(e){e.collapse()}),t.attr({tabindex:"-1","aria-hidden":"true"}),i.attr("aria-label",f.reorderLabelOff),p.a11y.speak(f.reorderModeOn),n.attr("aria-hidden","true")):(t.removeAttr("tabindex aria-hidden"),i.attr("aria-label",f.reorderLabelOn),p.a11y.speak(f.reorderModeOff),n.attr("aria-hidden","false")))},getWidgetFormControls:function(){var n=[];return _(this.setting()).each(function(e){var t=function(e){var t,i=w(e);t="widget_"+i.id_base,i.number&&(t+="["+i.number+"]");return t}(e),i=v.control(t);i&&n.push(i)}),n},addWidget:function(n){var e,t,i,s,d,a,o,r,c,l=this,g="widget_form",u=w(n),h=u.number,p=u.id_base,f=v.Widgets.availableWidgets.findWhere({id_base:p});return!!f&&(!(h&&!f.get("is_multi"))&&(f.get("is_multi")&&!h&&(f.set("multi_number",f.get("multi_number")+1),h=f.get("multi_number")),e=m.trim(m("#widget-tpl-"+f.get("id")).html()),f.get("is_multi")?e=e.replace(/<[^<>]+>/g,function(e){return e.replace(/__i__|%i%/g,h)}):f.set("is_disabled",!0),t=m(e),(i=m("<li/>").addClass("customize-control").addClass("customize-control-"+g).append(t)).find("> .widget-icon").remove(),f.get("is_multi")&&(i.find('input[name="widget_number"]').val(h),i.find('input[name="multi_number"]').val(h)),n=i.find('[name="widget-id"]').val(),i.hide(),d="widget_"+f.get("id_base"),f.get("is_multi")&&(d+="["+h+"]"),i.attr("id","customize-control-"+d.replace(/\]/g,"").replace(/\[/g,"-")),(a=v.has(d))||(c={transport:v.Widgets.data.selectiveRefreshableWidgets[f.get("id_base")]?"postMessage":"refresh",previewer:this.setting.previewer},v.create(d,d,"",c).set({})),s=v.controlConstructor[g],o=new s(d,{settings:{default:d},content:i,sidebar_id:l.params.sidebar_id,widget_id:n,widget_id_base:f.get("id_base"),type:g,is_new:!a,width:f.get("width"),height:f.get("height"),is_wide:f.get("is_wide")}),v.control.add(o),v.each(function(e){if(e.id!==l.setting.id&&0===e.id.indexOf("sidebars_widgets[")){var t=e().slice(),i=_.indexOf(t,n);-1!==i&&(t.splice(i),e(t))}}),r=this.setting().slice(),-1===_.indexOf(r,n)&&(r.push(n),this.setting(r)),i.slideDown(function(){a&&o.updateWidget({instance:o.setting()})}),o))}}),m.extend(v.panelConstructor,{widgets:v.Widgets.WidgetsPanel}),m.extend(v.sectionConstructor,{sidebar:v.Widgets.SidebarSection}),m.extend(v.controlConstructor,{widget_form:v.Widgets.WidgetControl,sidebar_widgets:v.Widgets.SidebarControl}),v.bind("ready",function(){v.Widgets.availableWidgetsPanel=new v.Widgets.AvailableWidgetsPanelView({collection:v.Widgets.availableWidgets}),v.previewer.bind("highlight-widget-control",v.Widgets.highlightWidgetFormControl),v.previewer.bind("focus-widget-control",v.Widgets.focusWidgetFormControl)}),v.Widgets.highlightWidgetFormControl=function(e){var t=v.Widgets.getWidgetFormControlForWidget(e);t&&t.highlightSectionAndControl()},v.Widgets.focusWidgetFormControl=function(e){var t=v.Widgets.getWidgetFormControlForWidget(e);t&&t.focus()},v.Widgets.getSidebarWidgetControlContainingWidget=function(t){var i=null;return v.control.each(function(e){"sidebar_widgets"===e.params.type&&-1!==_.indexOf(e.setting(),t)&&(i=e)}),i},v.Widgets.getWidgetFormControlForWidget=function(t){var i=null;return v.control.each(function(e){"widget_form"===e.params.type&&e.params.widget_id===t&&(i=e)}),i},m(document).on("widget-added",function(e,t){var i,n,s,d;"nav_menu"===(i=w(t.find("> .widget-inside > .form > .widget-id").val())).id_base&&(n=v.control("widget_nav_menu["+String(i.number)+"]"))&&(s=t.find('select[name*="nav_menu"]'),d=t.find(".edit-selected-nav-menu > button"),0!==s.length&&0!==d.length&&(s.on("change",function(){v.section.has("nav_menu["+s.val()+"]")?d.parent().show():d.parent().hide()}),d.on("click",function(){var e=v.section("nav_menu["+s.val()+"]");e&&function(i,n){i.focus(),i.expanded.bind(function e(t){t||(i.expanded.unbind(e),n.focus())})}(e,n)})))})}function w(e){var t,i={number:null,id_base:null};return(t=e.match(/^(.+)-(\d+)$/))?(i.id_base=t[1],i.number=parseInt(t[2],10)):i.id_base=e,i}}(window.wp,jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/dashboard.js b/srcs/wordpress/wp-admin/js/dashboard.js deleted file mode 100644 index aa9f921..0000000 --- a/srcs/wordpress/wp-admin/js/dashboard.js +++ /dev/null @@ -1,593 +0,0 @@ -/** - * @output wp-admin/js/dashboard.js - */ - -/* global pagenow, ajaxurl, postboxes, wpActiveEditor:true, ajaxWidgets */ -/* global ajaxPopulateWidgets, quickPressLoad, */ -window.wp = window.wp || {}; - -/** - * Initializes the dashboard widget functionality. - * - * @since 2.7.0 - */ -jQuery(document).ready( function($) { - var welcomePanel = $( '#welcome-panel' ), - welcomePanelHide = $('#wp_welcome_panel-hide'), - updateWelcomePanel; - - /** - * Saves the visibility of the welcome panel. - * - * @since 3.3.0 - * - * @param {boolean} visible Should it be visible or not. - * - * @returns {void} - */ - updateWelcomePanel = function( visible ) { - $.post( ajaxurl, { - action: 'update-welcome-panel', - visible: visible, - welcomepanelnonce: $( '#welcomepanelnonce' ).val() - }); - }; - - // Unhide the welcome panel if the Welcome Option checkbox is checked. - if ( welcomePanel.hasClass('hidden') && welcomePanelHide.prop('checked') ) { - welcomePanel.removeClass('hidden'); - } - - // Hide the welcome panel when the dismiss button or close button is clicked. - $('.welcome-panel-close, .welcome-panel-dismiss a', welcomePanel).click( function(e) { - e.preventDefault(); - welcomePanel.addClass('hidden'); - updateWelcomePanel( 0 ); - $('#wp_welcome_panel-hide').prop('checked', false); - }); - - // Set welcome panel visibility based on Welcome Option checkbox value. - welcomePanelHide.click( function() { - welcomePanel.toggleClass('hidden', ! this.checked ); - updateWelcomePanel( this.checked ? 1 : 0 ); - }); - - /** - * These widgets can be populated via ajax. - * - * @since 2.7.0 - * - * @type {string[]} - * - * @global - */ - window.ajaxWidgets = ['dashboard_primary']; - - /** - * Triggers widget updates via AJAX. - * - * @since 2.7.0 - * - * @global - * - * @param {string} el Optional. Widget to fetch or none to update all. - * - * @returns {void} - */ - window.ajaxPopulateWidgets = function(el) { - /** - * Fetch the latest representation of the widget via Ajax and show it. - * - * @param {number} i Number of half-seconds to use as the timeout. - * @param {string} id ID of the element which is going to be checked for changes. - * - * @returns {void} - */ - function show(i, id) { - var p, e = $('#' + id + ' div.inside:visible').find('.widget-loading'); - // If the element is found in the dom, queue to load latest representation. - if ( e.length ) { - p = e.parent(); - setTimeout( function(){ - // Request the widget content. - p.load( ajaxurl + '?action=dashboard-widgets&widget=' + id + '&pagenow=' + pagenow, '', function() { - // Hide the parent and slide it out for visual fancyness. - p.hide().slideDown('normal', function(){ - $(this).css('display', ''); - }); - }); - }, i * 500 ); - } - } - - // If we have received a specific element to fetch, check if it is valid. - if ( el ) { - el = el.toString(); - // If the element is available as AJAX widget, show it. - if ( $.inArray(el, ajaxWidgets) !== -1 ) { - // Show element without any delay. - show(0, el); - } - } else { - // Walk through all ajaxWidgets, loading them after each other. - $.each( ajaxWidgets, show ); - } - }; - - // Initially populate ajax widgets. - ajaxPopulateWidgets(); - - // Register ajax widgets as postbox toggles. - postboxes.add_postbox_toggles(pagenow, { pbshow: ajaxPopulateWidgets } ); - - /** - * Control the Quick Press (Quick Draft) widget. - * - * @since 2.7.0 - * - * @global - * - * @returns {void} - */ - window.quickPressLoad = function() { - var act = $('#quickpost-action'), t; - - // Enable the submit buttons. - $( '#quick-press .submit input[type="submit"], #quick-press .submit input[type="reset"]' ).prop( 'disabled' , false ); - - t = $('#quick-press').submit( function( e ) { - e.preventDefault(); - - // Show a spinner. - $('#dashboard_quick_press #publishing-action .spinner').show(); - - // Disable the submit button to prevent duplicate submissions. - $('#quick-press .submit input[type="submit"], #quick-press .submit input[type="reset"]').prop('disabled', true); - - // Post the entered data to save it. - $.post( t.attr( 'action' ), t.serializeArray(), function( data ) { - // Replace the form, and prepend the published post. - $('#dashboard_quick_press .inside').html( data ); - $('#quick-press').removeClass('initial-form'); - quickPressLoad(); - highlightLatestPost(); - - // Focus the title to allow for quickly drafting another post. - $('#title').focus(); - }); - - /** - * Highlights the latest post for one second. - * - * @returns {void} - */ - function highlightLatestPost () { - var latestPost = $('.drafts ul li').first(); - latestPost.css('background', '#fffbe5'); - setTimeout(function () { - latestPost.css('background', 'none'); - }, 1000); - } - } ); - - // Change the QuickPost action to the publish value. - $('#publish').click( function() { act.val( 'post-quickpress-publish' ); } ); - - $('#quick-press').on( 'click focusin', function() { - wpActiveEditor = 'content'; - }); - - autoResizeTextarea(); - }; - window.quickPressLoad(); - - // Enable the dragging functionality of the widgets. - $( '.meta-box-sortables' ).sortable( 'option', 'containment', '#wpwrap' ); - - /** - * Adjust the height of the textarea based on the content. - * - * @since 3.6.0 - * - * @returns {void} - */ - function autoResizeTextarea() { - // When IE8 or older is used to render this document, exit. - if ( document.documentMode && document.documentMode < 9 ) { - return; - } - - // Add a hidden div. We'll copy over the text from the textarea to measure its height. - $('body').append( '<div class="quick-draft-textarea-clone" style="display: none;"></div>' ); - - var clone = $('.quick-draft-textarea-clone'), - editor = $('#content'), - editorHeight = editor.height(), - /* - * 100px roughly accounts for browser chrome and allows the - * save draft button to show on-screen at the same time. - */ - editorMaxHeight = $(window).height() - 100; - - /* - * Match up textarea and clone div as much as possible. - * Padding cannot be reliably retrieved using shorthand in all browsers. - */ - clone.css({ - 'font-family': editor.css('font-family'), - 'font-size': editor.css('font-size'), - 'line-height': editor.css('line-height'), - 'padding-bottom': editor.css('paddingBottom'), - 'padding-left': editor.css('paddingLeft'), - 'padding-right': editor.css('paddingRight'), - 'padding-top': editor.css('paddingTop'), - 'white-space': 'pre-wrap', - 'word-wrap': 'break-word', - 'display': 'none' - }); - - // The 'propertychange' is used in IE < 9. - editor.on('focus input propertychange', function() { - var $this = $(this), - // Add a non-breaking space to ensure that the height of a trailing newline is - // included. - textareaContent = $this.val() + ' ', - // Add 2px to compensate for border-top & border-bottom. - cloneHeight = clone.css('width', $this.css('width')).text(textareaContent).outerHeight() + 2; - - // Default to show a vertical scrollbar, if needed. - editor.css('overflow-y', 'auto'); - - // Only change the height if it has changed and both heights are below the max. - if ( cloneHeight === editorHeight || ( cloneHeight >= editorMaxHeight && editorHeight >= editorMaxHeight ) ) { - return; - } - - /* - * Don't allow editor to exceed the height of the window. - * This is also bound in CSS to a max-height of 1300px to be extra safe. - */ - if ( cloneHeight > editorMaxHeight ) { - editorHeight = editorMaxHeight; - } else { - editorHeight = cloneHeight; - } - - // Disable scrollbars because we adjust the height to the content. - editor.css('overflow', 'hidden'); - - $this.css('height', editorHeight + 'px'); - }); - } - -} ); - -jQuery( function( $ ) { - 'use strict'; - - var communityEventsData = window.communityEventsData || {}, - app; - - /** - * Global Community Events namespace. - * - * @since 4.8.0 - * - * @memberOf wp - * @namespace wp.communityEvents - */ - app = window.wp.communityEvents = /** @lends wp.communityEvents */{ - initialized: false, - model: null, - - /** - * Initializes the wp.communityEvents object. - * - * @since 4.8.0 - * - * @returns {void} - */ - init: function() { - if ( app.initialized ) { - return; - } - - var $container = $( '#community-events' ); - - /* - * When JavaScript is disabled, the errors container is shown, so - * that "This widget requires JavaScript" message can be seen. - * - * When JS is enabled, the container is hidden at first, and then - * revealed during the template rendering, if there actually are - * errors to show. - * - * The display indicator switches from `hide-if-js` to `aria-hidden` - * here in order to maintain consistency with all the other fields - * that key off of `aria-hidden` to determine their visibility. - * `aria-hidden` can't be used initially, because there would be no - * way to set it to false when JavaScript is disabled, which would - * prevent people from seeing the "This widget requires JavaScript" - * message. - */ - $( '.community-events-errors' ) - .attr( 'aria-hidden', 'true' ) - .removeClass( 'hide-if-js' ); - - $container.on( 'click', '.community-events-toggle-location, .community-events-cancel', app.toggleLocationForm ); - - /** - * Filters events based on entered location. - * - * @returns {void} - */ - $container.on( 'submit', '.community-events-form', function( event ) { - var location = $.trim( $( '#community-events-location' ).val() ); - - event.preventDefault(); - - /* - * Don't trigger a search if the search field is empty or the - * search term was made of only spaces before being trimmed. - */ - if ( ! location ) { - return; - } - - app.getEvents({ - location: location - }); - }); - - if ( communityEventsData && communityEventsData.cache && communityEventsData.cache.location && communityEventsData.cache.events ) { - app.renderEventsTemplate( communityEventsData.cache, 'app' ); - } else { - app.getEvents(); - } - - app.initialized = true; - }, - - /** - * Toggles the visibility of the Edit Location form. - * - * @since 4.8.0 - * - * @param {event|string} action 'show' or 'hide' to specify a state; - * or an event object to flip between states. - * - * @returns {void} - */ - toggleLocationForm: function( action ) { - var $toggleButton = $( '.community-events-toggle-location' ), - $cancelButton = $( '.community-events-cancel' ), - $form = $( '.community-events-form' ), - $target = $(); - - if ( 'object' === typeof action ) { - // The action is the event object: get the clicked element. - $target = $( action.target ); - /* - * Strict comparison doesn't work in this case because sometimes - * we explicitly pass a string as value of aria-expanded and - * sometimes a boolean as the result of an evaluation. - */ - action = 'true' == $toggleButton.attr( 'aria-expanded' ) ? 'hide' : 'show'; - } - - if ( 'hide' === action ) { - $toggleButton.attr( 'aria-expanded', 'false' ); - $cancelButton.attr( 'aria-expanded', 'false' ); - $form.attr( 'aria-hidden', 'true' ); - /* - * If the Cancel button has been clicked, bring the focus back - * to the toggle button so users relying on screen readers don't - * lose their place. - */ - if ( $target.hasClass( 'community-events-cancel' ) ) { - $toggleButton.focus(); - } - } else { - $toggleButton.attr( 'aria-expanded', 'true' ); - $cancelButton.attr( 'aria-expanded', 'true' ); - $form.attr( 'aria-hidden', 'false' ); - } - }, - - /** - * Sends REST API requests to fetch events for the widget. - * - * @since 4.8.0 - * - * @param {Object} requestParams REST API Request parameters object. - * - * @returns {void} - */ - getEvents: function( requestParams ) { - var initiatedBy, - app = this, - $spinner = $( '.community-events-form' ).children( '.spinner' ); - - requestParams = requestParams || {}; - requestParams._wpnonce = communityEventsData.nonce; - requestParams.timezone = window.Intl ? window.Intl.DateTimeFormat().resolvedOptions().timeZone : ''; - - initiatedBy = requestParams.location ? 'user' : 'app'; - - $spinner.addClass( 'is-active' ); - - wp.ajax.post( 'get-community-events', requestParams ) - .always( function() { - $spinner.removeClass( 'is-active' ); - }) - - .done( function( response ) { - if ( 'no_location_available' === response.error ) { - if ( requestParams.location ) { - response.unknownCity = requestParams.location; - } else { - /* - * No location was passed, which means that this was an automatic query - * based on IP, locale, and timezone. Since the user didn't initiate it, - * it should fail silently. Otherwise, the error could confuse and/or - * annoy them. - */ - delete response.error; - } - } - app.renderEventsTemplate( response, initiatedBy ); - }) - - .fail( function() { - app.renderEventsTemplate({ - 'location' : false, - 'error' : true - }, initiatedBy ); - }); - }, - - /** - * Renders the template for the Events section of the Events & News widget. - * - * @since 4.8.0 - * - * @param {Object} templateParams The various parameters that will get passed to wp.template. - * @param {string} initiatedBy 'user' to indicate that this was triggered manually by the user; - * 'app' to indicate it was triggered automatically by the app itself. - * - * @returns {void} - */ - renderEventsTemplate: function( templateParams, initiatedBy ) { - var template, - elementVisibility, - l10nPlaceholder = /%(?:\d\$)?s/g, // Match `%s`, `%1$s`, `%2$s`, etc. - $toggleButton = $( '.community-events-toggle-location' ), - $locationMessage = $( '#community-events-location-message' ), - $results = $( '.community-events-results' ); - - /* - * Hide all toggleable elements by default, to keep the logic simple. - * Otherwise, each block below would have to turn hide everything that - * could have been shown at an earlier point. - * - * The exception to that is that the .community-events container is hidden - * when the page is first loaded, because the content isn't ready yet, - * but once we've reached this point, it should always be shown. - */ - elementVisibility = { - '.community-events' : true, - '.community-events-loading' : false, - '.community-events-errors' : false, - '.community-events-error-occurred' : false, - '.community-events-could-not-locate' : false, - '#community-events-location-message' : false, - '.community-events-toggle-location' : false, - '.community-events-results' : false - }; - - /* - * Determine which templates should be rendered and which elements - * should be displayed. - */ - if ( templateParams.location.ip ) { - /* - * If the API determined the location by geolocating an IP, it will - * provide events, but not a specific location. - */ - $locationMessage.text( communityEventsData.l10n.attend_event_near_generic ); - - if ( templateParams.events.length ) { - template = wp.template( 'community-events-event-list' ); - $results.html( template( templateParams ) ); - } else { - template = wp.template( 'community-events-no-upcoming-events' ); - $results.html( template( templateParams ) ); - } - - elementVisibility['#community-events-location-message'] = true; - elementVisibility['.community-events-toggle-location'] = true; - elementVisibility['.community-events-results'] = true; - - } else if ( templateParams.location.description ) { - template = wp.template( 'community-events-attend-event-near' ); - $locationMessage.html( template( templateParams ) ); - - if ( templateParams.events.length ) { - template = wp.template( 'community-events-event-list' ); - $results.html( template( templateParams ) ); - } else { - template = wp.template( 'community-events-no-upcoming-events' ); - $results.html( template( templateParams ) ); - } - - if ( 'user' === initiatedBy ) { - wp.a11y.speak( communityEventsData.l10n.city_updated.replace( l10nPlaceholder, templateParams.location.description ), 'assertive' ); - } - - elementVisibility['#community-events-location-message'] = true; - elementVisibility['.community-events-toggle-location'] = true; - elementVisibility['.community-events-results'] = true; - - } else if ( templateParams.unknownCity ) { - template = wp.template( 'community-events-could-not-locate' ); - $( '.community-events-could-not-locate' ).html( template( templateParams ) ); - wp.a11y.speak( communityEventsData.l10n.could_not_locate_city.replace( l10nPlaceholder, templateParams.unknownCity ) ); - - elementVisibility['.community-events-errors'] = true; - elementVisibility['.community-events-could-not-locate'] = true; - - } else if ( templateParams.error && 'user' === initiatedBy ) { - /* - * Errors messages are only shown for requests that were initiated - * by the user, not for ones that were initiated by the app itself. - * Showing error messages for an event that user isn't aware of - * could be confusing or unnecessarily distracting. - */ - wp.a11y.speak( communityEventsData.l10n.error_occurred_please_try_again ); - - elementVisibility['.community-events-errors'] = true; - elementVisibility['.community-events-error-occurred'] = true; - } else { - $locationMessage.text( communityEventsData.l10n.enter_closest_city ); - - elementVisibility['#community-events-location-message'] = true; - elementVisibility['.community-events-toggle-location'] = true; - } - - // Set the visibility of toggleable elements. - _.each( elementVisibility, function( isVisible, element ) { - $( element ).attr( 'aria-hidden', ! isVisible ); - }); - - $toggleButton.attr( 'aria-expanded', elementVisibility['.community-events-toggle-location'] ); - - if ( templateParams.location && ( templateParams.location.ip || templateParams.location.latitude ) ) { - // Hide the form when there's a valid location. - app.toggleLocationForm( 'hide' ); - - if ( 'user' === initiatedBy ) { - /* - * When the form is programmatically hidden after a user search, - * bring the focus back to the toggle button so users relying - * on screen readers don't lose their place. - */ - $toggleButton.focus(); - } - } else { - app.toggleLocationForm( 'show' ); - } - } - }; - - if ( $( '#dashboard_primary' ).is( ':visible' ) ) { - app.init(); - } else { - $( document ).on( 'postbox-toggled', function( event, postbox ) { - var $postbox = $( postbox ); - - if ( 'dashboard_primary' === $postbox.attr( 'id' ) && $postbox.is( ':visible' ) ) { - app.init(); - } - }); - } -}); diff --git a/srcs/wordpress/wp-admin/js/dashboard.min.js b/srcs/wordpress/wp-admin/js/dashboard.min.js deleted file mode 100644 index 9ac54bf..0000000 --- a/srcs/wordpress/wp-admin/js/dashboard.min.js +++ /dev/null @@ -1 +0,0 @@ -window.wp=window.wp||{},jQuery(document).ready(function(c){var t,n=c("#welcome-panel"),e=c("#wp_welcome_panel-hide");t=function(e){c.post(ajaxurl,{action:"update-welcome-panel",visible:e,welcomepanelnonce:c("#welcomepanelnonce").val()})},n.hasClass("hidden")&&e.prop("checked")&&n.removeClass("hidden"),c(".welcome-panel-close, .welcome-panel-dismiss a",n).click(function(e){e.preventDefault(),n.addClass("hidden"),t(0),c("#wp_welcome_panel-hide").prop("checked",!1)}),e.click(function(){n.toggleClass("hidden",!this.checked),t(this.checked?1:0)}),window.ajaxWidgets=["dashboard_primary"],window.ajaxPopulateWidgets=function(e){function t(e,t){var n,o=c("#"+t+" div.inside:visible").find(".widget-loading");o.length&&(n=o.parent(),setTimeout(function(){n.load(ajaxurl+"?action=dashboard-widgets&widget="+t+"&pagenow="+pagenow,"",function(){n.hide().slideDown("normal",function(){c(this).css("display","")})})},500*e))}e?(e=e.toString(),-1!==c.inArray(e,ajaxWidgets)&&t(0,e)):c.each(ajaxWidgets,t)},ajaxPopulateWidgets(),postboxes.add_postbox_toggles(pagenow,{pbshow:ajaxPopulateWidgets}),window.quickPressLoad=function(){var t,e=c("#quickpost-action");c('#quick-press .submit input[type="submit"], #quick-press .submit input[type="reset"]').prop("disabled",!1),t=c("#quick-press").submit(function(e){e.preventDefault(),c("#dashboard_quick_press #publishing-action .spinner").show(),c('#quick-press .submit input[type="submit"], #quick-press .submit input[type="reset"]').prop("disabled",!0),c.post(t.attr("action"),t.serializeArray(),function(e){c("#dashboard_quick_press .inside").html(e),c("#quick-press").removeClass("initial-form"),quickPressLoad(),function(){var e=c(".drafts ul li").first();e.css("background","#fffbe5"),setTimeout(function(){e.css("background","none")},1e3)}(),c("#title").focus()})}),c("#publish").click(function(){e.val("post-quickpress-publish")}),c("#quick-press").on("click focusin",function(){wpActiveEditor="content"}),function(){if(document.documentMode&&document.documentMode<9)return;c("body").append('<div class="quick-draft-textarea-clone" style="display: none;"></div>');var o=c(".quick-draft-textarea-clone"),i=c("#content"),a=i.height(),s=c(window).height()-100;o.css({"font-family":i.css("font-family"),"font-size":i.css("font-size"),"line-height":i.css("line-height"),"padding-bottom":i.css("paddingBottom"),"padding-left":i.css("paddingLeft"),"padding-right":i.css("paddingRight"),"padding-top":i.css("paddingTop"),"white-space":"pre-wrap","word-wrap":"break-word",display:"none"}),i.on("focus input propertychange",function(){var e=c(this),t=e.val()+" ",n=o.css("width",e.css("width")).text(t).outerHeight()+2;i.css("overflow-y","auto"),n===a||s<=n&&s<=a||(a=s<n?s:n,i.css("overflow","hidden"),e.css("height",a+"px"))})}()},window.quickPressLoad(),c(".meta-box-sortables").sortable("option","containment","#wpwrap")}),jQuery(function(r){"use strict";var l,d=window.communityEventsData||{};l=window.wp.communityEvents={initialized:!1,model:null,init:function(){if(!l.initialized){var e=r("#community-events");r(".community-events-errors").attr("aria-hidden","true").removeClass("hide-if-js"),e.on("click",".community-events-toggle-location, .community-events-cancel",l.toggleLocationForm),e.on("submit",".community-events-form",function(e){var t=r.trim(r("#community-events-location").val());e.preventDefault(),t&&l.getEvents({location:t})}),d&&d.cache&&d.cache.location&&d.cache.events?l.renderEventsTemplate(d.cache,"app"):l.getEvents(),l.initialized=!0}},toggleLocationForm:function(e){var t=r(".community-events-toggle-location"),n=r(".community-events-cancel"),o=r(".community-events-form"),i=r();"object"==typeof e&&(i=r(e.target),e="true"==t.attr("aria-expanded")?"hide":"show"),"hide"===e?(t.attr("aria-expanded","false"),n.attr("aria-expanded","false"),o.attr("aria-hidden","true"),i.hasClass("community-events-cancel")&&t.focus()):(t.attr("aria-expanded","true"),n.attr("aria-expanded","true"),o.attr("aria-hidden","false"))},getEvents:function(t){var n,o=this,e=r(".community-events-form").children(".spinner");(t=t||{})._wpnonce=d.nonce,t.timezone=window.Intl?window.Intl.DateTimeFormat().resolvedOptions().timeZone:"",n=t.location?"user":"app",e.addClass("is-active"),wp.ajax.post("get-community-events",t).always(function(){e.removeClass("is-active")}).done(function(e){"no_location_available"===e.error&&(t.location?e.unknownCity=t.location:delete e.error),o.renderEventsTemplate(e,n)}).fail(function(){o.renderEventsTemplate({location:!1,error:!0},n)})},renderEventsTemplate:function(e,t){var n,o,i=/%(?:\d\$)?s/g,a=r(".community-events-toggle-location"),s=r("#community-events-location-message"),c=r(".community-events-results");o={".community-events":!0,".community-events-loading":!1,".community-events-errors":!1,".community-events-error-occurred":!1,".community-events-could-not-locate":!1,"#community-events-location-message":!1,".community-events-toggle-location":!1,".community-events-results":!1},e.location.ip?(s.text(d.l10n.attend_event_near_generic),n=e.events.length?wp.template("community-events-event-list"):wp.template("community-events-no-upcoming-events"),c.html(n(e)),o["#community-events-location-message"]=!0,o[".community-events-toggle-location"]=!0,o[".community-events-results"]=!0):e.location.description?(n=wp.template("community-events-attend-event-near"),s.html(n(e)),n=e.events.length?wp.template("community-events-event-list"):wp.template("community-events-no-upcoming-events"),c.html(n(e)),"user"===t&&wp.a11y.speak(d.l10n.city_updated.replace(i,e.location.description),"assertive"),o["#community-events-location-message"]=!0,o[".community-events-toggle-location"]=!0,o[".community-events-results"]=!0):e.unknownCity?(n=wp.template("community-events-could-not-locate"),r(".community-events-could-not-locate").html(n(e)),wp.a11y.speak(d.l10n.could_not_locate_city.replace(i,e.unknownCity)),o[".community-events-errors"]=!0,o[".community-events-could-not-locate"]=!0):e.error&&"user"===t?(wp.a11y.speak(d.l10n.error_occurred_please_try_again),o[".community-events-errors"]=!0,o[".community-events-error-occurred"]=!0):(s.text(d.l10n.enter_closest_city),o["#community-events-location-message"]=!0,o[".community-events-toggle-location"]=!0),_.each(o,function(e,t){r(t).attr("aria-hidden",!e)}),a.attr("aria-expanded",o[".community-events-toggle-location"]),e.location&&(e.location.ip||e.location.latitude)?(l.toggleLocationForm("hide"),"user"===t&&a.focus()):l.toggleLocationForm("show")}},r("#dashboard_primary").is(":visible")?l.init():r(document).on("postbox-toggled",function(e,t){var n=r(t);"dashboard_primary"===n.attr("id")&&n.is(":visible")&&l.init()})});
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/edit-comments.js b/srcs/wordpress/wp-admin/js/edit-comments.js deleted file mode 100644 index 4391d50..0000000 --- a/srcs/wordpress/wp-admin/js/edit-comments.js +++ /dev/null @@ -1,1342 +0,0 @@ -/** - * Handles updating and editing comments. - * - * @file This file contains functionality for the admin comments page. - * @since 2.1.0 - * @output wp-admin/js/edit-comments.js - */ - -/* global adminCommentsL10n, thousandsSeparator, list_args, QTags, ajaxurl, wpAjax */ -/* global commentReply, theExtraList, theList, setCommentsList */ - -(function($) { -var getCount, updateCount, updateCountText, updatePending, updateApproved, - updateHtmlTitle, updateDashboardText, updateInModerationText, adminTitle = document.title, - isDashboard = $('#dashboard_right_now').length, - titleDiv, titleRegEx; - - /** - * Extracts a number from the content of a jQuery element. - * - * @since 2.9.0 - * @access private - * - * @param {jQuery} el jQuery element. - * - * @return {number} The number found in the given element. - */ - getCount = function(el) { - var n = parseInt( el.html().replace(/[^0-9]+/g, ''), 10 ); - if ( isNaN(n) ) { - return 0; - } - return n; - }; - - /** - * Updates an html element with a localized number string. - * - * @since 2.9.0 - * @access private - * - * @param {jQuery} el The jQuery element to update. - * @param {number} n Number to be put in the element. - * - * @return {void} - */ - updateCount = function(el, n) { - var n1 = ''; - if ( isNaN(n) ) { - return; - } - n = n < 1 ? '0' : n.toString(); - if ( n.length > 3 ) { - while ( n.length > 3 ) { - n1 = thousandsSeparator + n.substr(n.length - 3) + n1; - n = n.substr(0, n.length - 3); - } - n = n + n1; - } - el.html(n); - }; - - /** - * Updates the number of approved comments on a specific post and the filter bar. - * - * @since 4.4.0 - * @access private - * - * @param {number} diff The amount to lower or raise the approved count with. - * @param {number} commentPostId The ID of the post to be updated. - * - * @return {void} - */ - updateApproved = function( diff, commentPostId ) { - var postSelector = '.post-com-count-' + commentPostId, - noClass = 'comment-count-no-comments', - approvedClass = 'comment-count-approved', - approved, - noComments; - - updateCountText( 'span.approved-count', diff ); - - if ( ! commentPostId ) { - return; - } - - // Cache selectors to not get duplicates. - approved = $( 'span.' + approvedClass, postSelector ); - noComments = $( 'span.' + noClass, postSelector ); - - approved.each(function() { - var a = $(this), n = getCount(a) + diff; - if ( n < 1 ) - n = 0; - - if ( 0 === n ) { - a.removeClass( approvedClass ).addClass( noClass ); - } else { - a.addClass( approvedClass ).removeClass( noClass ); - } - updateCount( a, n ); - }); - - noComments.each(function() { - var a = $(this); - if ( diff > 0 ) { - a.removeClass( noClass ).addClass( approvedClass ); - } else { - a.addClass( noClass ).removeClass( approvedClass ); - } - updateCount( a, diff ); - }); - }; - - /** - * Updates a number count in all matched HTML elements - * - * @since 4.4.0 - * @access private - * - * @param {string} selector The jQuery selector for elements to update a count - * for. - * @param {number} diff The amount to lower or raise the count with. - * - * @return {void} - */ - updateCountText = function( selector, diff ) { - $( selector ).each(function() { - var a = $(this), n = getCount(a) + diff; - if ( n < 1 ) { - n = 0; - } - updateCount( a, n ); - }); - }; - - /** - * Updates a text about comment count on the dashboard. - * - * @since 4.4.0 - * @access private - * - * @param {Object} response Ajax response from the server that includes a - * translated "comment count" message. - * - * @return {void} - */ - updateDashboardText = function( response ) { - if ( ! isDashboard || ! response || ! response.i18n_comments_text ) { - return; - } - - $( '.comment-count a', '#dashboard_right_now' ).text( response.i18n_comments_text ); - }; - - /** - * Updates the "comments in moderation" text across the UI. - * - * @since 5.2.0 - * - * @param {object} response Ajax response from the server that includes a - * translated "comments in moderation" message. - * - * @return {void} - */ - updateInModerationText = function( response ) { - if ( ! response || ! response.i18n_moderation_text ) { - return; - } - - // Update the "comment in moderation" text across the UI. - $( '.comments-in-moderation-text' ).text( response.i18n_moderation_text ); - // Hide the "comment in moderation" text in the Dashboard "At a Glance" widget. - if ( isDashboard && response.in_moderation ) { - $( '.comment-mod-count', '#dashboard_right_now' ) - [ response.in_moderation > 0 ? 'removeClass' : 'addClass' ]( 'hidden' ); - } - }; - - /** - * Updates the title of the document with the number comments to be approved. - * - * @since 4.4.0 - * @access private - * - * @param {number} diff The amount to lower or raise the number of to be - * approved comments with. - * - * @return {void} - */ - updateHtmlTitle = function( diff ) { - var newTitle, regExMatch, titleCount, commentFrag; - - titleRegEx = titleRegEx || new RegExp( adminCommentsL10n.docTitleCommentsCount.replace( '%s', '\\([0-9' + thousandsSeparator + ']+\\)' ) + '?' ); - // count funcs operate on a $'d element - titleDiv = titleDiv || $( '<div />' ); - newTitle = adminTitle; - - commentFrag = titleRegEx.exec( document.title ); - if ( commentFrag ) { - commentFrag = commentFrag[0]; - titleDiv.html( commentFrag ); - titleCount = getCount( titleDiv ) + diff; - } else { - titleDiv.html( 0 ); - titleCount = diff; - } - - if ( titleCount >= 1 ) { - updateCount( titleDiv, titleCount ); - regExMatch = titleRegEx.exec( document.title ); - if ( regExMatch ) { - newTitle = document.title.replace( regExMatch[0], adminCommentsL10n.docTitleCommentsCount.replace( '%s', titleDiv.text() ) + ' ' ); - } - } else { - regExMatch = titleRegEx.exec( newTitle ); - if ( regExMatch ) { - newTitle = newTitle.replace( regExMatch[0], adminCommentsL10n.docTitleComments ); - } - } - document.title = newTitle; - }; - - /** - * Updates the number of pending comments on a specific post and the filter bar. - * - * @since 3.2.0 - * @access private - * - * @param {number} diff The amount to lower or raise the pending count with. - * @param {number} commentPostId The ID of the post to be updated. - * - * @return {void} - */ - updatePending = function( diff, commentPostId ) { - var postSelector = '.post-com-count-' + commentPostId, - noClass = 'comment-count-no-pending', - noParentClass = 'post-com-count-no-pending', - pendingClass = 'comment-count-pending', - pending, - noPending; - - if ( ! isDashboard ) { - updateHtmlTitle( diff ); - } - - $( 'span.pending-count' ).each(function() { - var a = $(this), n = getCount(a) + diff; - if ( n < 1 ) - n = 0; - a.closest('.awaiting-mod')[ 0 === n ? 'addClass' : 'removeClass' ]('count-0'); - updateCount( a, n ); - }); - - if ( ! commentPostId ) { - return; - } - - // cache selectors to not get dupes - pending = $( 'span.' + pendingClass, postSelector ); - noPending = $( 'span.' + noClass, postSelector ); - - pending.each(function() { - var a = $(this), n = getCount(a) + diff; - if ( n < 1 ) - n = 0; - - if ( 0 === n ) { - a.parent().addClass( noParentClass ); - a.removeClass( pendingClass ).addClass( noClass ); - } else { - a.parent().removeClass( noParentClass ); - a.addClass( pendingClass ).removeClass( noClass ); - } - updateCount( a, n ); - }); - - noPending.each(function() { - var a = $(this); - if ( diff > 0 ) { - a.parent().removeClass( noParentClass ); - a.removeClass( noClass ).addClass( pendingClass ); - } else { - a.parent().addClass( noParentClass ); - a.addClass( noClass ).removeClass( pendingClass ); - } - updateCount( a, diff ); - }); - }; - -/** - * Initializes the comments list. - * - * @since 4.4.0 - * - * @global - * - * @return {void} - */ -window.setCommentsList = function() { - var totalInput, perPageInput, pageInput, dimAfter, delBefore, updateTotalCount, delAfter, refillTheExtraList, diff, - lastConfidentTime = 0; - - totalInput = $('input[name="_total"]', '#comments-form'); - perPageInput = $('input[name="_per_page"]', '#comments-form'); - pageInput = $('input[name="_page"]', '#comments-form'); - - /** - * Updates the total with the latest count. - * - * The time parameter makes sure that we only update the total if this value is - * a newer value than we previously received. - * - * The time and setConfidentTime parameters make sure that we only update the - * total when necessary. So a value that has been generated earlier will not - * update the total. - * - * @since 2.8.0 - * @access private - * - * @param {number} total Total number of comments. - * @param {number} time Unix timestamp of response. - * @param {boolean} setConfidentTime Whether to update the last confident time - * with the given time. - * - * @return {void} - */ - updateTotalCount = function( total, time, setConfidentTime ) { - if ( time < lastConfidentTime ) - return; - - if ( setConfidentTime ) - lastConfidentTime = time; - - totalInput.val( total.toString() ); - }; - - /** - * Changes DOM that need to be changed after a list item has been dimmed. - * - * @since 2.5.0 - * @access private - * - * @param {Object} r Ajax response object. - * @param {Object} settings Settings for the wpList object. - * - * @return {void} - */ - dimAfter = function( r, settings ) { - var editRow, replyID, replyButton, response, - c = $( '#' + settings.element ); - - if ( true !== settings.parsed ) { - response = settings.parsed.responses[0]; - } - - editRow = $('#replyrow'); - replyID = $('#comment_ID', editRow).val(); - replyButton = $('#replybtn', editRow); - - if ( c.is('.unapproved') ) { - if ( settings.data.id == replyID ) - replyButton.text(adminCommentsL10n.replyApprove); - - c.find( '.row-actions span.view' ).addClass( 'hidden' ).end() - .find( 'div.comment_status' ).html( '0' ); - - } else { - if ( settings.data.id == replyID ) - replyButton.text(adminCommentsL10n.reply); - - c.find( '.row-actions span.view' ).removeClass( 'hidden' ).end() - .find( 'div.comment_status' ).html( '1' ); - } - - diff = $('#' + settings.element).is('.' + settings.dimClass) ? 1 : -1; - if ( response ) { - updateDashboardText( response.supplemental ); - updateInModerationText( response.supplemental ); - updatePending( diff, response.supplemental.postId ); - updateApproved( -1 * diff, response.supplemental.postId ); - } else { - updatePending( diff ); - updateApproved( -1 * diff ); - } - }; - - /** - * Handles marking a comment as spam or trashing the comment. - * - * Is executed in the list delBefore hook. - * - * @since 2.8.0 - * @access private - * - * @param {Object} settings Settings for the wpList object. - * @param {HTMLElement} list Comments table element. - * - * @return {Object} The settings object. - */ - delBefore = function( settings, list ) { - var note, id, el, n, h, a, author, - action = false, - wpListsData = $( settings.target ).attr( 'data-wp-lists' ); - - settings.data._total = totalInput.val() || 0; - settings.data._per_page = perPageInput.val() || 0; - settings.data._page = pageInput.val() || 0; - settings.data._url = document.location.href; - settings.data.comment_status = $('input[name="comment_status"]', '#comments-form').val(); - - if ( wpListsData.indexOf(':trash=1') != -1 ) - action = 'trash'; - else if ( wpListsData.indexOf(':spam=1') != -1 ) - action = 'spam'; - - if ( action ) { - id = wpListsData.replace(/.*?comment-([0-9]+).*/, '$1'); - el = $('#comment-' + id); - note = $('#' + action + '-undo-holder').html(); - - el.find('.check-column :checkbox').prop('checked', false); // Uncheck the row so as not to be affected by Bulk Edits. - - if ( el.siblings('#replyrow').length && commentReply.cid == id ) - commentReply.close(); - - if ( el.is('tr') ) { - n = el.children(':visible').length; - author = $('.author strong', el).text(); - h = $('<tr id="undo-' + id + '" class="undo un' + action + '" style="display:none;"><td colspan="' + n + '">' + note + '</td></tr>'); - } else { - author = $('.comment-author', el).text(); - h = $('<div id="undo-' + id + '" style="display:none;" class="undo un' + action + '">' + note + '</div>'); - } - - el.before(h); - - $('strong', '#undo-' + id).text(author); - a = $('.undo a', '#undo-' + id); - a.attr('href', 'comment.php?action=un' + action + 'comment&c=' + id + '&_wpnonce=' + settings.data._ajax_nonce); - a.attr('data-wp-lists', 'delete:the-comment-list:comment-' + id + '::un' + action + '=1'); - a.attr('class', 'vim-z vim-destructive aria-button-if-js'); - $('.avatar', el).first().clone().prependTo('#undo-' + id + ' .' + action + '-undo-inside'); - - a.click(function( e ){ - e.preventDefault(); - e.stopPropagation(); // ticket #35904 - list.wpList.del(this); - $('#undo-' + id).css( {backgroundColor:'#ceb'} ).fadeOut(350, function(){ - $(this).remove(); - $('#comment-' + id).css('backgroundColor', '').fadeIn(300, function(){ $(this).show(); }); - }); - }); - } - - return settings; - }; - - /** - * Handles actions that need to be done after marking as spam or thrashing a - * comment. - * - * The ajax requests return the unix time stamp a comment was marked as spam or - * trashed. We use this to have a correct total amount of comments. - * - * @since 2.5.0 - * @access private - * - * @param {Object} r Ajax response object. - * @param {Object} settings Settings for the wpList object. - * - * @return {void} - */ - delAfter = function( r, settings ) { - var total_items_i18n, total, animated, animatedCallback, - response = true === settings.parsed ? {} : settings.parsed.responses[0], - commentStatus = true === settings.parsed ? '' : response.supplemental.status, - commentPostId = true === settings.parsed ? '' : response.supplemental.postId, - newTotal = true === settings.parsed ? '' : response.supplemental, - - targetParent = $( settings.target ).parent(), - commentRow = $('#' + settings.element), - - spamDiff, trashDiff, pendingDiff, approvedDiff, - - /* - * As `wpList` toggles only the `unapproved` class, the approved comment - * rows can have both the `approved` and `unapproved` classes. - */ - approved = commentRow.hasClass( 'approved' ) && ! commentRow.hasClass( 'unapproved' ), - unapproved = commentRow.hasClass( 'unapproved' ), - spammed = commentRow.hasClass( 'spam' ), - trashed = commentRow.hasClass( 'trash' ), - undoing = false; // ticket #35904 - - updateDashboardText( newTotal ); - updateInModerationText( newTotal ); - - // the order of these checks is important - // .unspam can also have .approve or .unapprove - // .untrash can also have .approve or .unapprove - - if ( targetParent.is( 'span.undo' ) ) { - // the comment was spammed - if ( targetParent.hasClass( 'unspam' ) ) { - spamDiff = -1; - - if ( 'trash' === commentStatus ) { - trashDiff = 1; - } else if ( '1' === commentStatus ) { - approvedDiff = 1; - } else if ( '0' === commentStatus ) { - pendingDiff = 1; - } - - // the comment was trashed - } else if ( targetParent.hasClass( 'untrash' ) ) { - trashDiff = -1; - - if ( 'spam' === commentStatus ) { - spamDiff = 1; - } else if ( '1' === commentStatus ) { - approvedDiff = 1; - } else if ( '0' === commentStatus ) { - pendingDiff = 1; - } - } - - undoing = true; - - // user clicked "Spam" - } else if ( targetParent.is( 'span.spam' ) ) { - // the comment is currently approved - if ( approved ) { - approvedDiff = -1; - // the comment is currently pending - } else if ( unapproved ) { - pendingDiff = -1; - // the comment was in the trash - } else if ( trashed ) { - trashDiff = -1; - } - // you can't spam an item on the spam screen - spamDiff = 1; - - // user clicked "Unspam" - } else if ( targetParent.is( 'span.unspam' ) ) { - if ( approved ) { - pendingDiff = 1; - } else if ( unapproved ) { - approvedDiff = 1; - } else if ( trashed ) { - // the comment was previously approved - if ( targetParent.hasClass( 'approve' ) ) { - approvedDiff = 1; - // the comment was previously pending - } else if ( targetParent.hasClass( 'unapprove' ) ) { - pendingDiff = 1; - } - } else if ( spammed ) { - if ( targetParent.hasClass( 'approve' ) ) { - approvedDiff = 1; - - } else if ( targetParent.hasClass( 'unapprove' ) ) { - pendingDiff = 1; - } - } - // you can Unspam an item on the spam screen - spamDiff = -1; - - // user clicked "Trash" - } else if ( targetParent.is( 'span.trash' ) ) { - if ( approved ) { - approvedDiff = -1; - } else if ( unapproved ) { - pendingDiff = -1; - // the comment was in the spam queue - } else if ( spammed ) { - spamDiff = -1; - } - // you can't trash an item on the trash screen - trashDiff = 1; - - // user clicked "Restore" - } else if ( targetParent.is( 'span.untrash' ) ) { - if ( approved ) { - pendingDiff = 1; - } else if ( unapproved ) { - approvedDiff = 1; - } else if ( trashed ) { - if ( targetParent.hasClass( 'approve' ) ) { - approvedDiff = 1; - } else if ( targetParent.hasClass( 'unapprove' ) ) { - pendingDiff = 1; - } - } - // you can't go from trash to spam - // you can untrash on the trash screen - trashDiff = -1; - - // User clicked "Approve" - } else if ( targetParent.is( 'span.approve:not(.unspam):not(.untrash)' ) ) { - approvedDiff = 1; - pendingDiff = -1; - - // User clicked "Unapprove" - } else if ( targetParent.is( 'span.unapprove:not(.unspam):not(.untrash)' ) ) { - approvedDiff = -1; - pendingDiff = 1; - - // User clicked "Delete Permanently" - } else if ( targetParent.is( 'span.delete' ) ) { - if ( spammed ) { - spamDiff = -1; - } else if ( trashed ) { - trashDiff = -1; - } - } - - if ( pendingDiff ) { - updatePending( pendingDiff, commentPostId ); - updateCountText( 'span.all-count', pendingDiff ); - } - - if ( approvedDiff ) { - updateApproved( approvedDiff, commentPostId ); - updateCountText( 'span.all-count', approvedDiff ); - } - - if ( spamDiff ) { - updateCountText( 'span.spam-count', spamDiff ); - } - - if ( trashDiff ) { - updateCountText( 'span.trash-count', trashDiff ); - } - - if ( - ( ( 'trash' === settings.data.comment_status ) && !getCount( $( 'span.trash-count' ) ) ) || - ( ( 'spam' === settings.data.comment_status ) && !getCount( $( 'span.spam-count' ) ) ) - ) { - $( '#delete_all' ).hide(); - } - - if ( ! isDashboard ) { - total = totalInput.val() ? parseInt( totalInput.val(), 10 ) : 0; - if ( $(settings.target).parent().is('span.undo') ) - total++; - else - total--; - - if ( total < 0 ) - total = 0; - - if ( 'object' === typeof r ) { - if ( response.supplemental.total_items_i18n && lastConfidentTime < response.supplemental.time ) { - total_items_i18n = response.supplemental.total_items_i18n || ''; - if ( total_items_i18n ) { - $('.displaying-num').text( total_items_i18n.replace( ' ', String.fromCharCode( 160 ) ) ); - $('.total-pages').text( response.supplemental.total_pages_i18n.replace( ' ', String.fromCharCode( 160 ) ) ); - $('.tablenav-pages').find('.next-page, .last-page').toggleClass('disabled', response.supplemental.total_pages == $('.current-page').val()); - } - updateTotalCount( total, response.supplemental.time, true ); - } else if ( response.supplemental.time ) { - updateTotalCount( total, response.supplemental.time, false ); - } - } else { - updateTotalCount( total, r, false ); - } - } - - if ( ! theExtraList || theExtraList.length === 0 || theExtraList.children().length === 0 || undoing ) { - return; - } - - theList.get(0).wpList.add( theExtraList.children( ':eq(0):not(.no-items)' ).remove().clone() ); - - refillTheExtraList(); - - animated = $( ':animated', '#the-comment-list' ); - animatedCallback = function() { - if ( ! $( '#the-comment-list tr:visible' ).length ) { - theList.get(0).wpList.add( theExtraList.find( '.no-items' ).clone() ); - } - }; - - if ( animated.length ) { - animated.promise().done( animatedCallback ); - } else { - animatedCallback(); - } - }; - - /** - * Retrieves additional comments to populate the extra list. - * - * @since 3.1.0 - * @access private - * - * @param {boolean} [ev] Repopulate the extra comments list if true. - * - * @return {void} - */ - refillTheExtraList = function(ev) { - var args = $.query.get(), total_pages = $('.total-pages').text(), per_page = $('input[name="_per_page"]', '#comments-form').val(); - - if (! args.paged) - args.paged = 1; - - if (args.paged > total_pages) { - return; - } - - if (ev) { - theExtraList.empty(); - args.number = Math.min(8, per_page); // see WP_Comments_List_Table::prepare_items() @ class-wp-comments-list-table.php - } else { - args.number = 1; - args.offset = Math.min(8, per_page) - 1; // fetch only the next item on the extra list - } - - args.no_placeholder = true; - - args.paged ++; - - // $.query.get() needs some correction to be sent into an ajax request - if ( true === args.comment_type ) - args.comment_type = ''; - - args = $.extend(args, { - 'action': 'fetch-list', - 'list_args': list_args, - '_ajax_fetch_list_nonce': $('#_ajax_fetch_list_nonce').val() - }); - - $.ajax({ - url: ajaxurl, - global: false, - dataType: 'json', - data: args, - success: function(response) { - theExtraList.get(0).wpList.add( response.rows ); - } - }); - }; - - /** - * Globally available jQuery object referring to the extra comments list. - * - * @global - */ - window.theExtraList = $('#the-extra-comment-list').wpList( { alt: '', delColor: 'none', addColor: 'none' } ); - - /** - * Globally available jQuery object referring to the comments list. - * - * @global - */ - window.theList = $('#the-comment-list').wpList( { alt: '', delBefore: delBefore, dimAfter: dimAfter, delAfter: delAfter, addColor: 'none' } ) - .bind('wpListDelEnd', function(e, s){ - var wpListsData = $(s.target).attr('data-wp-lists'), id = s.element.replace(/[^0-9]+/g, ''); - - if ( wpListsData.indexOf(':trash=1') != -1 || wpListsData.indexOf(':spam=1') != -1 ) - $('#undo-' + id).fadeIn(300, function(){ $(this).show(); }); - }); -}; - -/** - * Object containing functionality regarding the comment quick editor and reply - * editor. - * - * @since 2.7.0 - * - * @global - */ -window.commentReply = { - cid : '', - act : '', - originalContent : '', - - /** - * Initializes the comment reply functionality. - * - * @memberof commentReply - * - * @since 2.7.0 - */ - init : function() { - var row = $('#replyrow'); - - $( '.cancel', row ).click( function() { return commentReply.revert(); } ); - $( '.save', row ).click( function() { return commentReply.send(); } ); - $( 'input#author-name, input#author-email, input#author-url', row ).keypress( function( e ) { - if ( e.which == 13 ) { - commentReply.send(); - e.preventDefault(); - return false; - } - }); - - // add events - $('#the-comment-list .column-comment > p').dblclick(function(){ - commentReply.toggle($(this).parent()); - }); - - $('#doaction, #doaction2, #post-query-submit').click(function(){ - if ( $('#the-comment-list #replyrow').length > 0 ) - commentReply.close(); - }); - - this.comments_listing = $('#comments-form > input[name="comment_status"]').val() || ''; - }, - - /** - * Adds doubleclick event handler to the given comment list row. - * - * The double-click event will toggle the comment edit or reply form. - * - * @since 2.7.0 - * - * @memberof commentReply - * - * @param {Object} r The row to add double click handlers to. - * - * @return {void} - */ - addEvents : function(r) { - r.each(function() { - $(this).find('.column-comment > p').dblclick(function(){ - commentReply.toggle($(this).parent()); - }); - }); - }, - - /** - * Opens the quick edit for the given element. - * - * @since 2.7.0 - * - * @memberof commentReply - * - * @param {HTMLElement} el The element you want to open the quick editor for. - * - * @return {void} - */ - toggle : function(el) { - if ( 'none' !== $( el ).css( 'display' ) && ( $( '#replyrow' ).parent().is('#com-reply') || window.confirm( adminCommentsL10n.warnQuickEdit ) ) ) { - $( el ).find( 'button.vim-q' ).click(); - } - }, - - /** - * Closes the comment quick edit or reply form and undoes any changes. - * - * @since 2.7.0 - * - * @memberof commentReply - * - * @return {void} - */ - revert : function() { - - if ( $('#the-comment-list #replyrow').length < 1 ) - return false; - - $('#replyrow').fadeOut('fast', function(){ - commentReply.close(); - }); - }, - - /** - * Closes the comment quick edit or reply form and undoes any changes. - * - * @since 2.7.0 - * - * @memberof commentReply - * - * @return {void} - */ - close : function() { - var commentRow = $(), - replyRow = $( '#replyrow' ); - - // Return if the replyrow is not showing. - if ( replyRow.parent().is( '#com-reply' ) ) { - return; - } - - if ( this.cid ) { - commentRow = $( '#comment-' + this.cid ); - } - - /* - * When closing the Quick Edit form, show the comment row and move focus - * back to the Quick Edit button. - */ - if ( 'edit-comment' === this.act ) { - commentRow.fadeIn( 300, function() { - commentRow - .show() - .find( '.vim-q' ) - .attr( 'aria-expanded', 'false' ) - .focus(); - } ).css( 'backgroundColor', '' ); - } - - // When closing the Reply form, move focus back to the Reply button. - if ( 'replyto-comment' === this.act ) { - commentRow.find( '.vim-r' ) - .attr( 'aria-expanded', 'false' ) - .focus(); - } - - // reset the Quicktags buttons - if ( typeof QTags != 'undefined' ) - QTags.closeAllTags('replycontent'); - - $('#add-new-comment').css('display', ''); - - replyRow.hide(); - $( '#com-reply' ).append( replyRow ); - $('#replycontent').css('height', '').val(''); - $('#edithead input').val(''); - $( '.notice-error', replyRow ) - .addClass( 'hidden' ) - .find( '.error' ).empty(); - $( '.spinner', replyRow ).removeClass( 'is-active' ); - - this.cid = ''; - this.originalContent = ''; - }, - - /** - * Opens the comment quick edit or reply form. - * - * @since 2.7.0 - * - * @memberof commentReply - * - * @param {number} comment_id The comment id to open an editor for. - * @param {number} post_id The post id to open an editor for. - * @param {string} action The action to perform. Either 'edit' or 'replyto'. - * - * @return {boolean} Always false. - */ - open : function(comment_id, post_id, action) { - var editRow, rowData, act, replyButton, editHeight, - t = this, - c = $('#comment-' + comment_id), - h = c.height(), - colspanVal = 0; - - if ( ! this.discardCommentChanges() ) { - return false; - } - - t.close(); - t.cid = comment_id; - - editRow = $('#replyrow'); - rowData = $('#inline-'+comment_id); - action = action || 'replyto'; - act = 'edit' == action ? 'edit' : 'replyto'; - act = t.act = act + '-comment'; - t.originalContent = $('textarea.comment', rowData).val(); - colspanVal = $( '> th:visible, > td:visible', c ).length; - - // Make sure it's actually a table and there's a `colspan` value to apply. - if ( editRow.hasClass( 'inline-edit-row' ) && 0 !== colspanVal ) { - $( 'td', editRow ).attr( 'colspan', colspanVal ); - } - - $('#action', editRow).val(act); - $('#comment_post_ID', editRow).val(post_id); - $('#comment_ID', editRow).val(comment_id); - - if ( action == 'edit' ) { - $( '#author-name', editRow ).val( $( 'div.author', rowData ).text() ); - $('#author-email', editRow).val( $('div.author-email', rowData).text() ); - $('#author-url', editRow).val( $('div.author-url', rowData).text() ); - $('#status', editRow).val( $('div.comment_status', rowData).text() ); - $('#replycontent', editRow).val( $('textarea.comment', rowData).val() ); - $( '#edithead, #editlegend, #savebtn', editRow ).show(); - $('#replyhead, #replybtn, #addhead, #addbtn', editRow).hide(); - - if ( h > 120 ) { - // Limit the maximum height when editing very long comments to make it more manageable. - // The textarea is resizable in most browsers, so the user can adjust it if needed. - editHeight = h > 500 ? 500 : h; - $('#replycontent', editRow).css('height', editHeight + 'px'); - } - - c.after( editRow ).fadeOut('fast', function(){ - $('#replyrow').fadeIn(300, function(){ $(this).show(); }); - }); - } else if ( action == 'add' ) { - $('#addhead, #addbtn', editRow).show(); - $( '#replyhead, #replybtn, #edithead, #editlegend, #savebtn', editRow ) .hide(); - $('#the-comment-list').prepend(editRow); - $('#replyrow').fadeIn(300); - } else { - replyButton = $('#replybtn', editRow); - $( '#edithead, #editlegend, #savebtn, #addhead, #addbtn', editRow ).hide(); - $('#replyhead, #replybtn', editRow).show(); - c.after(editRow); - - if ( c.hasClass('unapproved') ) { - replyButton.text(adminCommentsL10n.replyApprove); - } else { - replyButton.text(adminCommentsL10n.reply); - } - - $('#replyrow').fadeIn(300, function(){ $(this).show(); }); - } - - setTimeout(function() { - var rtop, rbottom, scrollTop, vp, scrollBottom; - - rtop = $('#replyrow').offset().top; - rbottom = rtop + $('#replyrow').height(); - scrollTop = window.pageYOffset || document.documentElement.scrollTop; - vp = document.documentElement.clientHeight || window.innerHeight || 0; - scrollBottom = scrollTop + vp; - - if ( scrollBottom - 20 < rbottom ) - window.scroll(0, rbottom - vp + 35); - else if ( rtop - 20 < scrollTop ) - window.scroll(0, rtop - 35); - - $('#replycontent').focus().keyup(function(e){ - if ( e.which == 27 ) - commentReply.revert(); // close on Escape - }); - }, 600); - - return false; - }, - - /** - * Submits the comment quick edit or reply form. - * - * @since 2.7.0 - * - * @memberof commentReply - * - * @return {void} - */ - send : function() { - var post = {}, - $errorNotice = $( '#replysubmit .error-notice' ); - - $errorNotice.addClass( 'hidden' ); - $( '#replysubmit .spinner' ).addClass( 'is-active' ); - - $('#replyrow input').not(':button').each(function() { - var t = $(this); - post[ t.attr('name') ] = t.val(); - }); - - post.content = $('#replycontent').val(); - post.id = post.comment_post_ID; - post.comments_listing = this.comments_listing; - post.p = $('[name="p"]').val(); - - if ( $('#comment-' + $('#comment_ID').val()).hasClass('unapproved') ) - post.approve_parent = 1; - - $.ajax({ - type : 'POST', - url : ajaxurl, - data : post, - success : function(x) { commentReply.show(x); }, - error : function(r) { commentReply.error(r); } - }); - }, - - /** - * Shows the new or updated comment or reply. - * - * This function needs to be passed the ajax result as received from the server. - * It will handle the response and show the comment that has just been saved to - * the server. - * - * @since 2.7.0 - * - * @memberof commentReply - * - * @param {Object} xml Ajax response object. - * - * @return {void} - */ - show : function(xml) { - var t = this, r, c, id, bg, pid; - - if ( typeof(xml) == 'string' ) { - t.error({'responseText': xml}); - return false; - } - - r = wpAjax.parseAjaxResponse(xml); - if ( r.errors ) { - t.error({'responseText': wpAjax.broken}); - return false; - } - - t.revert(); - - r = r.responses[0]; - id = '#comment-' + r.id; - - if ( 'edit-comment' == t.act ) - $(id).remove(); - - if ( r.supplemental.parent_approved ) { - pid = $('#comment-' + r.supplemental.parent_approved); - updatePending( -1, r.supplemental.parent_post_id ); - - if ( this.comments_listing == 'moderated' ) { - pid.animate( { 'backgroundColor':'#CCEEBB' }, 400, function(){ - pid.fadeOut(); - }); - return; - } - } - - if ( r.supplemental.i18n_comments_text ) { - updateDashboardText( r.supplemental ); - updateInModerationText( r.supplemental ); - updateApproved( 1, r.supplemental.parent_post_id ); - updateCountText( 'span.all-count', 1 ); - } - - c = $.trim(r.data); // Trim leading whitespaces - $(c).hide(); - $('#replyrow').after(c); - - id = $(id); - t.addEvents(id); - bg = id.hasClass('unapproved') ? '#FFFFE0' : id.closest('.widefat, .postbox').css('backgroundColor'); - - id.animate( { 'backgroundColor':'#CCEEBB' }, 300 ) - .animate( { 'backgroundColor': bg }, 300, function() { - if ( pid && pid.length ) { - pid.animate( { 'backgroundColor':'#CCEEBB' }, 300 ) - .animate( { 'backgroundColor': bg }, 300 ) - .removeClass('unapproved').addClass('approved') - .find('div.comment_status').html('1'); - } - }); - - }, - - /** - * Shows an error for the failed comment update or reply. - * - * @since 2.7.0 - * - * @memberof commentReply - * - * @param {string} r The Ajax response. - * - * @return {void} - */ - error : function(r) { - var er = r.statusText, - $errorNotice = $( '#replysubmit .notice-error' ), - $error = $errorNotice.find( '.error' ); - - $( '#replysubmit .spinner' ).removeClass( 'is-active' ); - - if ( r.responseText ) - er = r.responseText.replace( /<.[^<>]*?>/g, '' ); - - if ( er ) { - $errorNotice.removeClass( 'hidden' ); - $error.html( er ); - } - }, - - /** - * Opens the add comments form in the comments metabox on the post edit page. - * - * @since 3.4.0 - * - * @memberof commentReply - * - * @param {number} post_id The post id. - * - * @return {void} - */ - addcomment: function(post_id) { - var t = this; - - $('#add-new-comment').fadeOut(200, function(){ - t.open(0, post_id, 'add'); - $('table.comments-box').css('display', ''); - $('#no-comments').remove(); - }); - }, - - /** - * Alert the user if they have unsaved changes on a comment that will be lost if - * they proceed with the intended action. - * - * @since 4.6.0 - * - * @memberof commentReply - * - * @return {boolean} Whether it is safe the continue with the intended action. - */ - discardCommentChanges: function() { - var editRow = $( '#replyrow' ); - - if ( this.originalContent === $( '#replycontent', editRow ).val() ) { - return true; - } - - return window.confirm( adminCommentsL10n.warnCommentChanges ); - } -}; - -$(document).ready(function(){ - var make_hotkeys_redirect, edit_comment, toggle_all, make_bulk; - - setCommentsList(); - commentReply.init(); - - $(document).on( 'click', 'span.delete a.delete', function( e ) { - e.preventDefault(); - }); - - if ( typeof $.table_hotkeys != 'undefined' ) { - /** - * Creates a function that navigates to a previous or next page. - * - * @since 2.7.0 - * @access private - * - * @param {string} which What page to navigate to: either next or prev. - * - * @return {Function} The function that executes the navigation. - */ - make_hotkeys_redirect = function(which) { - return function() { - var first_last, l; - - first_last = 'next' == which? 'first' : 'last'; - l = $('.tablenav-pages .'+which+'-page:not(.disabled)'); - if (l.length) - window.location = l[0].href.replace(/\&hotkeys_highlight_(first|last)=1/g, '')+'&hotkeys_highlight_'+first_last+'=1'; - }; - }; - - /** - * Navigates to the edit page for the selected comment. - * - * @since 2.7.0 - * @access private - * - * @param {Object} event The event that triggered this action. - * @param {Object} current_row A jQuery object of the selected row. - * - * @return {void} - */ - edit_comment = function(event, current_row) { - window.location = $('span.edit a', current_row).attr('href'); - }; - - /** - * Toggles all comments on the screen, for bulk actions. - * - * @since 2.7.0 - * @access private - * - * @return {void} - */ - toggle_all = function() { - $('#cb-select-all-1').data( 'wp-toggle', 1 ).trigger( 'click' ).removeData( 'wp-toggle' ); - }; - - /** - * Creates a bulk action function that is executed on all selected comments. - * - * @since 2.7.0 - * @access private - * - * @param {string} value The name of the action to execute. - * - * @return {Function} The function that executes the bulk action. - */ - make_bulk = function(value) { - return function() { - var scope = $('select[name="action"]'); - $('option[value="' + value + '"]', scope).prop('selected', true); - $('#doaction').click(); - }; - }; - - $.table_hotkeys( - $('table.widefat'), - [ - 'a', 'u', 's', 'd', 'r', 'q', 'z', - ['e', edit_comment], - ['shift+x', toggle_all], - ['shift+a', make_bulk('approve')], - ['shift+s', make_bulk('spam')], - ['shift+d', make_bulk('delete')], - ['shift+t', make_bulk('trash')], - ['shift+z', make_bulk('untrash')], - ['shift+u', make_bulk('unapprove')] - ], - { - highlight_first: adminCommentsL10n.hotkeys_highlight_first, - highlight_last: adminCommentsL10n.hotkeys_highlight_last, - prev_page_link_cb: make_hotkeys_redirect('prev'), - next_page_link_cb: make_hotkeys_redirect('next'), - hotkeys_opts: { - disableInInput: true, - type: 'keypress', - noDisable: '.check-column input[type="checkbox"]' - }, - cycle_expr: '#the-comment-list tr', - start_row_index: 0 - } - ); - } - - // Quick Edit and Reply have an inline comment editor. - $( '#the-comment-list' ).on( 'click', '.comment-inline', function() { - var $el = $( this ), - action = 'replyto'; - - if ( 'undefined' !== typeof $el.data( 'action' ) ) { - action = $el.data( 'action' ); - } - - $( this ).attr( 'aria-expanded', 'true' ); - commentReply.open( $el.data( 'commentId' ), $el.data( 'postId' ), action ); - } ); -}); - -})(jQuery); diff --git a/srcs/wordpress/wp-admin/js/edit-comments.min.js b/srcs/wordpress/wp-admin/js/edit-comments.min.js deleted file mode 100644 index e69c9a0..0000000 --- a/srcs/wordpress/wp-admin/js/edit-comments.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(L){var E,l,I,R,T,m,j,D,s,i,r=document.title,O=L("#dashboard_right_now").length;E=function(t){var e=parseInt(t.html().replace(/[^0-9]+/g,""),10);return isNaN(e)?0:e},l=function(t,e){var n="";if(!isNaN(e)){if(3<(e=e<1?"0":e.toString()).length){for(;3<e.length;)n=thousandsSeparator+e.substr(e.length-3)+n,e=e.substr(0,e.length-3);e+=n}t.html(e)}},T=function(n,t){var e,a,o=".post-com-count-"+t,s="comment-count-no-comments",i="comment-count-approved";I("span.approved-count",n),t&&(e=L("span."+i,o),a=L("span."+s,o),e.each(function(){var t=L(this),e=E(t)+n;e<1&&(e=0),0===e?t.removeClass(i).addClass(s):t.addClass(i).removeClass(s),l(t,e)}),a.each(function(){var t=L(this);0<n?t.removeClass(s).addClass(i):t.addClass(s).removeClass(i),l(t,n)}))},I=function(t,n){L(t).each(function(){var t=L(this),e=E(t)+n;e<1&&(e=0),l(t,e)})},j=function(t){O&&t&&t.i18n_comments_text&&L(".comment-count a","#dashboard_right_now").text(t.i18n_comments_text)},D=function(t){t&&t.i18n_moderation_text&&(L(".comments-in-moderation-text").text(t.i18n_moderation_text),O&&t.in_moderation&&L(".comment-mod-count","#dashboard_right_now")[0<t.in_moderation?"removeClass":"addClass"]("hidden"))},m=function(t){var e,n,a,o;i=i||new RegExp(adminCommentsL10n.docTitleCommentsCount.replace("%s","\\([0-9"+thousandsSeparator+"]+\\)")+"?"),s=s||L("<div />"),e=r,1<=(a=(o=i.exec(document.title))?(o=o[0],s.html(o),E(s)+t):(s.html(0),t))?(l(s,a),(n=i.exec(document.title))&&(e=document.title.replace(n[0],adminCommentsL10n.docTitleCommentsCount.replace("%s",s.text())+" "))):(n=i.exec(e))&&(e=e.replace(n[0],adminCommentsL10n.docTitleComments)),document.title=e},R=function(n,t){var e,a,o=".post-com-count-"+t,s="comment-count-no-pending",i="post-com-count-no-pending",r="comment-count-pending";O||m(n),L("span.pending-count").each(function(){var t=L(this),e=E(t)+n;e<1&&(e=0),t.closest(".awaiting-mod")[0===e?"addClass":"removeClass"]("count-0"),l(t,e)}),t&&(e=L("span."+r,o),a=L("span."+s,o),e.each(function(){var t=L(this),e=E(t)+n;e<1&&(e=0),0===e?(t.parent().addClass(i),t.removeClass(r).addClass(s)):(t.parent().removeClass(i),t.addClass(r).removeClass(s)),l(t,e)}),a.each(function(){var t=L(this);0<n?(t.parent().removeClass(i),t.removeClass(s).addClass(r)):(t.parent().addClass(i),t.addClass(s).removeClass(r)),l(t,n)}))},window.setCommentsList=function(){var w,p,c,t,e,x,n,b,r,k=0;w=L('input[name="_total"]',"#comments-form"),p=L('input[name="_per_page"]',"#comments-form"),c=L('input[name="_page"]',"#comments-form"),x=function(t,e,n){e<k||(n&&(k=e),w.val(t.toString()))},t=function(t,e){var n,a,o,s,i=L("#"+e.element);!0!==e.parsed&&(s=e.parsed.responses[0]),n=L("#replyrow"),a=L("#comment_ID",n).val(),o=L("#replybtn",n),i.is(".unapproved")?(e.data.id==a&&o.text(adminCommentsL10n.replyApprove),i.find(".row-actions span.view").addClass("hidden").end().find("div.comment_status").html("0")):(e.data.id==a&&o.text(adminCommentsL10n.reply),i.find(".row-actions span.view").removeClass("hidden").end().find("div.comment_status").html("1")),r=L("#"+e.element).is("."+e.dimClass)?1:-1,s?(j(s.supplemental),D(s.supplemental),R(r,s.supplemental.postId),T(-1*r,s.supplemental.postId)):(R(r),T(-1*r))},e=function(t,e){var n,a,o,s,i,r,l,m=!1,d=L(t.target).attr("data-wp-lists");return t.data._total=w.val()||0,t.data._per_page=p.val()||0,t.data._page=c.val()||0,t.data._url=document.location.href,t.data.comment_status=L('input[name="comment_status"]',"#comments-form").val(),-1!=d.indexOf(":trash=1")?m="trash":-1!=d.indexOf(":spam=1")&&(m="spam"),m&&(a=d.replace(/.*?comment-([0-9]+).*/,"$1"),o=L("#comment-"+a),n=L("#"+m+"-undo-holder").html(),o.find(".check-column :checkbox").prop("checked",!1),o.siblings("#replyrow").length&&commentReply.cid==a&&commentReply.close(),i=o.is("tr")?(s=o.children(":visible").length,l=L(".author strong",o).text(),L('<tr id="undo-'+a+'" class="undo un'+m+'" style="display:none;"><td colspan="'+s+'">'+n+"</td></tr>")):(l=L(".comment-author",o).text(),L('<div id="undo-'+a+'" style="display:none;" class="undo un'+m+'">'+n+"</div>")),o.before(i),L("strong","#undo-"+a).text(l),(r=L(".undo a","#undo-"+a)).attr("href","comment.php?action=un"+m+"comment&c="+a+"&_wpnonce="+t.data._ajax_nonce),r.attr("data-wp-lists","delete:the-comment-list:comment-"+a+"::un"+m+"=1"),r.attr("class","vim-z vim-destructive aria-button-if-js"),L(".avatar",o).first().clone().prependTo("#undo-"+a+" ."+m+"-undo-inside"),r.click(function(t){t.preventDefault(),t.stopPropagation(),e.wpList.del(this),L("#undo-"+a).css({backgroundColor:"#ceb"}).fadeOut(350,function(){L(this).remove(),L("#comment-"+a).css("backgroundColor","").fadeIn(300,function(){L(this).show()})})})),t},n=function(t,e){var n,a,o,s,i,r,l,m,d=!0===e.parsed?{}:e.parsed.responses[0],p=!0===e.parsed?"":d.supplemental.status,c=!0===e.parsed?"":d.supplemental.postId,u=!0===e.parsed?"":d.supplemental,h=L(e.target).parent(),f=L("#"+e.element),v=f.hasClass("approved")&&!f.hasClass("unapproved"),g=f.hasClass("unapproved"),C=f.hasClass("spam"),_=f.hasClass("trash"),y=!1;j(u),D(u),h.is("span.undo")?(h.hasClass("unspam")?(i=-1,"trash"===p?r=1:"1"===p?m=1:"0"===p&&(l=1)):h.hasClass("untrash")&&(r=-1,"spam"===p?i=1:"1"===p?m=1:"0"===p&&(l=1)),y=!0):h.is("span.spam")?(v?m=-1:g?l=-1:_&&(r=-1),i=1):h.is("span.unspam")?(v?l=1:g?m=1:_?h.hasClass("approve")?m=1:h.hasClass("unapprove")&&(l=1):C&&(h.hasClass("approve")?m=1:h.hasClass("unapprove")&&(l=1)),i=-1):h.is("span.trash")?(v?m=-1:g?l=-1:C&&(i=-1),r=1):h.is("span.untrash")?(v?l=1:g?m=1:_&&(h.hasClass("approve")?m=1:h.hasClass("unapprove")&&(l=1)),r=-1):h.is("span.approve:not(.unspam):not(.untrash)")?l=-(m=1):h.is("span.unapprove:not(.unspam):not(.untrash)")?(m=-1,l=1):h.is("span.delete")&&(C?i=-1:_&&(r=-1)),l&&(R(l,c),I("span.all-count",l)),m&&(T(m,c),I("span.all-count",m)),i&&I("span.spam-count",i),r&&I("span.trash-count",r),("trash"===e.data.comment_status&&!E(L("span.trash-count"))||"spam"===e.data.comment_status&&!E(L("span.spam-count")))&&L("#delete_all").hide(),O||(a=w.val()?parseInt(w.val(),10):0,L(e.target).parent().is("span.undo")?a++:a--,a<0&&(a=0),"object"==typeof t?d.supplemental.total_items_i18n&&k<d.supplemental.time?((n=d.supplemental.total_items_i18n||"")&&(L(".displaying-num").text(n.replace(" ",String.fromCharCode(160))),L(".total-pages").text(d.supplemental.total_pages_i18n.replace(" ",String.fromCharCode(160))),L(".tablenav-pages").find(".next-page, .last-page").toggleClass("disabled",d.supplemental.total_pages==L(".current-page").val())),x(a,d.supplemental.time,!0)):d.supplemental.time&&x(a,d.supplemental.time,!1):x(a,t,!1)),theExtraList&&0!==theExtraList.length&&0!==theExtraList.children().length&&!y&&(theList.get(0).wpList.add(theExtraList.children(":eq(0):not(.no-items)").remove().clone()),b(),s=function(){L("#the-comment-list tr:visible").length||theList.get(0).wpList.add(theExtraList.find(".no-items").clone())},(o=L(":animated","#the-comment-list")).length?o.promise().done(s):s())},b=function(t){var e=L.query.get(),n=L(".total-pages").text(),a=L('input[name="_per_page"]',"#comments-form").val();e.paged||(e.paged=1),e.paged>n||(t?(theExtraList.empty(),e.number=Math.min(8,a)):(e.number=1,e.offset=Math.min(8,a)-1),e.no_placeholder=!0,e.paged++,!0===e.comment_type&&(e.comment_type=""),e=L.extend(e,{action:"fetch-list",list_args:list_args,_ajax_fetch_list_nonce:L("#_ajax_fetch_list_nonce").val()}),L.ajax({url:ajaxurl,global:!1,dataType:"json",data:e,success:function(t){theExtraList.get(0).wpList.add(t.rows)}}))},window.theExtraList=L("#the-extra-comment-list").wpList({alt:"",delColor:"none",addColor:"none"}),window.theList=L("#the-comment-list").wpList({alt:"",delBefore:e,dimAfter:t,delAfter:n,addColor:"none"}).bind("wpListDelEnd",function(t,e){var n=L(e.target).attr("data-wp-lists"),a=e.element.replace(/[^0-9]+/g,"");-1==n.indexOf(":trash=1")&&-1==n.indexOf(":spam=1")||L("#undo-"+a).fadeIn(300,function(){L(this).show()})})},window.commentReply={cid:"",act:"",originalContent:"",init:function(){var t=L("#replyrow");L(".cancel",t).click(function(){return commentReply.revert()}),L(".save",t).click(function(){return commentReply.send()}),L("input#author-name, input#author-email, input#author-url",t).keypress(function(t){if(13==t.which)return commentReply.send(),t.preventDefault(),!1}),L("#the-comment-list .column-comment > p").dblclick(function(){commentReply.toggle(L(this).parent())}),L("#doaction, #doaction2, #post-query-submit").click(function(){0<L("#the-comment-list #replyrow").length&&commentReply.close()}),this.comments_listing=L('#comments-form > input[name="comment_status"]').val()||""},addEvents:function(t){t.each(function(){L(this).find(".column-comment > p").dblclick(function(){commentReply.toggle(L(this).parent())})})},toggle:function(t){"none"!==L(t).css("display")&&(L("#replyrow").parent().is("#com-reply")||window.confirm(adminCommentsL10n.warnQuickEdit))&&L(t).find("button.vim-q").click()},revert:function(){if(L("#the-comment-list #replyrow").length<1)return!1;L("#replyrow").fadeOut("fast",function(){commentReply.close()})},close:function(){var t=L(),e=L("#replyrow");e.parent().is("#com-reply")||(this.cid&&(t=L("#comment-"+this.cid)),"edit-comment"===this.act&&t.fadeIn(300,function(){t.show().find(".vim-q").attr("aria-expanded","false").focus()}).css("backgroundColor",""),"replyto-comment"===this.act&&t.find(".vim-r").attr("aria-expanded","false").focus(),"undefined"!=typeof QTags&&QTags.closeAllTags("replycontent"),L("#add-new-comment").css("display",""),e.hide(),L("#com-reply").append(e),L("#replycontent").css("height","").val(""),L("#edithead input").val(""),L(".notice-error",e).addClass("hidden").find(".error").empty(),L(".spinner",e).removeClass("is-active"),this.cid="",this.originalContent="")},open:function(t,e,n){var a,o,s,i,r,l,m=L("#comment-"+t),d=m.height();return this.discardCommentChanges()&&(this.close(),this.cid=t,a=L("#replyrow"),o=L("#inline-"+t),s="edit"==(n=n||"replyto")?"edit":"replyto",s=this.act=s+"-comment",this.originalContent=L("textarea.comment",o).val(),l=L("> th:visible, > td:visible",m).length,a.hasClass("inline-edit-row")&&0!==l&&L("td",a).attr("colspan",l),L("#action",a).val(s),L("#comment_post_ID",a).val(e),L("#comment_ID",a).val(t),"edit"==n?(L("#author-name",a).val(L("div.author",o).text()),L("#author-email",a).val(L("div.author-email",o).text()),L("#author-url",a).val(L("div.author-url",o).text()),L("#status",a).val(L("div.comment_status",o).text()),L("#replycontent",a).val(L("textarea.comment",o).val()),L("#edithead, #editlegend, #savebtn",a).show(),L("#replyhead, #replybtn, #addhead, #addbtn",a).hide(),120<d&&(r=500<d?500:d,L("#replycontent",a).css("height",r+"px")),m.after(a).fadeOut("fast",function(){L("#replyrow").fadeIn(300,function(){L(this).show()})})):"add"==n?(L("#addhead, #addbtn",a).show(),L("#replyhead, #replybtn, #edithead, #editlegend, #savebtn",a).hide(),L("#the-comment-list").prepend(a),L("#replyrow").fadeIn(300)):(i=L("#replybtn",a),L("#edithead, #editlegend, #savebtn, #addhead, #addbtn",a).hide(),L("#replyhead, #replybtn",a).show(),m.after(a),m.hasClass("unapproved")?i.text(adminCommentsL10n.replyApprove):i.text(adminCommentsL10n.reply),L("#replyrow").fadeIn(300,function(){L(this).show()})),setTimeout(function(){var t,e,n,a;e=(t=L("#replyrow").offset().top)+L("#replyrow").height(),(n=window.pageYOffset||document.documentElement.scrollTop)+(a=document.documentElement.clientHeight||window.innerHeight||0)-20<e?window.scroll(0,e-a+35):t-20<n&&window.scroll(0,t-35),L("#replycontent").focus().keyup(function(t){27==t.which&&commentReply.revert()})},600)),!1},send:function(){var e={};L("#replysubmit .error-notice").addClass("hidden"),L("#replysubmit .spinner").addClass("is-active"),L("#replyrow input").not(":button").each(function(){var t=L(this);e[t.attr("name")]=t.val()}),e.content=L("#replycontent").val(),e.id=e.comment_post_ID,e.comments_listing=this.comments_listing,e.p=L('[name="p"]').val(),L("#comment-"+L("#comment_ID").val()).hasClass("unapproved")&&(e.approve_parent=1),L.ajax({type:"POST",url:ajaxurl,data:e,success:function(t){commentReply.show(t)},error:function(t){commentReply.error(t)}})},show:function(t){var e,n,a,o,s,i=this;return"string"==typeof t?(i.error({responseText:t}),!1):(e=wpAjax.parseAjaxResponse(t)).errors?(i.error({responseText:wpAjax.broken}),!1):(i.revert(),a="#comment-"+(e=e.responses[0]).id,"edit-comment"==i.act&&L(a).remove(),void(e.supplemental.parent_approved&&(s=L("#comment-"+e.supplemental.parent_approved),R(-1,e.supplemental.parent_post_id),"moderated"==this.comments_listing)?s.animate({backgroundColor:"#CCEEBB"},400,function(){s.fadeOut()}):(e.supplemental.i18n_comments_text&&(j(e.supplemental),D(e.supplemental),T(1,e.supplemental.parent_post_id),I("span.all-count",1)),n=L.trim(e.data),L(n).hide(),L("#replyrow").after(n),a=L(a),i.addEvents(a),o=a.hasClass("unapproved")?"#FFFFE0":a.closest(".widefat, .postbox").css("backgroundColor"),a.animate({backgroundColor:"#CCEEBB"},300).animate({backgroundColor:o},300,function(){s&&s.length&&s.animate({backgroundColor:"#CCEEBB"},300).animate({backgroundColor:o},300).removeClass("unapproved").addClass("approved").find("div.comment_status").html("1")}))))},error:function(t){var e=t.statusText,n=L("#replysubmit .notice-error"),a=n.find(".error");L("#replysubmit .spinner").removeClass("is-active"),t.responseText&&(e=t.responseText.replace(/<.[^<>]*?>/g,"")),e&&(n.removeClass("hidden"),a.html(e))},addcomment:function(t){var e=this;L("#add-new-comment").fadeOut(200,function(){e.open(0,t,"add"),L("table.comments-box").css("display",""),L("#no-comments").remove()})},discardCommentChanges:function(){var t=L("#replyrow");return this.originalContent===L("#replycontent",t).val()||window.confirm(adminCommentsL10n.warnCommentChanges)}},L(document).ready(function(){var t,e,n,a;setCommentsList(),commentReply.init(),L(document).on("click","span.delete a.delete",function(t){t.preventDefault()}),void 0!==L.table_hotkeys&&(t=function(n){return function(){var t,e;t="next"==n?"first":"last",(e=L(".tablenav-pages ."+n+"-page:not(.disabled)")).length&&(window.location=e[0].href.replace(/\&hotkeys_highlight_(first|last)=1/g,"")+"&hotkeys_highlight_"+t+"=1")}},e=function(t,e){window.location=L("span.edit a",e).attr("href")},n=function(){L("#cb-select-all-1").data("wp-toggle",1).trigger("click").removeData("wp-toggle")},a=function(e){return function(){var t=L('select[name="action"]');L('option[value="'+e+'"]',t).prop("selected",!0),L("#doaction").click()}},L.table_hotkeys(L("table.widefat"),["a","u","s","d","r","q","z",["e",e],["shift+x",n],["shift+a",a("approve")],["shift+s",a("spam")],["shift+d",a("delete")],["shift+t",a("trash")],["shift+z",a("untrash")],["shift+u",a("unapprove")]],{highlight_first:adminCommentsL10n.hotkeys_highlight_first,highlight_last:adminCommentsL10n.hotkeys_highlight_last,prev_page_link_cb:t("prev"),next_page_link_cb:t("next"),hotkeys_opts:{disableInInput:!0,type:"keypress",noDisable:'.check-column input[type="checkbox"]'},cycle_expr:"#the-comment-list tr",start_row_index:0})),L("#the-comment-list").on("click",".comment-inline",function(){var t=L(this),e="replyto";void 0!==t.data("action")&&(e=t.data("action")),L(this).attr("aria-expanded","true"),commentReply.open(t.data("commentId"),t.data("postId"),e)})})}(jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/editor-expand.js b/srcs/wordpress/wp-admin/js/editor-expand.js deleted file mode 100644 index 030193a..0000000 --- a/srcs/wordpress/wp-admin/js/editor-expand.js +++ /dev/null @@ -1,1616 +0,0 @@ -/** - * @output wp-admin/js/editor-expand.js - */ - -( function( window, $, undefined ) { - 'use strict'; - - var $window = $( window ), - $document = $( document ), - $adminBar = $( '#wpadminbar' ), - $footer = $( '#wpfooter' ); - - /** - * Handles the resizing of the editor. - * - * @since 4.0.0 - * - * @returns {void} - */ - $( function() { - var $wrap = $( '#postdivrich' ), - $contentWrap = $( '#wp-content-wrap' ), - $tools = $( '#wp-content-editor-tools' ), - $visualTop = $(), - $visualEditor = $(), - $textTop = $( '#ed_toolbar' ), - $textEditor = $( '#content' ), - textEditor = $textEditor[0], - oldTextLength = 0, - $bottom = $( '#post-status-info' ), - $menuBar = $(), - $statusBar = $(), - $sideSortables = $( '#side-sortables' ), - $postboxContainer = $( '#postbox-container-1' ), - $postBody = $('#post-body'), - fullscreen = window.wp.editor && window.wp.editor.fullscreen, - mceEditor, - mceBind = function(){}, - mceUnbind = function(){}, - fixedTop = false, - fixedBottom = false, - fixedSideTop = false, - fixedSideBottom = false, - scrollTimer, - lastScrollPosition = 0, - pageYOffsetAtTop = 130, - pinnedToolsTop = 56, - sidebarBottom = 20, - autoresizeMinHeight = 300, - initialMode = $contentWrap.hasClass( 'tmce-active' ) ? 'tinymce' : 'html', - advanced = !! parseInt( window.getUserSetting( 'hidetb' ), 10 ), - // These are corrected when adjust() runs, except on scrolling if already set. - heights = { - windowHeight: 0, - windowWidth: 0, - adminBarHeight: 0, - toolsHeight: 0, - menuBarHeight: 0, - visualTopHeight: 0, - textTopHeight: 0, - bottomHeight: 0, - statusBarHeight: 0, - sideSortablesHeight: 0 - }; - - /** - * Resizes textarea based on scroll height and width. - * - * Doesn't shrink the editor size below the 300px auto resize minimum height. - * - * @since 4.6.1 - * - * @returns {void} - */ - var shrinkTextarea = window._.throttle( function() { - var x = window.scrollX || document.documentElement.scrollLeft; - var y = window.scrollY || document.documentElement.scrollTop; - var height = parseInt( textEditor.style.height, 10 ); - - textEditor.style.height = autoresizeMinHeight + 'px'; - - if ( textEditor.scrollHeight > autoresizeMinHeight ) { - textEditor.style.height = textEditor.scrollHeight + 'px'; - } - - if ( typeof x !== 'undefined' ) { - window.scrollTo( x, y ); - } - - if ( textEditor.scrollHeight < height ) { - adjust(); - } - }, 300 ); - - /** - * Resizes the text editor depending on the old text length. - * - * If there is an mceEditor and it is hidden, it resizes the editor depending - * on the old text length. If the current length of the text is smaller than - * the old text length, it shrinks the text area. Otherwise it resizes the editor to - * the scroll height. - * - * @since 4.6.1 - * - * @returns {void} - */ - function textEditorResize() { - var length = textEditor.value.length; - - if ( mceEditor && ! mceEditor.isHidden() ) { - return; - } - - if ( ! mceEditor && initialMode === 'tinymce' ) { - return; - } - - if ( length < oldTextLength ) { - shrinkTextarea(); - } else if ( parseInt( textEditor.style.height, 10 ) < textEditor.scrollHeight ) { - textEditor.style.height = Math.ceil( textEditor.scrollHeight ) + 'px'; - adjust(); - } - - oldTextLength = length; - } - - /** - * Gets the height and widths of elements. - * - * Gets the heights of the window, the adminbar, the tools, the menu, - * the visualTop, the textTop, the bottom, the statusbar and sideSortables - * and stores these in the heights object. Defaults to 0. - * Gets the width of the window and stores this in the heights object. - * - * @since 4.0.0 - * - * @returns {void} - */ - function getHeights() { - var windowWidth = $window.width(); - - heights = { - windowHeight: $window.height(), - windowWidth: windowWidth, - adminBarHeight: ( windowWidth > 600 ? $adminBar.outerHeight() : 0 ), - toolsHeight: $tools.outerHeight() || 0, - menuBarHeight: $menuBar.outerHeight() || 0, - visualTopHeight: $visualTop.outerHeight() || 0, - textTopHeight: $textTop.outerHeight() || 0, - bottomHeight: $bottom.outerHeight() || 0, - statusBarHeight: $statusBar.outerHeight() || 0, - sideSortablesHeight: $sideSortables.height() || 0 - }; - - // Adjust for hidden menubar. - if ( heights.menuBarHeight < 3 ) { - heights.menuBarHeight = 0; - } - } - - // We need to wait for TinyMCE to initialize. - /** - * Binds all necessary functions for editor expand to the editor when the editor - * is initialized. - * - * @since 4.0.0 - * - * @param {event} event The TinyMCE editor init event. - * @param {object} editor The editor to bind the vents on. - * - * @returns {void} - */ - $document.on( 'tinymce-editor-init.editor-expand', function( event, editor ) { - // VK contains the type of key pressed. VK = virtual keyboard. - var VK = window.tinymce.util.VK, - /** - * Hides any float panel with a hover state. Additionally hides tooltips. - * - * @returns {void} - */ - hideFloatPanels = _.debounce( function() { - ! $( '.mce-floatpanel:hover' ).length && window.tinymce.ui.FloatPanel.hideAll(); - $( '.mce-tooltip' ).hide(); - }, 1000, true ); - - // Make sure it's the main editor. - if ( editor.id !== 'content' ) { - return; - } - - // Copy the editor instance. - mceEditor = editor; - - // Set the minimum height to the initial viewport height. - editor.settings.autoresize_min_height = autoresizeMinHeight; - - // Get the necessary UI elements. - $visualTop = $contentWrap.find( '.mce-toolbar-grp' ); - $visualEditor = $contentWrap.find( '.mce-edit-area' ); - $statusBar = $contentWrap.find( '.mce-statusbar' ); - $menuBar = $contentWrap.find( '.mce-menubar' ); - - /** - * Gets the offset of the editor. - * - * @returns {Number|Boolean} Returns the offset of the editor - * or false if there is no offset height. - */ - function mceGetCursorOffset() { - var node = editor.selection.getNode(), - range, view, offset; - - /* - * If editor.wp.getView and the selection node from the editor selection - * are defined, use this as a view for the offset. - */ - if ( editor.wp && editor.wp.getView && ( view = editor.wp.getView( node ) ) ) { - offset = view.getBoundingClientRect(); - } else { - range = editor.selection.getRng(); - - // Try to get the offset from a range. - try { - offset = range.getClientRects()[0]; - } catch( er ) {} - - // Get the offset from the bounding client rectangle of the node. - if ( ! offset ) { - offset = node.getBoundingClientRect(); - } - } - - return offset.height ? offset : false; - } - - /** - * Filters the special keys that should not be used for scrolling. - * - * @since 4.0.0 - * - * @param {event} event The event to get the key code from. - * - * @returns {void} - */ - function mceKeyup( event ) { - var key = event.keyCode; - - // Bail on special keys. Key code 47 is a / - if ( key <= 47 && ! ( key === VK.SPACEBAR || key === VK.ENTER || key === VK.DELETE || key === VK.BACKSPACE || key === VK.UP || key === VK.LEFT || key === VK.DOWN || key === VK.UP ) ) { - return; - // OS keys, function keys, num lock, scroll lock. Key code 91-93 are OS keys. Key code 112-123 are F1 to F12. Key code 144 is num lock. Key code 145 is scroll lock. - } else if ( ( key >= 91 && key <= 93 ) || ( key >= 112 && key <= 123 ) || key === 144 || key === 145 ) { - return; - } - - mceScroll( key ); - } - - /** - * Makes sure the cursor is always visible in the editor. - * - * Makes sure the cursor is kept between the toolbars of the editor and scrolls - * the window when the cursor moves out of the viewport to a wpview. - * Setting a buffer > 0 will prevent the browser default. - * Some browsers will scroll to the middle, - * others to the top/bottom of the *window* when moving the cursor out of the viewport. - * - * @since 4.1.0 - * - * @param {string} key The key code of the pressed key. - * - * @returns {void} - */ - function mceScroll( key ) { - var offset = mceGetCursorOffset(), - buffer = 50, - cursorTop, cursorBottom, editorTop, editorBottom; - - // Don't scroll if there is no offset. - if ( ! offset ) { - return; - } - - // Determine the cursorTop based on the offset and the top of the editor iframe. - cursorTop = offset.top + editor.iframeElement.getBoundingClientRect().top; - - // Determine the cursorBottom based on the cursorTop and offset height. - cursorBottom = cursorTop + offset.height; - - // Subtract the buffer from the cursorTop. - cursorTop = cursorTop - buffer; - - // Add the buffer to the cursorBottom. - cursorBottom = cursorBottom + buffer; - editorTop = heights.adminBarHeight + heights.toolsHeight + heights.menuBarHeight + heights.visualTopHeight; - - /* - * Set the editorBottom based on the window Height, and add the bottomHeight and statusBarHeight if the - * advanced editor is enabled. - */ - editorBottom = heights.windowHeight - ( advanced ? heights.bottomHeight + heights.statusBarHeight : 0 ); - - // Don't scroll if the node is taller than the visible part of the editor. - if ( editorBottom - editorTop < offset.height ) { - return; - } - - /* - * If the cursorTop is smaller than the editorTop and the up, left - * or backspace key is pressed, scroll the editor to the position defined - * by the cursorTop, pageYOffset and editorTop. - */ - if ( cursorTop < editorTop && ( key === VK.UP || key === VK.LEFT || key === VK.BACKSPACE ) ) { - window.scrollTo( window.pageXOffset, cursorTop + window.pageYOffset - editorTop ); - - /* - * If any other key is pressed or the cursorTop is bigger than the editorTop, - * scroll the editor to the position defined by the cursorBottom, - * pageYOffset and editorBottom. - */ - } else if ( cursorBottom > editorBottom ) { - window.scrollTo( window.pageXOffset, cursorBottom + window.pageYOffset - editorBottom ); - } - } - - /** - * If the editor is fullscreen, calls adjust. - * - * @since 4.1.0 - * - * @param {event} event The FullscreenStateChanged event. - * - * @returns {void} - */ - function mceFullscreenToggled( event ) { - // event.state is true if the editor is fullscreen. - if ( ! event.state ) { - adjust(); - } - } - - /** - * Shows the editor when scrolled. - * - * Binds the hideFloatPanels function on the window scroll.mce-float-panels event. - * Executes the wpAutoResize on the active editor. - * - * @since 4.0.0 - * - * @returns {void} - */ - function mceShow() { - $window.on( 'scroll.mce-float-panels', hideFloatPanels ); - - setTimeout( function() { - editor.execCommand( 'wpAutoResize' ); - adjust(); - }, 300 ); - } - - /** - * Resizes the editor. - * - * Removes all functions from the window scroll.mce-float-panels event. - * Resizes the text editor and scrolls to a position based on the pageXOffset and adminBarHeight. - * - * @since 4.0.0 - * - * @returns {void} - */ - function mceHide() { - $window.off( 'scroll.mce-float-panels' ); - - setTimeout( function() { - var top = $contentWrap.offset().top; - - if ( window.pageYOffset > top ) { - window.scrollTo( window.pageXOffset, top - heights.adminBarHeight ); - } - - textEditorResize(); - adjust(); - }, 100 ); - - adjust(); - } - - /** - * Toggles advanced states. - * - * @since 4.1.0 - * - * @returns {void} - */ - function toggleAdvanced() { - advanced = ! advanced; - } - - /** - * Binds events of the editor and window. - * - * @since 4.0.0 - * - * @returns {void} - */ - mceBind = function() { - editor.on( 'keyup', mceKeyup ); - editor.on( 'show', mceShow ); - editor.on( 'hide', mceHide ); - editor.on( 'wp-toolbar-toggle', toggleAdvanced ); - - // Adjust when the editor resizes. - editor.on( 'setcontent wp-autoresize wp-toolbar-toggle', adjust ); - - // Don't hide the caret after undo/redo. - editor.on( 'undo redo', mceScroll ); - - // Adjust when exiting TinyMCE's fullscreen mode. - editor.on( 'FullscreenStateChanged', mceFullscreenToggled ); - - $window.off( 'scroll.mce-float-panels' ).on( 'scroll.mce-float-panels', hideFloatPanels ); - }; - - /** - * Unbinds the events of the editor and window. - * - * @since 4.0.0 - * - * @returns {void} - */ - mceUnbind = function() { - editor.off( 'keyup', mceKeyup ); - editor.off( 'show', mceShow ); - editor.off( 'hide', mceHide ); - editor.off( 'wp-toolbar-toggle', toggleAdvanced ); - editor.off( 'setcontent wp-autoresize wp-toolbar-toggle', adjust ); - editor.off( 'undo redo', mceScroll ); - editor.off( 'FullscreenStateChanged', mceFullscreenToggled ); - - $window.off( 'scroll.mce-float-panels' ); - }; - - if ( $wrap.hasClass( 'wp-editor-expand' ) ) { - - // Adjust "immediately". - mceBind(); - initialResize( adjust ); - } - } ); - - /** - * Adjusts the toolbars heights and positions. - * - * Adjusts the toolbars heights and positions based on the scroll position on - * the page, the active editor mode and the heights of the editor, admin bar and - * side bar. - * - * @since 4.0.0 - * - * @param {event} event The event that calls this function. - * - * @returns {void} - */ - function adjust( event ) { - - // Makes sure we're not in fullscreen mode. - if ( fullscreen && fullscreen.settings.visible ) { - return; - } - - var windowPos = $window.scrollTop(), - type = event && event.type, - resize = type !== 'scroll', - visual = mceEditor && ! mceEditor.isHidden(), - buffer = autoresizeMinHeight, - postBodyTop = $postBody.offset().top, - borderWidth = 1, - contentWrapWidth = $contentWrap.width(), - $top, $editor, sidebarTop, footerTop, canPin, - topPos, topHeight, editorPos, editorHeight; - - /* - * Refresh the heights if type isn't 'scroll' - * or heights.windowHeight isn't set. - */ - if ( resize || ! heights.windowHeight ) { - getHeights(); - } - - // Resize on resize event when the editor is in text mode. - if ( ! visual && type === 'resize' ) { - textEditorResize(); - } - - if ( visual ) { - $top = $visualTop; - $editor = $visualEditor; - topHeight = heights.visualTopHeight; - } else { - $top = $textTop; - $editor = $textEditor; - topHeight = heights.textTopHeight; - } - - // Return if TinyMCE is still initializing. - if ( ! visual && ! $top.length ) { - return; - } - - topPos = $top.parent().offset().top; - editorPos = $editor.offset().top; - editorHeight = $editor.outerHeight(); - - /* - * If in visual mode, checks if the editorHeight is greater than the autoresizeMinHeight + topHeight. - * If not in visual mode, checks if the editorHeight is greater than the autoresizeMinHeight + 20. - */ - canPin = visual ? autoresizeMinHeight + topHeight : autoresizeMinHeight + 20; // 20px from textarea padding - canPin = editorHeight > ( canPin + 5 ); - - if ( ! canPin ) { - if ( resize ) { - $tools.css( { - position: 'absolute', - top: 0, - width: contentWrapWidth - } ); - - if ( visual && $menuBar.length ) { - $menuBar.css( { - position: 'absolute', - top: 0, - width: contentWrapWidth - ( borderWidth * 2 ) - } ); - } - - $top.css( { - position: 'absolute', - top: heights.menuBarHeight, - width: contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top.outerWidth() - $top.width() ) ) - } ); - - $statusBar.attr( 'style', advanced ? '' : 'visibility: hidden;' ); - $bottom.attr( 'style', '' ); - } - } else { - // Check if the top is not already in a fixed position. - if ( ( ! fixedTop || resize ) && - ( windowPos >= ( topPos - heights.toolsHeight - heights.adminBarHeight ) && - windowPos <= ( topPos - heights.toolsHeight - heights.adminBarHeight + editorHeight - buffer ) ) ) { - fixedTop = true; - - $tools.css( { - position: 'fixed', - top: heights.adminBarHeight, - width: contentWrapWidth - } ); - - if ( visual && $menuBar.length ) { - $menuBar.css( { - position: 'fixed', - top: heights.adminBarHeight + heights.toolsHeight, - width: contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top.outerWidth() - $top.width() ) ) - } ); - } - - $top.css( { - position: 'fixed', - top: heights.adminBarHeight + heights.toolsHeight + heights.menuBarHeight, - width: contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top.outerWidth() - $top.width() ) ) - } ); - // Check if the top is already in a fixed position. - } else if ( fixedTop || resize ) { - if ( windowPos <= ( topPos - heights.toolsHeight - heights.adminBarHeight ) ) { - fixedTop = false; - - $tools.css( { - position: 'absolute', - top: 0, - width: contentWrapWidth - } ); - - if ( visual && $menuBar.length ) { - $menuBar.css( { - position: 'absolute', - top: 0, - width: contentWrapWidth - ( borderWidth * 2 ) - } ); - } - - $top.css( { - position: 'absolute', - top: heights.menuBarHeight, - width: contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top.outerWidth() - $top.width() ) ) - } ); - } else if ( windowPos >= ( topPos - heights.toolsHeight - heights.adminBarHeight + editorHeight - buffer ) ) { - fixedTop = false; - - $tools.css( { - position: 'absolute', - top: editorHeight - buffer, - width: contentWrapWidth - } ); - - if ( visual && $menuBar.length ) { - $menuBar.css( { - position: 'absolute', - top: editorHeight - buffer, - width: contentWrapWidth - ( borderWidth * 2 ) - } ); - } - - $top.css( { - position: 'absolute', - top: editorHeight - buffer + heights.menuBarHeight, - width: contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top.outerWidth() - $top.width() ) ) - } ); - } - } - - // Check if the bottom is not already in a fixed position. - if ( ( ! fixedBottom || ( resize && advanced ) ) && - // Add borderWidth for the border around the .wp-editor-container. - ( windowPos + heights.windowHeight ) <= ( editorPos + editorHeight + heights.bottomHeight + heights.statusBarHeight + borderWidth ) ) { - - if ( event && event.deltaHeight > 0 && event.deltaHeight < 100 ) { - window.scrollBy( 0, event.deltaHeight ); - } else if ( visual && advanced ) { - fixedBottom = true; - - $statusBar.css( { - position: 'fixed', - bottom: heights.bottomHeight, - visibility: '', - width: contentWrapWidth - ( borderWidth * 2 ) - } ); - - $bottom.css( { - position: 'fixed', - bottom: 0, - width: contentWrapWidth - } ); - } - } else if ( ( ! advanced && fixedBottom ) || - ( ( fixedBottom || resize ) && - ( windowPos + heights.windowHeight ) > ( editorPos + editorHeight + heights.bottomHeight + heights.statusBarHeight - borderWidth ) ) ) { - fixedBottom = false; - - $statusBar.attr( 'style', advanced ? '' : 'visibility: hidden;' ); - $bottom.attr( 'style', '' ); - } - } - - // The postbox container is positioned with @media from CSS. Ensure it is pinned on the side. - if ( $postboxContainer.width() < 300 && heights.windowWidth > 600 && - - // Check if the sidebar is not taller than the document height. - $document.height() > ( $sideSortables.height() + postBodyTop + 120 ) && - - // Check if the editor is taller than the viewport. - heights.windowHeight < editorHeight ) { - - if ( ( heights.sideSortablesHeight + pinnedToolsTop + sidebarBottom ) > heights.windowHeight || fixedSideTop || fixedSideBottom ) { - - // Reset the sideSortables style when scrolling to the top. - if ( windowPos + pinnedToolsTop <= postBodyTop ) { - $sideSortables.attr( 'style', '' ); - fixedSideTop = fixedSideBottom = false; - } else { - - // When scrolling down. - if ( windowPos > lastScrollPosition ) { - if ( fixedSideTop ) { - - // Let it scroll. - fixedSideTop = false; - sidebarTop = $sideSortables.offset().top - heights.adminBarHeight; - footerTop = $footer.offset().top; - - // Don't get over the footer. - if ( footerTop < sidebarTop + heights.sideSortablesHeight + sidebarBottom ) { - sidebarTop = footerTop - heights.sideSortablesHeight - 12; - } - - $sideSortables.css({ - position: 'absolute', - top: sidebarTop, - bottom: '' - }); - } else if ( ! fixedSideBottom && heights.sideSortablesHeight + $sideSortables.offset().top + sidebarBottom < windowPos + heights.windowHeight ) { - // Pin the bottom. - fixedSideBottom = true; - - $sideSortables.css({ - position: 'fixed', - top: 'auto', - bottom: sidebarBottom - }); - } - - // When scrolling up. - } else if ( windowPos < lastScrollPosition ) { - if ( fixedSideBottom ) { - // Let it scroll. - fixedSideBottom = false; - sidebarTop = $sideSortables.offset().top - sidebarBottom; - footerTop = $footer.offset().top; - - // Don't get over the footer. - if ( footerTop < sidebarTop + heights.sideSortablesHeight + sidebarBottom ) { - sidebarTop = footerTop - heights.sideSortablesHeight - 12; - } - - $sideSortables.css({ - position: 'absolute', - top: sidebarTop, - bottom: '' - }); - } else if ( ! fixedSideTop && $sideSortables.offset().top >= windowPos + pinnedToolsTop ) { - // Pin the top. - fixedSideTop = true; - - $sideSortables.css({ - position: 'fixed', - top: pinnedToolsTop, - bottom: '' - }); - } - } - } - } else { - // If the sidebar container is smaller than the viewport, then pin/unpin the top when scrolling. - if ( windowPos >= ( postBodyTop - pinnedToolsTop ) ) { - - $sideSortables.css( { - position: 'fixed', - top: pinnedToolsTop - } ); - } else { - $sideSortables.attr( 'style', '' ); - } - - fixedSideTop = fixedSideBottom = false; - } - - lastScrollPosition = windowPos; - } else { - $sideSortables.attr( 'style', '' ); - fixedSideTop = fixedSideBottom = false; - } - - if ( resize ) { - $contentWrap.css( { - paddingTop: heights.toolsHeight - } ); - - if ( visual ) { - $visualEditor.css( { - paddingTop: heights.visualTopHeight + heights.menuBarHeight - } ); - } else { - $textEditor.css( { - marginTop: heights.textTopHeight - } ); - } - } - } - - /** - * Resizes the editor and adjusts the toolbars. - * - * @since 4.0.0 - * - * @returns {void} - */ - function fullscreenHide() { - textEditorResize(); - adjust(); - } - - /** - * Runs the passed function with 500ms intervals. - * - * @since 4.0.0 - * - * @param {function} callback The function to run in the timeout. - * - * @returns {void} - */ - function initialResize( callback ) { - for ( var i = 1; i < 6; i++ ) { - setTimeout( callback, 500 * i ); - } - } - - /** - * Runs adjust after 100ms. - * - * @since 4.0.0 - * - * @returns {void} - */ - function afterScroll() { - clearTimeout( scrollTimer ); - scrollTimer = setTimeout( adjust, 100 ); - } - - /** - * Binds editor expand events on elements. - * - * @since 4.0.0 - * - * @returns {void} - */ - function on() { - /* - * Scroll to the top when triggering this from JS. - * Ensure the toolbars are pinned properly. - */ - if ( window.pageYOffset && window.pageYOffset > pageYOffsetAtTop ) { - window.scrollTo( window.pageXOffset, 0 ); - } - - $wrap.addClass( 'wp-editor-expand' ); - - // Adjust when the window is scrolled or resized. - $window.on( 'scroll.editor-expand resize.editor-expand', function( event ) { - adjust( event.type ); - afterScroll(); - } ); - - /* - * Adjust when collapsing the menu, changing the columns - * or changing the body class. - */ - $document.on( 'wp-collapse-menu.editor-expand postboxes-columnchange.editor-expand editor-classchange.editor-expand', adjust ) - .on( 'postbox-toggled.editor-expand postbox-moved.editor-expand', function() { - if ( ! fixedSideTop && ! fixedSideBottom && window.pageYOffset > pinnedToolsTop ) { - fixedSideBottom = true; - window.scrollBy( 0, -1 ); - adjust(); - window.scrollBy( 0, 1 ); - } - - adjust(); - }).on( 'wp-window-resized.editor-expand', function() { - if ( mceEditor && ! mceEditor.isHidden() ) { - mceEditor.execCommand( 'wpAutoResize' ); - } else { - textEditorResize(); - } - }); - - $textEditor.on( 'focus.editor-expand input.editor-expand propertychange.editor-expand', textEditorResize ); - mceBind(); - - // Adjust when entering or exiting fullscreen mode. - fullscreen && fullscreen.pubsub.subscribe( 'hidden', fullscreenHide ); - - if ( mceEditor ) { - mceEditor.settings.wp_autoresize_on = true; - mceEditor.execCommand( 'wpAutoResizeOn' ); - - if ( ! mceEditor.isHidden() ) { - mceEditor.execCommand( 'wpAutoResize' ); - } - } - - if ( ! mceEditor || mceEditor.isHidden() ) { - textEditorResize(); - } - - adjust(); - - $document.trigger( 'editor-expand-on' ); - } - - /** - * Unbinds editor expand events. - * - * @since 4.0.0 - * - * @returns {void} - */ - function off() { - var height = parseInt( window.getUserSetting( 'ed_size', 300 ), 10 ); - - if ( height < 50 ) { - height = 50; - } else if ( height > 5000 ) { - height = 5000; - } - - /* - * Scroll to the top when triggering this from JS. - * Ensure the toolbars are reset properly. - */ - if ( window.pageYOffset && window.pageYOffset > pageYOffsetAtTop ) { - window.scrollTo( window.pageXOffset, 0 ); - } - - $wrap.removeClass( 'wp-editor-expand' ); - - $window.off( '.editor-expand' ); - $document.off( '.editor-expand' ); - $textEditor.off( '.editor-expand' ); - mceUnbind(); - - // Adjust when entering or exiting fullscreen mode. - fullscreen && fullscreen.pubsub.unsubscribe( 'hidden', fullscreenHide ); - - // Reset all css - $.each( [ $visualTop, $textTop, $tools, $menuBar, $bottom, $statusBar, $contentWrap, $visualEditor, $textEditor, $sideSortables ], function( i, element ) { - element && element.attr( 'style', '' ); - }); - - fixedTop = fixedBottom = fixedSideTop = fixedSideBottom = false; - - if ( mceEditor ) { - mceEditor.settings.wp_autoresize_on = false; - mceEditor.execCommand( 'wpAutoResizeOff' ); - - if ( ! mceEditor.isHidden() ) { - $textEditor.hide(); - - if ( height ) { - mceEditor.theme.resizeTo( null, height ); - } - } - } - - // If there is a height found in the user setting. - if ( height ) { - $textEditor.height( height ); - } - - $document.trigger( 'editor-expand-off' ); - } - - // Start on load. - if ( $wrap.hasClass( 'wp-editor-expand' ) ) { - on(); - - // Resize just after CSS has fully loaded and QuickTags is ready. - if ( $contentWrap.hasClass( 'html-active' ) ) { - initialResize( function() { - adjust(); - textEditorResize(); - } ); - } - } - - // Show the on/off checkbox. - $( '#adv-settings .editor-expand' ).show(); - $( '#editor-expand-toggle' ).on( 'change.editor-expand', function() { - if ( $(this).prop( 'checked' ) ) { - on(); - window.setUserSetting( 'editor_expand', 'on' ); - } else { - off(); - window.setUserSetting( 'editor_expand', 'off' ); - } - }); - - // Expose on() and off(). - window.editorExpand = { - on: on, - off: off - }; - } ); - - /** - * Handles the distraction free writing of TinyMCE. - * - * @since 4.1.0 - * - * @returns {void} - */ - $( function() { - var $body = $( document.body ), - $wrap = $( '#wpcontent' ), - $editor = $( '#post-body-content' ), - $title = $( '#title' ), - $content = $( '#content' ), - $overlay = $( document.createElement( 'DIV' ) ), - $slug = $( '#edit-slug-box' ), - $slugFocusEl = $slug.find( 'a' ) - .add( $slug.find( 'button' ) ) - .add( $slug.find( 'input' ) ), - $menuWrap = $( '#adminmenuwrap' ), - $editorWindow = $(), - $editorIframe = $(), - _isActive = window.getUserSetting( 'editor_expand', 'on' ) === 'on', - _isOn = _isActive ? window.getUserSetting( 'post_dfw' ) === 'on' : false, - traveledX = 0, - traveledY = 0, - buffer = 20, - faded, fadedAdminBar, fadedSlug, - editorRect, x, y, mouseY, scrollY, - focusLostTimer, overlayTimer, editorHasFocus; - - $body.append( $overlay ); - - $overlay.css( { - display: 'none', - position: 'fixed', - top: $adminBar.height(), - right: 0, - bottom: 0, - left: 0, - 'z-index': 9997 - } ); - - $editor.css( { - position: 'relative' - } ); - - $window.on( 'mousemove.focus', function( event ) { - mouseY = event.pageY; - } ); - - /** - * Recalculates the bottom and right position of the editor in the DOM. - * - * @since 4.1.0 - * - * @returns {void} - */ - function recalcEditorRect() { - editorRect = $editor.offset(); - editorRect.right = editorRect.left + $editor.outerWidth(); - editorRect.bottom = editorRect.top + $editor.outerHeight(); - } - - /** - * Activates the distraction free writing mode. - * - * @since 4.1.0 - * - * @returns {void} - */ - function activate() { - if ( ! _isActive ) { - _isActive = true; - - $document.trigger( 'dfw-activate' ); - $content.on( 'keydown.focus-shortcut', toggleViaKeyboard ); - } - } - - /** - * Deactivates the distraction free writing mode. - * - * @since 4.1.0 - * - * @returns {void} - */ - function deactivate() { - if ( _isActive ) { - off(); - - _isActive = false; - - $document.trigger( 'dfw-deactivate' ); - $content.off( 'keydown.focus-shortcut' ); - } - } - - /** - * Returns _isActive. - * - * @since 4.1.0 - * - * @returns {boolean} Returns true is _isActive is true. - */ - function isActive() { - return _isActive; - } - - /** - * Binds events on the editor for distraction free writing. - * - * @since 4.1.0 - * - * @returns {void} - */ - function on() { - if ( ! _isOn && _isActive ) { - _isOn = true; - - $content.on( 'keydown.focus', fadeOut ); - - $title.add( $content ).on( 'blur.focus', maybeFadeIn ); - - fadeOut(); - - window.setUserSetting( 'post_dfw', 'on' ); - - $document.trigger( 'dfw-on' ); - } - } - - /** - * Unbinds events on the editor for distraction free writing. - * - * @since 4.1.0 - * - * @returns {void} - */ - function off() { - if ( _isOn ) { - _isOn = false; - - $title.add( $content ).off( '.focus' ); - - fadeIn(); - - $editor.off( '.focus' ); - - window.setUserSetting( 'post_dfw', 'off' ); - - $document.trigger( 'dfw-off' ); - } - } - - /** - * Binds or unbinds the editor expand events. - * - * @since 4.1.0 - * - * @returns {void} - */ - function toggle() { - if ( _isOn ) { - off(); - } else { - on(); - } - } - - /** - * Returns the value of _isOn. - * - * @since 4.1.0 - * - * @returns {boolean} Returns true if _isOn is true. - */ - function isOn() { - return _isOn; - } - - /** - * Fades out all elements except for the editor. - * - * The fading is done based on key presses and mouse movements. - * Also calls the fadeIn on certain key presses - * or if the mouse leaves the editor. - * - * @since 4.1.0 - * - * @param event The event that triggers this function. - * - * @returns {void} - */ - function fadeOut( event ) { - var isMac, - key = event && event.keyCode; - - if ( window.navigator.platform ) { - isMac = ( window.navigator.platform.indexOf( 'Mac' ) > -1 ); - } - - // Fade in and returns on Escape and keyboard shortcut Alt+Shift+W and Ctrl+Opt+W. - if ( key === 27 || ( key === 87 && event.altKey && ( ( ! isMac && event.shiftKey ) || ( isMac && event.ctrlKey ) ) ) ) { - fadeIn( event ); - return; - } - - // Return if any of the following keys or combinations of keys is pressed. - if ( event && ( event.metaKey || ( event.ctrlKey && ! event.altKey ) || ( event.altKey && event.shiftKey ) || ( key && ( - // Special keys ( tab, ctrl, alt, esc, arrow keys... ) - ( key <= 47 && key !== 8 && key !== 13 && key !== 32 && key !== 46 ) || - // Windows keys - ( key >= 91 && key <= 93 ) || - // F keys - ( key >= 112 && key <= 135 ) || - // Num Lock, Scroll Lock, OEM - ( key >= 144 && key <= 150 ) || - // OEM or non-printable - key >= 224 - ) ) ) ) { - return; - } - - if ( ! faded ) { - faded = true; - - clearTimeout( overlayTimer ); - - overlayTimer = setTimeout( function() { - $overlay.show(); - }, 600 ); - - $editor.css( 'z-index', 9998 ); - - $overlay - // Always recalculate the editor area when entering the overlay with the mouse. - .on( 'mouseenter.focus', function() { - recalcEditorRect(); - - $window.on( 'scroll.focus', function() { - var nScrollY = window.pageYOffset; - - if ( ( - scrollY && mouseY && - scrollY !== nScrollY - ) && ( - mouseY < editorRect.top - buffer || - mouseY > editorRect.bottom + buffer - ) ) { - fadeIn(); - } - - scrollY = nScrollY; - } ); - } ) - .on( 'mouseleave.focus', function() { - x = y = null; - traveledX = traveledY = 0; - - $window.off( 'scroll.focus' ); - } ) - // Fade in when the mouse moves away form the editor area. - .on( 'mousemove.focus', function( event ) { - var nx = event.clientX, - ny = event.clientY, - pageYOffset = window.pageYOffset, - pageXOffset = window.pageXOffset; - - if ( x && y && ( nx !== x || ny !== y ) ) { - if ( - ( ny <= y && ny < editorRect.top - pageYOffset ) || - ( ny >= y && ny > editorRect.bottom - pageYOffset ) || - ( nx <= x && nx < editorRect.left - pageXOffset ) || - ( nx >= x && nx > editorRect.right - pageXOffset ) - ) { - traveledX += Math.abs( x - nx ); - traveledY += Math.abs( y - ny ); - - if ( ( - ny <= editorRect.top - buffer - pageYOffset || - ny >= editorRect.bottom + buffer - pageYOffset || - nx <= editorRect.left - buffer - pageXOffset || - nx >= editorRect.right + buffer - pageXOffset - ) && ( - traveledX > 10 || - traveledY > 10 - ) ) { - fadeIn(); - - x = y = null; - traveledX = traveledY = 0; - - return; - } - } else { - traveledX = traveledY = 0; - } - } - - x = nx; - y = ny; - } ) - - // When the overlay is touched, fade in and cancel the event. - .on( 'touchstart.focus', function( event ) { - event.preventDefault(); - fadeIn(); - } ); - - $editor.off( 'mouseenter.focus' ); - - if ( focusLostTimer ) { - clearTimeout( focusLostTimer ); - focusLostTimer = null; - } - - $body.addClass( 'focus-on' ).removeClass( 'focus-off' ); - } - - fadeOutAdminBar(); - fadeOutSlug(); - } - - /** - * Fades all elements back in. - * - * @since 4.1.0 - * - * @param event The event that triggers this function. - * - * @returns {void} - */ - function fadeIn( event ) { - if ( faded ) { - faded = false; - - clearTimeout( overlayTimer ); - - overlayTimer = setTimeout( function() { - $overlay.hide(); - }, 200 ); - - $editor.css( 'z-index', '' ); - - $overlay.off( 'mouseenter.focus mouseleave.focus mousemove.focus touchstart.focus' ); - - /* - * When fading in, temporarily watch for refocus and fade back out - helps - * with 'accidental' editor exits with the mouse. When fading in and the event - * is a key event (Escape or Alt+Shift+W) don't watch for refocus. - */ - if ( 'undefined' === typeof event ) { - $editor.on( 'mouseenter.focus', function() { - if ( $.contains( $editor.get( 0 ), document.activeElement ) || editorHasFocus ) { - fadeOut(); - } - } ); - } - - focusLostTimer = setTimeout( function() { - focusLostTimer = null; - $editor.off( 'mouseenter.focus' ); - }, 1000 ); - - $body.addClass( 'focus-off' ).removeClass( 'focus-on' ); - } - - fadeInAdminBar(); - fadeInSlug(); - } - - /** - * Fades in if the focused element based on it position. - * - * @since 4.1.0 - * - * @returns {void} - */ - function maybeFadeIn() { - setTimeout( function() { - var position = document.activeElement.compareDocumentPosition( $editor.get( 0 ) ); - - function hasFocus( $el ) { - return $.contains( $el.get( 0 ), document.activeElement ); - } - - // The focused node is before or behind the editor area, and not outside the wrap. - if ( ( position === 2 || position === 4 ) && ( hasFocus( $menuWrap ) || hasFocus( $wrap ) || hasFocus( $footer ) ) ) { - fadeIn(); - } - }, 0 ); - } - - /** - * Fades out the admin bar based on focus on the admin bar. - * - * @since 4.1.0 - * - * @returns {void} - */ - function fadeOutAdminBar() { - if ( ! fadedAdminBar && faded ) { - fadedAdminBar = true; - - $adminBar - .on( 'mouseenter.focus', function() { - $adminBar.addClass( 'focus-off' ); - } ) - .on( 'mouseleave.focus', function() { - $adminBar.removeClass( 'focus-off' ); - } ); - } - } - - /** - * Fades in the admin bar. - * - * @since 4.1.0 - * - * @returns {void} - */ - function fadeInAdminBar() { - if ( fadedAdminBar ) { - fadedAdminBar = false; - - $adminBar.off( '.focus' ); - } - } - - /** - * Fades out the edit slug box. - * - * @since 4.1.0 - * - * @returns {void} - */ - function fadeOutSlug() { - if ( ! fadedSlug && faded && ! $slug.find( ':focus').length ) { - fadedSlug = true; - - $slug.stop().fadeTo( 'fast', 0.3 ).on( 'mouseenter.focus', fadeInSlug ).off( 'mouseleave.focus' ); - - $slugFocusEl.on( 'focus.focus', fadeInSlug ).off( 'blur.focus' ); - } - } - - /** - * Fades in the edit slug box. - * - * @since 4.1.0 - * - * @returns {void} - */ - function fadeInSlug() { - if ( fadedSlug ) { - fadedSlug = false; - - $slug.stop().fadeTo( 'fast', 1 ).on( 'mouseleave.focus', fadeOutSlug ).off( 'mouseenter.focus' ); - - $slugFocusEl.on( 'blur.focus', fadeOutSlug ).off( 'focus.focus' ); - } - } - - /** - * Triggers the toggle on Alt + Shift + W. - * - * Keycode 87 = w. - * - * @since 4.1.0 - * - * @param {event} event The event to trigger the toggle. - * - * @returns {void} - */ - function toggleViaKeyboard( event ) { - if ( event.altKey && event.shiftKey && 87 === event.keyCode ) { - toggle(); - } - } - - if ( $( '#postdivrich' ).hasClass( 'wp-editor-expand' ) ) { - $content.on( 'keydown.focus-shortcut', toggleViaKeyboard ); - } - - /** - * Adds the distraction free writing button when setting up TinyMCE. - * - * @since 4.1.0 - * - * @param {event} event The TinyMCE editor setup event. - * @param {object} editor The editor to add the button to. - * - * @returns {void} - */ - $document.on( 'tinymce-editor-setup.focus', function( event, editor ) { - editor.addButton( 'dfw', { - active: _isOn, - classes: 'wp-dfw btn widget', - disabled: ! _isActive, - onclick: toggle, - onPostRender: function() { - var button = this; - - editor.on( 'init', function() { - if ( button.disabled() ) { - button.hide(); - } - } ); - - $document - .on( 'dfw-activate.focus', function() { - button.disabled( false ); - button.show(); - } ) - .on( 'dfw-deactivate.focus', function() { - button.disabled( true ); - button.hide(); - } ) - .on( 'dfw-on.focus', function() { - button.active( true ); - } ) - .on( 'dfw-off.focus', function() { - button.active( false ); - } ); - }, - tooltip: 'Distraction-free writing mode', - shortcut: 'Alt+Shift+W' - } ); - - editor.addCommand( 'wpToggleDFW', toggle ); - editor.addShortcut( 'access+w', '', 'wpToggleDFW' ); - } ); - - /** - * Binds and unbinds events on the editor. - * - * @since 4.1.0 - * - * @param {event} event The TinyMCE editor init event. - * @param {object} editor The editor to bind events on. - * - * @returns {void} - */ - $document.on( 'tinymce-editor-init.focus', function( event, editor ) { - var mceBind, mceUnbind; - - function focus() { - editorHasFocus = true; - } - - function blur() { - editorHasFocus = false; - } - - if ( editor.id === 'content' ) { - $editorWindow = $( editor.getWin() ); - $editorIframe = $( editor.getContentAreaContainer() ).find( 'iframe' ); - - mceBind = function() { - editor.on( 'keydown', fadeOut ); - editor.on( 'blur', maybeFadeIn ); - editor.on( 'focus', focus ); - editor.on( 'blur', blur ); - editor.on( 'wp-autoresize', recalcEditorRect ); - }; - - mceUnbind = function() { - editor.off( 'keydown', fadeOut ); - editor.off( 'blur', maybeFadeIn ); - editor.off( 'focus', focus ); - editor.off( 'blur', blur ); - editor.off( 'wp-autoresize', recalcEditorRect ); - }; - - if ( _isOn ) { - mceBind(); - } - - // Bind and unbind based on the distraction free writing focus. - $document.on( 'dfw-on.focus', mceBind ).on( 'dfw-off.focus', mceUnbind ); - - // Focuse the editor when it is the target of the click event. - editor.on( 'click', function( event ) { - if ( event.target === editor.getDoc().documentElement ) { - editor.focus(); - } - } ); - } - } ); - - /** - * Binds events on quicktags init. - * - * @since 4.1.0 - * - * @param {event} event The quicktags init event. - * @param {object} editor The editor to bind events on. - * - * @returns {void} - */ - $document.on( 'quicktags-init', function( event, editor ) { - var $button; - - // Bind the distraction free writing events if the distraction free writing button is available. - if ( editor.settings.buttons && ( ',' + editor.settings.buttons + ',' ).indexOf( ',dfw,' ) !== -1 ) { - $button = $( '#' + editor.name + '_dfw' ); - - $( document ) - .on( 'dfw-activate', function() { - $button.prop( 'disabled', false ); - } ) - .on( 'dfw-deactivate', function() { - $button.prop( 'disabled', true ); - } ) - .on( 'dfw-on', function() { - $button.addClass( 'active' ); - } ) - .on( 'dfw-off', function() { - $button.removeClass( 'active' ); - } ); - } - } ); - - $document.on( 'editor-expand-on.focus', activate ).on( 'editor-expand-off.focus', deactivate ); - - if ( _isOn ) { - $content.on( 'keydown.focus', fadeOut ); - - $title.add( $content ).on( 'blur.focus', maybeFadeIn ); - } - - window.wp = window.wp || {}; - window.wp.editor = window.wp.editor || {}; - window.wp.editor.dfw = { - activate: activate, - deactivate: deactivate, - isActive: isActive, - on: on, - off: off, - toggle: toggle, - isOn: isOn - }; - } ); -} )( window, window.jQuery ); diff --git a/srcs/wordpress/wp-admin/js/editor-expand.min.js b/srcs/wordpress/wp-admin/js/editor-expand.min.js deleted file mode 100644 index 7c4e459..0000000 --- a/srcs/wordpress/wp-admin/js/editor-expand.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(I,L){"use strict";var M=L(I),V=L(document),N=L("#wpadminbar"),j=L("#wpfooter");L(function(){var m,e,u=L("#postdivrich"),w=L("#wp-content-wrap"),H=L("#wp-content-editor-tools"),b=L(),v=L(),x=L("#ed_toolbar"),y=L("#content"),i=y[0],o=0,T=L("#post-status-info"),B=L(),C=L(),S=L("#side-sortables"),O=L("#postbox-container-1"),z=L("#post-body"),E=I.wp.editor&&I.wp.editor.fullscreen,r=function(){},l=function(){},k=!1,A=!1,W=!1,K=!1,R=0,Y=56,U=20,D=300,n=w.hasClass("tmce-active")?"tinymce":"html",P=!!parseInt(I.getUserSetting("hidetb"),10),X={windowHeight:0,windowWidth:0,adminBarHeight:0,toolsHeight:0,menuBarHeight:0,visualTopHeight:0,textTopHeight:0,bottomHeight:0,statusBarHeight:0,sideSortablesHeight:0},s=I._.throttle(function(){var t=I.scrollX||document.documentElement.scrollLeft,e=I.scrollY||document.documentElement.scrollTop,o=parseInt(i.style.height,10);i.style.height=D+"px",i.scrollHeight>D&&(i.style.height=i.scrollHeight+"px"),void 0!==t&&I.scrollTo(t,e),i.scrollHeight<o&&p()},300);function F(){var t=i.value.length;m&&!m.isHidden()||!m&&"tinymce"===n||(t<o?s():parseInt(i.style.height,10)<i.scrollHeight&&(i.style.height=Math.ceil(i.scrollHeight)+"px",p()),o=t)}function p(t){if(!E||!E.settings.visible){var e,o,i,n,s,f,a,d,c=M.scrollTop(),u=t&&t.type,r="scroll"!==u,l=m&&!m.isHidden(),p=D,g=z.offset().top,h=w.width();!r&&X.windowHeight||function(){var t=M.width();(X={windowHeight:M.height(),windowWidth:t,adminBarHeight:600<t?N.outerHeight():0,toolsHeight:H.outerHeight()||0,menuBarHeight:B.outerHeight()||0,visualTopHeight:b.outerHeight()||0,textTopHeight:x.outerHeight()||0,bottomHeight:T.outerHeight()||0,statusBarHeight:C.outerHeight()||0,sideSortablesHeight:S.height()||0}).menuBarHeight<3&&(X.menuBarHeight=0)}(),l||"resize"!==u||F(),f=l?(e=b,o=v,X.visualTopHeight):(e=x,o=y,X.textTopHeight),(l||e.length)&&(s=e.parent().offset().top,a=o.offset().top,d=o.outerHeight(),(l?D+f:D+20)+5<d?((!k||r)&&c>=s-X.toolsHeight-X.adminBarHeight&&c<=s-X.toolsHeight-X.adminBarHeight+d-p?(k=!0,H.css({position:"fixed",top:X.adminBarHeight,width:h}),l&&B.length&&B.css({position:"fixed",top:X.adminBarHeight+X.toolsHeight,width:h-2-(l?0:e.outerWidth()-e.width())}),e.css({position:"fixed",top:X.adminBarHeight+X.toolsHeight+X.menuBarHeight,width:h-2-(l?0:e.outerWidth()-e.width())})):(k||r)&&(c<=s-X.toolsHeight-X.adminBarHeight?(k=!1,H.css({position:"absolute",top:0,width:h}),l&&B.length&&B.css({position:"absolute",top:0,width:h-2}),e.css({position:"absolute",top:X.menuBarHeight,width:h-2-(l?0:e.outerWidth()-e.width())})):c>=s-X.toolsHeight-X.adminBarHeight+d-p&&(k=!1,H.css({position:"absolute",top:d-p,width:h}),l&&B.length&&B.css({position:"absolute",top:d-p,width:h-2}),e.css({position:"absolute",top:d-p+X.menuBarHeight,width:h-2-(l?0:e.outerWidth()-e.width())}))),(!A||r&&P)&&c+X.windowHeight<=a+d+X.bottomHeight+X.statusBarHeight+1?t&&0<t.deltaHeight&&t.deltaHeight<100?I.scrollBy(0,t.deltaHeight):l&&P&&(A=!0,C.css({position:"fixed",bottom:X.bottomHeight,visibility:"",width:h-2}),T.css({position:"fixed",bottom:0,width:h})):(!P&&A||(A||r)&&c+X.windowHeight>a+d+X.bottomHeight+X.statusBarHeight-1)&&(A=!1,C.attr("style",P?"":"visibility: hidden;"),T.attr("style",""))):r&&(H.css({position:"absolute",top:0,width:h}),l&&B.length&&B.css({position:"absolute",top:0,width:h-2}),e.css({position:"absolute",top:X.menuBarHeight,width:h-2-(l?0:e.outerWidth()-e.width())}),C.attr("style",P?"":"visibility: hidden;"),T.attr("style","")),O.width()<300&&600<X.windowWidth&&V.height()>S.height()+g+120&&X.windowHeight<d?(X.sideSortablesHeight+Y+U>X.windowHeight||W||K?c+Y<=g?(S.attr("style",""),W=K=!1):R<c?W?(W=!1,i=S.offset().top-X.adminBarHeight,(n=j.offset().top)<i+X.sideSortablesHeight+U&&(i=n-X.sideSortablesHeight-12),S.css({position:"absolute",top:i,bottom:""})):!K&&X.sideSortablesHeight+S.offset().top+U<c+X.windowHeight&&(K=!0,S.css({position:"fixed",top:"auto",bottom:U})):c<R&&(K?(K=!1,i=S.offset().top-U,(n=j.offset().top)<i+X.sideSortablesHeight+U&&(i=n-X.sideSortablesHeight-12),S.css({position:"absolute",top:i,bottom:""})):!W&&S.offset().top>=c+Y&&(W=!0,S.css({position:"fixed",top:Y,bottom:""}))):(g-Y<=c?S.css({position:"fixed",top:Y}):S.attr("style",""),W=K=!1),R=c):(S.attr("style",""),W=K=!1),r&&(w.css({paddingTop:X.toolsHeight}),l?v.css({paddingTop:X.visualTopHeight+X.menuBarHeight}):y.css({marginTop:X.textTopHeight})))}}function f(){F(),p()}function g(t){for(var e=1;e<6;e++)setTimeout(t,500*e)}function t(){I.pageYOffset&&130<I.pageYOffset&&I.scrollTo(I.pageXOffset,0),u.addClass("wp-editor-expand"),M.on("scroll.editor-expand resize.editor-expand",function(t){p(t.type),clearTimeout(e),e=setTimeout(p,100)}),V.on("wp-collapse-menu.editor-expand postboxes-columnchange.editor-expand editor-classchange.editor-expand",p).on("postbox-toggled.editor-expand postbox-moved.editor-expand",function(){!W&&!K&&I.pageYOffset>Y&&(K=!0,I.scrollBy(0,-1),p(),I.scrollBy(0,1)),p()}).on("wp-window-resized.editor-expand",function(){m&&!m.isHidden()?m.execCommand("wpAutoResize"):F()}),y.on("focus.editor-expand input.editor-expand propertychange.editor-expand",F),r(),E&&E.pubsub.subscribe("hidden",f),m&&(m.settings.wp_autoresize_on=!0,m.execCommand("wpAutoResizeOn"),m.isHidden()||m.execCommand("wpAutoResize")),m&&!m.isHidden()||F(),p(),V.trigger("editor-expand-on")}function a(){var t=parseInt(I.getUserSetting("ed_size",300),10);t<50?t=50:5e3<t&&(t=5e3),I.pageYOffset&&130<I.pageYOffset&&I.scrollTo(I.pageXOffset,0),u.removeClass("wp-editor-expand"),M.off(".editor-expand"),V.off(".editor-expand"),y.off(".editor-expand"),l(),E&&E.pubsub.unsubscribe("hidden",f),L.each([b,x,H,B,T,C,w,v,y,S],function(t,e){e&&e.attr("style","")}),k=A=W=K=!1,m&&(m.settings.wp_autoresize_on=!1,m.execCommand("wpAutoResizeOff"),m.isHidden()||(y.hide(),t&&m.theme.resizeTo(null,t))),t&&y.height(t),V.trigger("editor-expand-off")}V.on("tinymce-editor-init.editor-expand",function(t,f){var a=I.tinymce.util.VK,e=_.debounce(function(){L(".mce-floatpanel:hover").length||I.tinymce.ui.FloatPanel.hideAll(),L(".mce-tooltip").hide()},1e3,!0);function o(t){var e=t.keyCode;e<=47&&e!==a.SPACEBAR&&e!==a.ENTER&&e!==a.DELETE&&e!==a.BACKSPACE&&e!==a.UP&&e!==a.LEFT&&e!==a.DOWN&&e!==a.UP||91<=e&&e<=93||112<=e&&e<=123||144===e||145===e||i(e)}function i(t){var e,o,i,n,s=function(){var t,e,o,i=f.selection.getNode();if(f.wp&&f.wp.getView&&(e=f.wp.getView(i)))o=e.getBoundingClientRect();else{t=f.selection.getRng();try{o=t.getClientRects()[0]}catch(t){}o=o||i.getBoundingClientRect()}return!!o.height&&o}();s&&(o=(e=s.top+f.iframeElement.getBoundingClientRect().top)+s.height,e-=50,o+=50,i=X.adminBarHeight+X.toolsHeight+X.menuBarHeight+X.visualTopHeight,(n=X.windowHeight-(P?X.bottomHeight+X.statusBarHeight:0))-i<s.height||(e<i&&(t===a.UP||t===a.LEFT||t===a.BACKSPACE)?I.scrollTo(I.pageXOffset,e+I.pageYOffset-i):n<o&&I.scrollTo(I.pageXOffset,o+I.pageYOffset-n)))}function n(t){t.state||p()}function s(){M.on("scroll.mce-float-panels",e),setTimeout(function(){f.execCommand("wpAutoResize"),p()},300)}function d(){M.off("scroll.mce-float-panels"),setTimeout(function(){var t=w.offset().top;I.pageYOffset>t&&I.scrollTo(I.pageXOffset,t-X.adminBarHeight),F(),p()},100),p()}function c(){P=!P}"content"===f.id&&((m=f).settings.autoresize_min_height=D,b=w.find(".mce-toolbar-grp"),v=w.find(".mce-edit-area"),C=w.find(".mce-statusbar"),B=w.find(".mce-menubar"),r=function(){f.on("keyup",o),f.on("show",s),f.on("hide",d),f.on("wp-toolbar-toggle",c),f.on("setcontent wp-autoresize wp-toolbar-toggle",p),f.on("undo redo",i),f.on("FullscreenStateChanged",n),M.off("scroll.mce-float-panels").on("scroll.mce-float-panels",e)},l=function(){f.off("keyup",o),f.off("show",s),f.off("hide",d),f.off("wp-toolbar-toggle",c),f.off("setcontent wp-autoresize wp-toolbar-toggle",p),f.off("undo redo",i),f.off("FullscreenStateChanged",n),M.off("scroll.mce-float-panels")},u.hasClass("wp-editor-expand")&&(r(),g(p)))}),u.hasClass("wp-editor-expand")&&(t(),w.hasClass("html-active")&&g(function(){p(),F()})),L("#adv-settings .editor-expand").show(),L("#editor-expand-toggle").on("change.editor-expand",function(){L(this).prop("checked")?(t(),I.setUserSetting("editor_expand","on")):(a(),I.setUserSetting("editor_expand","off"))}),I.editorExpand={on:t,off:a}}),L(function(){var i,n,t,s,f,a,d,c,u,r,l,p=L(document.body),o=L("#wpcontent"),g=L("#post-body-content"),e=L("#title"),h=L("#content"),m=L(document.createElement("DIV")),w=L("#edit-slug-box"),H=w.find("a").add(w.find("button")).add(w.find("input")),b=L("#adminmenuwrap"),v=(L(),L(),"on"===I.getUserSetting("editor_expand","on")),x=!!v&&"on"===I.getUserSetting("post_dfw"),y=0,T=0,B=20;function C(){(s=g.offset()).right=s.left+g.outerWidth(),s.bottom=s.top+g.outerHeight()}function S(){v||(v=!0,V.trigger("dfw-activate"),h.on("keydown.focus-shortcut",Y))}function O(){v&&(E(),v=!1,V.trigger("dfw-deactivate"),h.off("keydown.focus-shortcut"))}function z(){!x&&v&&(x=!0,h.on("keydown.focus",k),e.add(h).on("blur.focus",W),k(),I.setUserSetting("post_dfw","on"),V.trigger("dfw-on"))}function E(){x&&(x=!1,e.add(h).off(".focus"),A(),g.off(".focus"),I.setUserSetting("post_dfw","off"),V.trigger("dfw-off"))}function _(){x?E():z()}function k(t){var e,o=t&&t.keyCode;I.navigator.platform&&(e=-1<I.navigator.platform.indexOf("Mac")),27===o||87===o&&t.altKey&&(!e&&t.shiftKey||e&&t.ctrlKey)?A(t):t&&(t.metaKey||t.ctrlKey&&!t.altKey||t.altKey&&t.shiftKey||o&&(o<=47&&8!==o&&13!==o&&32!==o&&46!==o||91<=o&&o<=93||112<=o&&o<=135||144<=o&&o<=150||224<=o))||(i||(i=!0,clearTimeout(r),r=setTimeout(function(){m.show()},600),g.css("z-index",9998),m.on("mouseenter.focus",function(){C(),M.on("scroll.focus",function(){var t=I.pageYOffset;c&&d&&c!==t&&(d<s.top-B||d>s.bottom+B)&&A(),c=t})}).on("mouseleave.focus",function(){f=a=null,y=T=0,M.off("scroll.focus")}).on("mousemove.focus",function(t){var e=t.clientX,o=t.clientY,i=I.pageYOffset,n=I.pageXOffset;if(f&&a&&(e!==f||o!==a))if(o<=a&&o<s.top-i||a<=o&&o>s.bottom-i||e<=f&&e<s.left-n||f<=e&&e>s.right-n){if(y+=Math.abs(f-e),T+=Math.abs(a-o),(o<=s.top-B-i||o>=s.bottom+B-i||e<=s.left-B-n||e>=s.right+B-n)&&(10<y||10<T))return A(),f=a=null,void(y=T=0)}else y=T=0;f=e,a=o}).on("touchstart.focus",function(t){t.preventDefault(),A()}),g.off("mouseenter.focus"),u&&(clearTimeout(u),u=null),p.addClass("focus-on").removeClass("focus-off")),!n&&i&&(n=!0,N.on("mouseenter.focus",function(){N.addClass("focus-off")}).on("mouseleave.focus",function(){N.removeClass("focus-off")})),K())}function A(t){i&&(i=!1,clearTimeout(r),r=setTimeout(function(){m.hide()},200),g.css("z-index",""),m.off("mouseenter.focus mouseleave.focus mousemove.focus touchstart.focus"),void 0===t&&g.on("mouseenter.focus",function(){(L.contains(g.get(0),document.activeElement)||l)&&k()}),u=setTimeout(function(){u=null,g.off("mouseenter.focus")},1e3),p.addClass("focus-off").removeClass("focus-on")),n&&(n=!1,N.off(".focus")),R()}function W(){setTimeout(function(){var t=document.activeElement.compareDocumentPosition(g.get(0));function e(t){return L.contains(t.get(0),document.activeElement)}2!==t&&4!==t||!(e(b)||e(o)||e(j))||A()},0)}function K(){t||!i||w.find(":focus").length||(t=!0,w.stop().fadeTo("fast",.3).on("mouseenter.focus",R).off("mouseleave.focus"),H.on("focus.focus",R).off("blur.focus"))}function R(){t&&(t=!1,w.stop().fadeTo("fast",1).on("mouseleave.focus",K).off("mouseenter.focus"),H.on("blur.focus",K).off("focus.focus"))}function Y(t){t.altKey&&t.shiftKey&&87===t.keyCode&&_()}p.append(m),m.css({display:"none",position:"fixed",top:N.height(),right:0,bottom:0,left:0,"z-index":9997}),g.css({position:"relative"}),M.on("mousemove.focus",function(t){d=t.pageY}),L("#postdivrich").hasClass("wp-editor-expand")&&h.on("keydown.focus-shortcut",Y),V.on("tinymce-editor-setup.focus",function(t,e){e.addButton("dfw",{active:x,classes:"wp-dfw btn widget",disabled:!v,onclick:_,onPostRender:function(){var t=this;e.on("init",function(){t.disabled()&&t.hide()}),V.on("dfw-activate.focus",function(){t.disabled(!1),t.show()}).on("dfw-deactivate.focus",function(){t.disabled(!0),t.hide()}).on("dfw-on.focus",function(){t.active(!0)}).on("dfw-off.focus",function(){t.active(!1)})},tooltip:"Distraction-free writing mode",shortcut:"Alt+Shift+W"}),e.addCommand("wpToggleDFW",_),e.addShortcut("access+w","","wpToggleDFW")}),V.on("tinymce-editor-init.focus",function(t,e){var o,i;function n(){l=!0}function s(){l=!1}"content"===e.id&&(L(e.getWin()),L(e.getContentAreaContainer()).find("iframe"),o=function(){e.on("keydown",k),e.on("blur",W),e.on("focus",n),e.on("blur",s),e.on("wp-autoresize",C)},i=function(){e.off("keydown",k),e.off("blur",W),e.off("focus",n),e.off("blur",s),e.off("wp-autoresize",C)},x&&o(),V.on("dfw-on.focus",o).on("dfw-off.focus",i),e.on("click",function(t){t.target===e.getDoc().documentElement&&e.focus()}))}),V.on("quicktags-init",function(t,e){var o;e.settings.buttons&&-1!==(","+e.settings.buttons+",").indexOf(",dfw,")&&(o=L("#"+e.name+"_dfw"),L(document).on("dfw-activate",function(){o.prop("disabled",!1)}).on("dfw-deactivate",function(){o.prop("disabled",!0)}).on("dfw-on",function(){o.addClass("active")}).on("dfw-off",function(){o.removeClass("active")}))}),V.on("editor-expand-on.focus",S).on("editor-expand-off.focus",O),x&&(h.on("keydown.focus",k),e.add(h).on("blur.focus",W)),I.wp=I.wp||{},I.wp.editor=I.wp.editor||{},I.wp.editor.dfw={activate:S,deactivate:O,isActive:function(){return v},on:z,off:E,toggle:_,isOn:function(){return x}}})}(window,window.jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/editor.js b/srcs/wordpress/wp-admin/js/editor.js deleted file mode 100644 index 0620b31..0000000 --- a/srcs/wordpress/wp-admin/js/editor.js +++ /dev/null @@ -1,1414 +0,0 @@ -/** - * @output wp-admin/js/editor.js - */ - -window.wp = window.wp || {}; - -( function( $, wp ) { - wp.editor = wp.editor || {}; - - /** - * Utility functions for the editor. - * - * @since 2.5.0 - */ - function SwitchEditors() { - var tinymce, $$, - exports = {}; - - function init() { - if ( ! tinymce && window.tinymce ) { - tinymce = window.tinymce; - $$ = tinymce.$; - - /** - * Handles onclick events for the Visual/Text tabs. - * - * @since 4.3.0 - * - * @returns {void} - */ - $$( document ).on( 'click', function( event ) { - var id, mode, - target = $$( event.target ); - - if ( target.hasClass( 'wp-switch-editor' ) ) { - id = target.attr( 'data-wp-editor-id' ); - mode = target.hasClass( 'switch-tmce' ) ? 'tmce' : 'html'; - switchEditor( id, mode ); - } - }); - } - } - - /** - * Returns the height of the editor toolbar(s) in px. - * - * @since 3.9.0 - * - * @param {Object} editor The TinyMCE editor. - * @returns {number} If the height is between 10 and 200 return the height, - * else return 30. - */ - function getToolbarHeight( editor ) { - var node = $$( '.mce-toolbar-grp', editor.getContainer() )[0], - height = node && node.clientHeight; - - if ( height && height > 10 && height < 200 ) { - return parseInt( height, 10 ); - } - - return 30; - } - - /** - * Switches the editor between Visual and Text mode. - * - * @since 2.5.0 - * - * @memberof switchEditors - * - * @param {string} id The id of the editor you want to change the editor mode for. Default: `content`. - * @param {string} mode The mode you want to switch to. Default: `toggle`. - * @returns {void} - */ - function switchEditor( id, mode ) { - id = id || 'content'; - mode = mode || 'toggle'; - - var editorHeight, toolbarHeight, iframe, - editor = tinymce.get( id ), - wrap = $$( '#wp-' + id + '-wrap' ), - $textarea = $$( '#' + id ), - textarea = $textarea[0]; - - if ( 'toggle' === mode ) { - if ( editor && ! editor.isHidden() ) { - mode = 'html'; - } else { - mode = 'tmce'; - } - } - - if ( 'tmce' === mode || 'tinymce' === mode ) { - // If the editor is visible we are already in `tinymce` mode. - if ( editor && ! editor.isHidden() ) { - return false; - } - - // Insert closing tags for any open tags in QuickTags. - if ( typeof( window.QTags ) !== 'undefined' ) { - window.QTags.closeAllTags( id ); - } - - editorHeight = parseInt( textarea.style.height, 10 ) || 0; - - var keepSelection = false; - if ( editor ) { - keepSelection = editor.getParam( 'wp_keep_scroll_position' ); - } else { - keepSelection = window.tinyMCEPreInit.mceInit[ id ] && - window.tinyMCEPreInit.mceInit[ id ].wp_keep_scroll_position; - } - - if ( keepSelection ) { - // Save the selection - addHTMLBookmarkInTextAreaContent( $textarea ); - } - - if ( editor ) { - editor.show(); - - // No point to resize the iframe in iOS. - if ( ! tinymce.Env.iOS && editorHeight ) { - toolbarHeight = getToolbarHeight( editor ); - editorHeight = editorHeight - toolbarHeight + 14; - - // Sane limit for the editor height. - if ( editorHeight > 50 && editorHeight < 5000 ) { - editor.theme.resizeTo( null, editorHeight ); - } - } - - if ( editor.getParam( 'wp_keep_scroll_position' ) ) { - // Restore the selection - focusHTMLBookmarkInVisualEditor( editor ); - } - } else { - tinymce.init( window.tinyMCEPreInit.mceInit[ id ] ); - } - - wrap.removeClass( 'html-active' ).addClass( 'tmce-active' ); - $textarea.attr( 'aria-hidden', true ); - window.setUserSetting( 'editor', 'tinymce' ); - - } else if ( 'html' === mode ) { - // If the editor is hidden (Quicktags is shown) we don't need to switch. - if ( editor && editor.isHidden() ) { - return false; - } - - if ( editor ) { - // Don't resize the textarea in iOS. The iframe is forced to 100% height there, we shouldn't match it. - if ( ! tinymce.Env.iOS ) { - iframe = editor.iframeElement; - editorHeight = iframe ? parseInt( iframe.style.height, 10 ) : 0; - - if ( editorHeight ) { - toolbarHeight = getToolbarHeight( editor ); - editorHeight = editorHeight + toolbarHeight - 14; - - // Sane limit for the textarea height. - if ( editorHeight > 50 && editorHeight < 5000 ) { - textarea.style.height = editorHeight + 'px'; - } - } - } - - var selectionRange = null; - - if ( editor.getParam( 'wp_keep_scroll_position' ) ) { - selectionRange = findBookmarkedPosition( editor ); - } - - editor.hide(); - - if ( selectionRange ) { - selectTextInTextArea( editor, selectionRange ); - } - } else { - // There is probably a JS error on the page. The TinyMCE editor instance doesn't exist. Show the textarea. - $textarea.css({ 'display': '', 'visibility': '' }); - } - - wrap.removeClass( 'tmce-active' ).addClass( 'html-active' ); - $textarea.attr( 'aria-hidden', false ); - window.setUserSetting( 'editor', 'html' ); - } - } - - /** - * Checks if a cursor is inside an HTML tag or comment. - * - * In order to prevent breaking HTML tags when selecting text, the cursor - * must be moved to either the start or end of the tag. - * - * This will prevent the selection marker to be inserted in the middle of an HTML tag. - * - * This function gives information whether the cursor is inside a tag or not, as well as - * the tag type, if it is a closing tag and check if the HTML tag is inside a shortcode tag, - * e.g. `[caption]<img.../>..`. - * - * @param {string} content The test content where the cursor is. - * @param {number} cursorPosition The cursor position inside the content. - * - * @returns {(null|Object)} Null if cursor is not in a tag, Object if the cursor is inside a tag. - */ - function getContainingTagInfo( content, cursorPosition ) { - var lastLtPos = content.lastIndexOf( '<', cursorPosition - 1 ), - lastGtPos = content.lastIndexOf( '>', cursorPosition ); - - if ( lastLtPos > lastGtPos || content.substr( cursorPosition, 1 ) === '>' ) { - // find what the tag is - var tagContent = content.substr( lastLtPos ), - tagMatch = tagContent.match( /<\s*(\/)?(\w+|\!-{2}.*-{2})/ ); - - if ( ! tagMatch ) { - return null; - } - - var tagType = tagMatch[2], - closingGt = tagContent.indexOf( '>' ); - - return { - ltPos: lastLtPos, - gtPos: lastLtPos + closingGt + 1, // offset by one to get the position _after_ the character, - tagType: tagType, - isClosingTag: !! tagMatch[1] - }; - } - return null; - } - - /** - * Checks if the cursor is inside a shortcode - * - * If the cursor is inside a shortcode wrapping tag, e.g. `[caption]` it's better to - * move the selection marker to before or after the shortcode. - * - * For example `[caption]` rewrites/removes anything that's between the `[caption]` tag and the - * `<img/>` tag inside. - * - * `[caption]<span>ThisIsGone</span><img .../>[caption]` - * - * Moving the selection to before or after the short code is better, since it allows to select - * something, instead of just losing focus and going to the start of the content. - * - * @param {string} content The text content to check against. - * @param {number} cursorPosition The cursor position to check. - * - * @return {(undefined|Object)} Undefined if the cursor is not wrapped in a shortcode tag. - * Information about the wrapping shortcode tag if it's wrapped in one. - */ - function getShortcodeWrapperInfo( content, cursorPosition ) { - var contentShortcodes = getShortCodePositionsInText( content ); - - for ( var i = 0; i < contentShortcodes.length; i++ ) { - var element = contentShortcodes[ i ]; - - if ( cursorPosition >= element.startIndex && cursorPosition <= element.endIndex ) { - return element; - } - } - } - - /** - * Gets a list of unique shortcodes or shortcode-look-alikes in the content. - * - * @param {string} content The content we want to scan for shortcodes. - */ - function getShortcodesInText( content ) { - var shortcodes = content.match( /\[+([\w_-])+/g ), - result = []; - - if ( shortcodes ) { - for ( var i = 0; i < shortcodes.length; i++ ) { - var shortcode = shortcodes[ i ].replace( /^\[+/g, '' ); - - if ( result.indexOf( shortcode ) === -1 ) { - result.push( shortcode ); - } - } - } - - return result; - } - - /** - * Gets all shortcodes and their positions in the content - * - * This function returns all the shortcodes that could be found in the textarea content - * along with their character positions and boundaries. - * - * This is used to check if the selection cursor is inside the boundaries of a shortcode - * and move it accordingly, to avoid breakage. - * - * @link adjustTextAreaSelectionCursors - * - * The information can also be used in other cases when we need to lookup shortcode data, - * as it's already structured! - * - * @param {string} content The content we want to scan for shortcodes - */ - function getShortCodePositionsInText( content ) { - var allShortcodes = getShortcodesInText( content ), shortcodeInfo; - - if ( allShortcodes.length === 0 ) { - return []; - } - - var shortcodeDetailsRegexp = wp.shortcode.regexp( allShortcodes.join( '|' ) ), - shortcodeMatch, // Define local scope for the variable to be used in the loop below. - shortcodesDetails = []; - - while ( shortcodeMatch = shortcodeDetailsRegexp.exec( content ) ) { - /** - * Check if the shortcode should be shown as plain text. - * - * This corresponds to the [[shortcode]] syntax, which doesn't parse the shortcode - * and just shows it as text. - */ - var showAsPlainText = shortcodeMatch[1] === '['; - - shortcodeInfo = { - shortcodeName: shortcodeMatch[2], - showAsPlainText: showAsPlainText, - startIndex: shortcodeMatch.index, - endIndex: shortcodeMatch.index + shortcodeMatch[0].length, - length: shortcodeMatch[0].length - }; - - shortcodesDetails.push( shortcodeInfo ); - } - - /** - * Get all URL matches, and treat them as embeds. - * - * Since there isn't a good way to detect if a URL by itself on a line is a previewable - * object, it's best to treat all of them as such. - * - * This means that the selection will capture the whole URL, in a similar way shrotcodes - * are treated. - */ - var urlRegexp = new RegExp( - '(^|[\\n\\r][\\n\\r]|<p>)(https?:\\/\\/[^\s"]+?)(<\\/p>\s*|[\\n\\r][\\n\\r]|$)', 'gi' - ); - - while ( shortcodeMatch = urlRegexp.exec( content ) ) { - shortcodeInfo = { - shortcodeName: 'url', - showAsPlainText: false, - startIndex: shortcodeMatch.index, - endIndex: shortcodeMatch.index + shortcodeMatch[ 0 ].length, - length: shortcodeMatch[ 0 ].length, - urlAtStartOfContent: shortcodeMatch[ 1 ] === '', - urlAtEndOfContent: shortcodeMatch[ 3 ] === '' - }; - - shortcodesDetails.push( shortcodeInfo ); - } - - return shortcodesDetails; - } - - /** - * Generate a cursor marker element to be inserted in the content. - * - * `span` seems to be the least destructive element that can be used. - * - * Using DomQuery syntax to create it, since it's used as both text and as a DOM element. - * - * @param {Object} domLib DOM library instance. - * @param {string} content The content to insert into the cusror marker element. - */ - function getCursorMarkerSpan( domLib, content ) { - return domLib( '<span>' ).css( { - display: 'inline-block', - width: 0, - overflow: 'hidden', - 'line-height': 0 - } ) - .html( content ? content : '' ); - } - - /** - * Gets adjusted selection cursor positions according to HTML tags, comments, and shortcodes. - * - * Shortcodes and HTML codes are a bit of a special case when selecting, since they may render - * content in Visual mode. If we insert selection markers somewhere inside them, it's really possible - * to break the syntax and render the HTML tag or shortcode broken. - * - * @link getShortcodeWrapperInfo - * - * @param {string} content Textarea content that the cursors are in - * @param {{cursorStart: number, cursorEnd: number}} cursorPositions Cursor start and end positions - * - * @return {{cursorStart: number, cursorEnd: number}} - */ - function adjustTextAreaSelectionCursors( content, cursorPositions ) { - var voidElements = [ - 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', - 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr' - ]; - - var cursorStart = cursorPositions.cursorStart, - cursorEnd = cursorPositions.cursorEnd, - // check if the cursor is in a tag and if so, adjust it - isCursorStartInTag = getContainingTagInfo( content, cursorStart ); - - if ( isCursorStartInTag ) { - /** - * Only move to the start of the HTML tag (to select the whole element) if the tag - * is part of the voidElements list above. - * - * This list includes tags that are self-contained and don't need a closing tag, according to the - * HTML5 specification. - * - * This is done in order to make selection of text a bit more consistent when selecting text in - * `<p>` tags or such. - * - * In cases where the tag is not a void element, the cursor is put to the end of the tag, - * so it's either between the opening and closing tag elements or after the closing tag. - */ - if ( voidElements.indexOf( isCursorStartInTag.tagType ) !== -1 ) { - cursorStart = isCursorStartInTag.ltPos; - } else { - cursorStart = isCursorStartInTag.gtPos; - } - } - - var isCursorEndInTag = getContainingTagInfo( content, cursorEnd ); - if ( isCursorEndInTag ) { - cursorEnd = isCursorEndInTag.gtPos; - } - - var isCursorStartInShortcode = getShortcodeWrapperInfo( content, cursorStart ); - if ( isCursorStartInShortcode && ! isCursorStartInShortcode.showAsPlainText ) { - /** - * If a URL is at the start or the end of the content, - * the selection doesn't work, because it inserts a marker in the text, - * which breaks the embedURL detection. - * - * The best way to avoid that and not modify the user content is to - * adjust the cursor to either after or before URL. - */ - if ( isCursorStartInShortcode.urlAtStartOfContent ) { - cursorStart = isCursorStartInShortcode.endIndex; - } else { - cursorStart = isCursorStartInShortcode.startIndex; - } - } - - var isCursorEndInShortcode = getShortcodeWrapperInfo( content, cursorEnd ); - if ( isCursorEndInShortcode && ! isCursorEndInShortcode.showAsPlainText ) { - if ( isCursorEndInShortcode.urlAtEndOfContent ) { - cursorEnd = isCursorEndInShortcode.startIndex; - } else { - cursorEnd = isCursorEndInShortcode.endIndex; - } - } - - return { - cursorStart: cursorStart, - cursorEnd: cursorEnd - }; - } - - /** - * Adds text selection markers in the editor textarea. - * - * Adds selection markers in the content of the editor `textarea`. - * The method directly manipulates the `textarea` content, to allow TinyMCE plugins - * to run after the markers are added. - * - * @param {object} $textarea TinyMCE's textarea wrapped as a DomQuery object - */ - function addHTMLBookmarkInTextAreaContent( $textarea ) { - if ( ! $textarea || ! $textarea.length ) { - // If no valid $textarea object is provided, there's nothing we can do. - return; - } - - var textArea = $textarea[0], - textAreaContent = textArea.value, - - adjustedCursorPositions = adjustTextAreaSelectionCursors( textAreaContent, { - cursorStart: textArea.selectionStart, - cursorEnd: textArea.selectionEnd - } ), - - htmlModeCursorStartPosition = adjustedCursorPositions.cursorStart, - htmlModeCursorEndPosition = adjustedCursorPositions.cursorEnd, - - mode = htmlModeCursorStartPosition !== htmlModeCursorEndPosition ? 'range' : 'single', - - selectedText = null, - cursorMarkerSkeleton = getCursorMarkerSpan( $$, '' ).attr( 'data-mce-type','bookmark' ); - - if ( mode === 'range' ) { - var markedText = textArea.value.slice( htmlModeCursorStartPosition, htmlModeCursorEndPosition ), - bookMarkEnd = cursorMarkerSkeleton.clone().addClass( 'mce_SELRES_end' ); - - selectedText = [ - markedText, - bookMarkEnd[0].outerHTML - ].join( '' ); - } - - textArea.value = [ - textArea.value.slice( 0, htmlModeCursorStartPosition ), // text until the cursor/selection position - cursorMarkerSkeleton.clone() // cursor/selection start marker - .addClass( 'mce_SELRES_start' )[0].outerHTML, - selectedText, // selected text with end cursor/position marker - textArea.value.slice( htmlModeCursorEndPosition ) // text from last cursor/selection position to end - ].join( '' ); - } - - /** - * Focuses the selection markers in Visual mode. - * - * The method checks for existing selection markers inside the editor DOM (Visual mode) - * and create a selection between the two nodes using the DOM `createRange` selection API - * - * If there is only a single node, select only the single node through TinyMCE's selection API - * - * @param {Object} editor TinyMCE editor instance. - */ - function focusHTMLBookmarkInVisualEditor( editor ) { - var startNode = editor.$( '.mce_SELRES_start' ).attr( 'data-mce-bogus', 1 ), - endNode = editor.$( '.mce_SELRES_end' ).attr( 'data-mce-bogus', 1 ); - - if ( startNode.length ) { - editor.focus(); - - if ( ! endNode.length ) { - editor.selection.select( startNode[0] ); - } else { - var selection = editor.getDoc().createRange(); - - selection.setStartAfter( startNode[0] ); - selection.setEndBefore( endNode[0] ); - - editor.selection.setRng( selection ); - } - } - - if ( editor.getParam( 'wp_keep_scroll_position' ) ) { - scrollVisualModeToStartElement( editor, startNode ); - } - - removeSelectionMarker( startNode ); - removeSelectionMarker( endNode ); - - editor.save(); - } - - /** - * Removes selection marker and the parent node if it is an empty paragraph. - * - * By default TinyMCE wraps loose inline tags in a `<p>`. - * When removing selection markers an empty `<p>` may be left behind, remove it. - * - * @param {object} $marker The marker to be removed from the editor DOM, wrapped in an instnce of `editor.$` - */ - function removeSelectionMarker( $marker ) { - var $markerParent = $marker.parent(); - - $marker.remove(); - - //Remove empty paragraph left over after removing the marker. - if ( $markerParent.is( 'p' ) && ! $markerParent.children().length && ! $markerParent.text() ) { - $markerParent.remove(); - } - } - - /** - * Scrolls the content to place the selected element in the center of the screen. - * - * Takes an element, that is usually the selection start element, selected in - * `focusHTMLBookmarkInVisualEditor()` and scrolls the screen so the element appears roughly - * in the middle of the screen. - * - * I order to achieve the proper positioning, the editor media bar and toolbar are subtracted - * from the window height, to get the proper viewport window, that the user sees. - * - * @param {Object} editor TinyMCE editor instance. - * @param {Object} element HTMLElement that should be scrolled into view. - */ - function scrollVisualModeToStartElement( editor, element ) { - var elementTop = editor.$( element ).offset().top, - TinyMCEContentAreaTop = editor.$( editor.getContentAreaContainer() ).offset().top, - - toolbarHeight = getToolbarHeight( editor ), - - edTools = $( '#wp-content-editor-tools' ), - edToolsHeight = 0, - edToolsOffsetTop = 0, - - $scrollArea; - - if ( edTools.length ) { - edToolsHeight = edTools.height(); - edToolsOffsetTop = edTools.offset().top; - } - - var windowHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight, - - selectionPosition = TinyMCEContentAreaTop + elementTop, - visibleAreaHeight = windowHeight - ( edToolsHeight + toolbarHeight ); - - // There's no need to scroll if the selection is inside the visible area. - if ( selectionPosition < visibleAreaHeight ) { - return; - } - - /** - * The minimum scroll height should be to the top of the editor, to offer a consistent - * experience. - * - * In order to find the top of the editor, we calculate the offset of `#wp-content-editor-tools` and - * subtracting the height. This gives the scroll position where the top of the editor tools aligns with - * the top of the viewport (under the Master Bar) - */ - var adjustedScroll; - if ( editor.settings.wp_autoresize_on ) { - $scrollArea = $( 'html,body' ); - adjustedScroll = Math.max( selectionPosition - visibleAreaHeight / 2, edToolsOffsetTop - edToolsHeight ); - } else { - $scrollArea = $( editor.contentDocument ).find( 'html,body' ); - adjustedScroll = elementTop; - } - - $scrollArea.animate( { - scrollTop: parseInt( adjustedScroll, 10 ) - }, 100 ); - } - - /** - * This method was extracted from the `SaveContent` hook in - * `wp-includes/js/tinymce/plugins/wordpress/plugin.js`. - * - * It's needed here, since the method changes the content a bit, which confuses the cursor position. - * - * @param {Object} event TinyMCE event object. - */ - function fixTextAreaContent( event ) { - // Keep empty paragraphs :( - event.content = event.content.replace( /<p>(?:<br ?\/?>|\u00a0|\uFEFF| )*<\/p>/g, '<p> </p>' ); - } - - /** - * Finds the current selection position in the Visual editor. - * - * Find the current selection in the Visual editor by inserting marker elements at the start - * and end of the selection. - * - * Uses the standard DOM selection API to achieve that goal. - * - * Check the notes in the comments in the code below for more information on some gotchas - * and why this solution was chosen. - * - * @param {Object} editor The editor where we must find the selection - * @returns {(null|Object)} The selection range position in the editor - */ - function findBookmarkedPosition( editor ) { - // Get the TinyMCE `window` reference, since we need to access the raw selection. - var TinyMCEWindow = editor.getWin(), - selection = TinyMCEWindow.getSelection(); - - if ( ! selection || selection.rangeCount < 1 ) { - // no selection, no need to continue. - return; - } - - /** - * The ID is used to avoid replacing user generated content, that may coincide with the - * format specified below. - * @type {string} - */ - var selectionID = 'SELRES_' + Math.random(); - - /** - * Create two marker elements that will be used to mark the start and the end of the range. - * - * The elements have hardcoded style that makes them invisible. This is done to avoid seeing - * random content flickering in the editor when switching between modes. - */ - var spanSkeleton = getCursorMarkerSpan( editor.$, selectionID ), - startElement = spanSkeleton.clone().addClass( 'mce_SELRES_start' ), - endElement = spanSkeleton.clone().addClass( 'mce_SELRES_end' ); - - /** - * Inspired by: - * @link https://stackoverflow.com/a/17497803/153310 - * - * Why do it this way and not with TinyMCE's bookmarks? - * - * TinyMCE's bookmarks are very nice when working with selections and positions, BUT - * there is no way to determine the precise position of the bookmark when switching modes, since - * TinyMCE does some serialization of the content, to fix things like shortcodes, run plugins, prettify - * HTML code and so on. In this process, the bookmark markup gets lost. - * - * If we decide to hook right after the bookmark is added, we can see where the bookmark is in the raw HTML - * in TinyMCE. Unfortunately this state is before the serialization, so any visual markup in the content will - * throw off the positioning. - * - * To avoid this, we insert two custom `span`s that will serve as the markers at the beginning and end of the - * selection. - * - * Why not use TinyMCE's selection API or the DOM API to wrap the contents? Because if we do that, this creates - * a new node, which is inserted in the dom. Now this will be fine, if we worked with fixed selections to - * full nodes. Unfortunately in our case, the user can select whatever they like, which means that the - * selection may start in the middle of one node and end in the middle of a completely different one. If we - * wrap the selection in another node, this will create artifacts in the content. - * - * Using the method below, we insert the custom `span` nodes at the start and at the end of the selection. - * This helps us not break the content and also gives us the option to work with multi-node selections without - * breaking the markup. - */ - var range = selection.getRangeAt( 0 ), - startNode = range.startContainer, - startOffset = range.startOffset, - boundaryRange = range.cloneRange(); - - /** - * If the selection is on a shortcode with Live View, TinyMCE creates a bogus markup, - * which we have to account for. - */ - if ( editor.$( startNode ).parents( '.mce-offscreen-selection' ).length > 0 ) { - startNode = editor.$( '[data-mce-selected]' )[0]; - - /** - * Marking the start and end element with `data-mce-object-selection` helps - * discern when the selected object is a Live Preview selection. - * - * This way we can adjust the selection to properly select only the content, ignoring - * whitespace inserted around the selected object by the Editor. - */ - startElement.attr( 'data-mce-object-selection', 'true' ); - endElement.attr( 'data-mce-object-selection', 'true' ); - - editor.$( startNode ).before( startElement[0] ); - editor.$( startNode ).after( endElement[0] ); - } else { - boundaryRange.collapse( false ); - boundaryRange.insertNode( endElement[0] ); - - boundaryRange.setStart( startNode, startOffset ); - boundaryRange.collapse( true ); - boundaryRange.insertNode( startElement[0] ); - - range.setStartAfter( startElement[0] ); - range.setEndBefore( endElement[0] ); - selection.removeAllRanges(); - selection.addRange( range ); - } - - /** - * Now the editor's content has the start/end nodes. - * - * Unfortunately the content goes through some more changes after this step, before it gets inserted - * in the `textarea`. This means that we have to do some minor cleanup on our own here. - */ - editor.on( 'GetContent', fixTextAreaContent ); - - var content = removep( editor.getContent() ); - - editor.off( 'GetContent', fixTextAreaContent ); - - startElement.remove(); - endElement.remove(); - - var startRegex = new RegExp( - '<span[^>]*\\s*class="mce_SELRES_start"[^>]+>\\s*' + selectionID + '[^<]*<\\/span>(\\s*)' - ); - - var endRegex = new RegExp( - '(\\s*)<span[^>]*\\s*class="mce_SELRES_end"[^>]+>\\s*' + selectionID + '[^<]*<\\/span>' - ); - - var startMatch = content.match( startRegex ), - endMatch = content.match( endRegex ); - - if ( ! startMatch ) { - return null; - } - - var startIndex = startMatch.index, - startMatchLength = startMatch[0].length, - endIndex = null; - - if (endMatch) { - /** - * Adjust the selection index, if the selection contains a Live Preview object or not. - * - * Check where the `data-mce-object-selection` attribute is set above for more context. - */ - if ( startMatch[0].indexOf( 'data-mce-object-selection' ) !== -1 ) { - startMatchLength -= startMatch[1].length; - } - - var endMatchIndex = endMatch.index; - - if ( endMatch[0].indexOf( 'data-mce-object-selection' ) !== -1 ) { - endMatchIndex -= endMatch[1].length; - } - - // We need to adjust the end position to discard the length of the range start marker - endIndex = endMatchIndex - startMatchLength; - } - - return { - start: startIndex, - end: endIndex - }; - } - - /** - * Selects text in the TinyMCE `textarea`. - * - * Selects the text in TinyMCE's textarea that's between `selection.start` and `selection.end`. - * - * For `selection` parameter: - * @link findBookmarkedPosition - * - * @param {Object} editor TinyMCE's editor instance. - * @param {Object} selection Selection data. - */ - function selectTextInTextArea( editor, selection ) { - // only valid in the text area mode and if we have selection - if ( ! selection ) { - return; - } - - var textArea = editor.getElement(), - start = selection.start, - end = selection.end || selection.start; - - if ( textArea.focus ) { - // Wait for the Visual editor to be hidden, then focus and scroll to the position - setTimeout( function() { - textArea.setSelectionRange( start, end ); - if ( textArea.blur ) { - // defocus before focusing - textArea.blur(); - } - textArea.focus(); - }, 100 ); - } - } - - // Restore the selection when the editor is initialized. Needed when the Text editor is the default. - $( document ).on( 'tinymce-editor-init.keep-scroll-position', function( event, editor ) { - if ( editor.$( '.mce_SELRES_start' ).length ) { - focusHTMLBookmarkInVisualEditor( editor ); - } - } ); - - /** - * Replaces <p> tags with two line breaks. "Opposite" of wpautop(). - * - * Replaces <p> tags with two line breaks except where the <p> has attributes. - * Unifies whitespace. - * Indents <li>, <dt> and <dd> for better readability. - * - * @since 2.5.0 - * - * @memberof switchEditors - * - * @param {string} html The content from the editor. - * @return {string} The content with stripped paragraph tags. - */ - function removep( html ) { - var blocklist = 'blockquote|ul|ol|li|dl|dt|dd|table|thead|tbody|tfoot|tr|th|td|h[1-6]|fieldset|figure', - blocklist1 = blocklist + '|div|p', - blocklist2 = blocklist + '|pre', - preserve_linebreaks = false, - preserve_br = false, - preserve = []; - - if ( ! html ) { - return ''; - } - - // Protect script and style tags. - if ( html.indexOf( '<script' ) !== -1 || html.indexOf( '<style' ) !== -1 ) { - html = html.replace( /<(script|style)[^>]*>[\s\S]*?<\/\1>/g, function( match ) { - preserve.push( match ); - return '<wp-preserve>'; - } ); - } - - // Protect pre tags. - if ( html.indexOf( '<pre' ) !== -1 ) { - preserve_linebreaks = true; - html = html.replace( /<pre[^>]*>[\s\S]+?<\/pre>/g, function( a ) { - a = a.replace( /<br ?\/?>(\r\n|\n)?/g, '<wp-line-break>' ); - a = a.replace( /<\/?p( [^>]*)?>(\r\n|\n)?/g, '<wp-line-break>' ); - return a.replace( /\r?\n/g, '<wp-line-break>' ); - }); - } - - // Remove line breaks but keep <br> tags inside image captions. - if ( html.indexOf( '[caption' ) !== -1 ) { - preserve_br = true; - html = html.replace( /\[caption[\s\S]+?\[\/caption\]/g, function( a ) { - return a.replace( /<br([^>]*)>/g, '<wp-temp-br$1>' ).replace( /[\r\n\t]+/, '' ); - }); - } - - // Normalize white space characters before and after block tags. - html = html.replace( new RegExp( '\\s*</(' + blocklist1 + ')>\\s*', 'g' ), '</$1>\n' ); - html = html.replace( new RegExp( '\\s*<((?:' + blocklist1 + ')(?: [^>]*)?)>', 'g' ), '\n<$1>' ); - - // Mark </p> if it has any attributes. - html = html.replace( /(<p [^>]+>.*?)<\/p>/g, '$1</p#>' ); - - // Preserve the first <p> inside a <div>. - html = html.replace( /<div( [^>]*)?>\s*<p>/gi, '<div$1>\n\n' ); - - // Remove paragraph tags. - html = html.replace( /\s*<p>/gi, '' ); - html = html.replace( /\s*<\/p>\s*/gi, '\n\n' ); - - // Normalize white space chars and remove multiple line breaks. - html = html.replace( /\n[\s\u00a0]+\n/g, '\n\n' ); - - // Replace <br> tags with line breaks. - html = html.replace( /(\s*)<br ?\/?>\s*/gi, function( match, space ) { - if ( space && space.indexOf( '\n' ) !== -1 ) { - return '\n\n'; - } - - return '\n'; - }); - - // Fix line breaks around <div>. - html = html.replace( /\s*<div/g, '\n<div' ); - html = html.replace( /<\/div>\s*/g, '</div>\n' ); - - // Fix line breaks around caption shortcodes. - html = html.replace( /\s*\[caption([^\[]+)\[\/caption\]\s*/gi, '\n\n[caption$1[/caption]\n\n' ); - html = html.replace( /caption\]\n\n+\[caption/g, 'caption]\n\n[caption' ); - - // Pad block elements tags with a line break. - html = html.replace( new RegExp('\\s*<((?:' + blocklist2 + ')(?: [^>]*)?)\\s*>', 'g' ), '\n<$1>' ); - html = html.replace( new RegExp('\\s*</(' + blocklist2 + ')>\\s*', 'g' ), '</$1>\n' ); - - // Indent <li>, <dt> and <dd> tags. - html = html.replace( /<((li|dt|dd)[^>]*)>/g, ' \t<$1>' ); - - // Fix line breaks around <select> and <option>. - if ( html.indexOf( '<option' ) !== -1 ) { - html = html.replace( /\s*<option/g, '\n<option' ); - html = html.replace( /\s*<\/select>/g, '\n</select>' ); - } - - // Pad <hr> with two line breaks. - if ( html.indexOf( '<hr' ) !== -1 ) { - html = html.replace( /\s*<hr( [^>]*)?>\s*/g, '\n\n<hr$1>\n\n' ); - } - - // Remove line breaks in <object> tags. - if ( html.indexOf( '<object' ) !== -1 ) { - html = html.replace( /<object[\s\S]+?<\/object>/g, function( a ) { - return a.replace( /[\r\n]+/g, '' ); - }); - } - - // Unmark special paragraph closing tags. - html = html.replace( /<\/p#>/g, '</p>\n' ); - - // Pad remaining <p> tags whit a line break. - html = html.replace( /\s*(<p [^>]+>[\s\S]*?<\/p>)/g, '\n$1' ); - - // Trim. - html = html.replace( /^\s+/, '' ); - html = html.replace( /[\s\u00a0]+$/, '' ); - - if ( preserve_linebreaks ) { - html = html.replace( /<wp-line-break>/g, '\n' ); - } - - if ( preserve_br ) { - html = html.replace( /<wp-temp-br([^>]*)>/g, '<br$1>' ); - } - - // Restore preserved tags. - if ( preserve.length ) { - html = html.replace( /<wp-preserve>/g, function() { - return preserve.shift(); - } ); - } - - return html; - } - - /** - * Replaces two line breaks with a paragraph tag and one line break with a <br>. - * - * Similar to `wpautop()` in formatting.php. - * - * @since 2.5.0 - * - * @memberof switchEditors - * - * @param {string} text The text input. - * @returns {string} The formatted text. - */ - function autop( text ) { - var preserve_linebreaks = false, - preserve_br = false, - blocklist = 'table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre' + - '|form|map|area|blockquote|address|math|style|p|h[1-6]|hr|fieldset|legend|section' + - '|article|aside|hgroup|header|footer|nav|figure|figcaption|details|menu|summary'; - - // Normalize line breaks. - text = text.replace( /\r\n|\r/g, '\n' ); - - // Remove line breaks from <object>. - if ( text.indexOf( '<object' ) !== -1 ) { - text = text.replace( /<object[\s\S]+?<\/object>/g, function( a ) { - return a.replace( /\n+/g, '' ); - }); - } - - // Remove line breaks from tags. - text = text.replace( /<[^<>]+>/g, function( a ) { - return a.replace( /[\n\t ]+/g, ' ' ); - }); - - // Preserve line breaks in <pre> and <script> tags. - if ( text.indexOf( '<pre' ) !== -1 || text.indexOf( '<script' ) !== -1 ) { - preserve_linebreaks = true; - text = text.replace( /<(pre|script)[^>]*>[\s\S]*?<\/\1>/g, function( a ) { - return a.replace( /\n/g, '<wp-line-break>' ); - }); - } - - if ( text.indexOf( '<figcaption' ) !== -1 ) { - text = text.replace( /\s*(<figcaption[^>]*>)/g, '$1' ); - text = text.replace( /<\/figcaption>\s*/g, '</figcaption>' ); - } - - // Keep <br> tags inside captions. - if ( text.indexOf( '[caption' ) !== -1 ) { - preserve_br = true; - - text = text.replace( /\[caption[\s\S]+?\[\/caption\]/g, function( a ) { - a = a.replace( /<br([^>]*)>/g, '<wp-temp-br$1>' ); - - a = a.replace( /<[^<>]+>/g, function( b ) { - return b.replace( /[\n\t ]+/, ' ' ); - }); - - return a.replace( /\s*\n\s*/g, '<wp-temp-br />' ); - }); - } - - text = text + '\n\n'; - text = text.replace( /<br \/>\s*<br \/>/gi, '\n\n' ); - - // Pad block tags with two line breaks. - text = text.replace( new RegExp( '(<(?:' + blocklist + ')(?: [^>]*)?>)', 'gi' ), '\n\n$1' ); - text = text.replace( new RegExp( '(</(?:' + blocklist + ')>)', 'gi' ), '$1\n\n' ); - text = text.replace( /<hr( [^>]*)?>/gi, '<hr$1>\n\n' ); - - // Remove white space chars around <option>. - text = text.replace( /\s*<option/gi, '<option' ); - text = text.replace( /<\/option>\s*/gi, '</option>' ); - - // Normalize multiple line breaks and white space chars. - text = text.replace( /\n\s*\n+/g, '\n\n' ); - - // Convert two line breaks to a paragraph. - text = text.replace( /([\s\S]+?)\n\n/g, '<p>$1</p>\n' ); - - // Remove empty paragraphs. - text = text.replace( /<p>\s*?<\/p>/gi, ''); - - // Remove <p> tags that are around block tags. - text = text.replace( new RegExp( '<p>\\s*(</?(?:' + blocklist + ')(?: [^>]*)?>)\\s*</p>', 'gi' ), '$1' ); - text = text.replace( /<p>(<li.+?)<\/p>/gi, '$1'); - - // Fix <p> in blockquotes. - text = text.replace( /<p>\s*<blockquote([^>]*)>/gi, '<blockquote$1><p>'); - text = text.replace( /<\/blockquote>\s*<\/p>/gi, '</p></blockquote>'); - - // Remove <p> tags that are wrapped around block tags. - text = text.replace( new RegExp( '<p>\\s*(</?(?:' + blocklist + ')(?: [^>]*)?>)', 'gi' ), '$1' ); - text = text.replace( new RegExp( '(</?(?:' + blocklist + ')(?: [^>]*)?>)\\s*</p>', 'gi' ), '$1' ); - - text = text.replace( /(<br[^>]*>)\s*\n/gi, '$1' ); - - // Add <br> tags. - text = text.replace( /\s*\n/g, '<br />\n'); - - // Remove <br> tags that are around block tags. - text = text.replace( new RegExp( '(</?(?:' + blocklist + ')[^>]*>)\\s*<br />', 'gi' ), '$1' ); - text = text.replace( /<br \/>(\s*<\/?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)>)/gi, '$1' ); - - // Remove <p> and <br> around captions. - text = text.replace( /(?:<p>|<br ?\/?>)*\s*\[caption([^\[]+)\[\/caption\]\s*(?:<\/p>|<br ?\/?>)*/gi, '[caption$1[/caption]' ); - - // Make sure there is <p> when there is </p> inside block tags that can contain other blocks. - text = text.replace( /(<(?:div|th|td|form|fieldset|dd)[^>]*>)(.*?)<\/p>/g, function( a, b, c ) { - if ( c.match( /<p( [^>]*)?>/ ) ) { - return a; - } - - return b + '<p>' + c + '</p>'; - }); - - // Restore the line breaks in <pre> and <script> tags. - if ( preserve_linebreaks ) { - text = text.replace( /<wp-line-break>/g, '\n' ); - } - - // Restore the <br> tags in captions. - if ( preserve_br ) { - text = text.replace( /<wp-temp-br([^>]*)>/g, '<br$1>' ); - } - - return text; - } - - /** - * Fires custom jQuery events `beforePreWpautop` and `afterPreWpautop` when jQuery is available. - * - * @since 2.9.0 - * - * @memberof switchEditors - * - * @param {String} html The content from the visual editor. - * @returns {String} the filtered content. - */ - function pre_wpautop( html ) { - var obj = { o: exports, data: html, unfiltered: html }; - - if ( $ ) { - $( 'body' ).trigger( 'beforePreWpautop', [ obj ] ); - } - - obj.data = removep( obj.data ); - - if ( $ ) { - $( 'body' ).trigger( 'afterPreWpautop', [ obj ] ); - } - - return obj.data; - } - - /** - * Fires custom jQuery events `beforeWpautop` and `afterWpautop` when jQuery is available. - * - * @since 2.9.0 - * - * @memberof switchEditors - * - * @param {String} text The content from the text editor. - * @returns {String} filtered content. - */ - function wpautop( text ) { - var obj = { o: exports, data: text, unfiltered: text }; - - if ( $ ) { - $( 'body' ).trigger( 'beforeWpautop', [ obj ] ); - } - - obj.data = autop( obj.data ); - - if ( $ ) { - $( 'body' ).trigger( 'afterWpautop', [ obj ] ); - } - - return obj.data; - } - - if ( $ ) { - $( document ).ready( init ); - } else if ( document.addEventListener ) { - document.addEventListener( 'DOMContentLoaded', init, false ); - window.addEventListener( 'load', init, false ); - } else if ( window.attachEvent ) { - window.attachEvent( 'onload', init ); - document.attachEvent( 'onreadystatechange', function() { - if ( 'complete' === document.readyState ) { - init(); - } - } ); - } - - wp.editor.autop = wpautop; - wp.editor.removep = pre_wpautop; - - exports = { - go: switchEditor, - wpautop: wpautop, - pre_wpautop: pre_wpautop, - _wp_Autop: autop, - _wp_Nop: removep - }; - - return exports; - } - - /** - * Expose the switch editors to be used globally. - * - * @namespace switchEditors - */ - window.switchEditors = new SwitchEditors(); - - /** - * Initialize TinyMCE and/or Quicktags. For use with wp_enqueue_editor() (PHP). - * - * Intended for use with an existing textarea that will become the Text editor tab. - * The editor width will be the width of the textarea container, height will be adjustable. - * - * Settings for both TinyMCE and Quicktags can be passed on initialization, and are "filtered" - * with custom jQuery events on the document element, wp-before-tinymce-init and wp-before-quicktags-init. - * - * @since 4.8.0 - * - * @param {string} id The HTML id of the textarea that is used for the editor. - * Has to be jQuery compliant. No brackets, special chars, etc. - * @param {object} settings Example: - * settings = { - * // See https://www.tinymce.com/docs/configure/integration-and-setup/. - * // Alternatively set to `true` to use the defaults. - * tinymce: { - * setup: function( editor ) { - * console.log( 'Editor initialized', editor ); - * } - * } - * - * // Alternatively set to `true` to use the defaults. - * quicktags: { - * buttons: 'strong,em,link' - * } - * } - */ - wp.editor.initialize = function( id, settings ) { - var init; - var defaults; - - if ( ! $ || ! id || ! wp.editor.getDefaultSettings ) { - return; - } - - defaults = wp.editor.getDefaultSettings(); - - // Initialize TinyMCE by default - if ( ! settings ) { - settings = { - tinymce: true - }; - } - - // Add wrap and the Visual|Text tabs. - if ( settings.tinymce && settings.quicktags ) { - var $textarea = $( '#' + id ); - - var $wrap = $( '<div>' ).attr( { - 'class': 'wp-core-ui wp-editor-wrap tmce-active', - id: 'wp-' + id + '-wrap' - } ); - - var $editorContainer = $( '<div class="wp-editor-container">' ); - - var $button = $( '<button>' ).attr( { - type: 'button', - 'data-wp-editor-id': id - } ); - - var $editorTools = $( '<div class="wp-editor-tools">' ); - - if ( settings.mediaButtons ) { - var buttonText = 'Add Media'; - - if ( window._wpMediaViewsL10n && window._wpMediaViewsL10n.addMedia ) { - buttonText = window._wpMediaViewsL10n.addMedia; - } - - var $addMediaButton = $( '<button type="button" class="button insert-media add_media">' ); - - $addMediaButton.append( '<span class="wp-media-buttons-icon"></span>' ); - $addMediaButton.append( document.createTextNode( ' ' + buttonText ) ); - $addMediaButton.data( 'editor', id ); - - $editorTools.append( - $( '<div class="wp-media-buttons">' ) - .append( $addMediaButton ) - ); - } - - $wrap.append( - $editorTools - .append( $( '<div class="wp-editor-tabs">' ) - .append( $button.clone().attr({ - id: id + '-tmce', - 'class': 'wp-switch-editor switch-tmce' - }).text( window.tinymce.translate( 'Visual' ) ) ) - .append( $button.attr({ - id: id + '-html', - 'class': 'wp-switch-editor switch-html' - }).text( window.tinymce.translate( 'Text' ) ) ) - ).append( $editorContainer ) - ); - - $textarea.after( $wrap ); - $editorContainer.append( $textarea ); - } - - if ( window.tinymce && settings.tinymce ) { - if ( typeof settings.tinymce !== 'object' ) { - settings.tinymce = {}; - } - - init = $.extend( {}, defaults.tinymce, settings.tinymce ); - init.selector = '#' + id; - - $( document ).trigger( 'wp-before-tinymce-init', init ); - window.tinymce.init( init ); - - if ( ! window.wpActiveEditor ) { - window.wpActiveEditor = id; - } - } - - if ( window.quicktags && settings.quicktags ) { - if ( typeof settings.quicktags !== 'object' ) { - settings.quicktags = {}; - } - - init = $.extend( {}, defaults.quicktags, settings.quicktags ); - init.id = id; - - $( document ).trigger( 'wp-before-quicktags-init', init ); - window.quicktags( init ); - - if ( ! window.wpActiveEditor ) { - window.wpActiveEditor = init.id; - } - } - }; - - /** - * Remove one editor instance. - * - * Intended for use with editors that were initialized with wp.editor.initialize(). - * - * @since 4.8.0 - * - * @param {string} id The HTML id of the editor textarea. - */ - wp.editor.remove = function( id ) { - var mceInstance, qtInstance, - $wrap = $( '#wp-' + id + '-wrap' ); - - if ( window.tinymce ) { - mceInstance = window.tinymce.get( id ); - - if ( mceInstance ) { - if ( ! mceInstance.isHidden() ) { - mceInstance.save(); - } - - mceInstance.remove(); - } - } - - if ( window.quicktags ) { - qtInstance = window.QTags.getInstance( id ); - - if ( qtInstance ) { - qtInstance.remove(); - } - } - - if ( $wrap.length ) { - $wrap.after( $( '#' + id ) ); - $wrap.remove(); - } - }; - - /** - * Get the editor content. - * - * Intended for use with editors that were initialized with wp.editor.initialize(). - * - * @since 4.8.0 - * - * @param {string} id The HTML id of the editor textarea. - * @return The editor content. - */ - wp.editor.getContent = function( id ) { - var editor; - - if ( ! $ || ! id ) { - return; - } - - if ( window.tinymce ) { - editor = window.tinymce.get( id ); - - if ( editor && ! editor.isHidden() ) { - editor.save(); - } - } - - return $( '#' + id ).val(); - }; - -}( window.jQuery, window.wp )); diff --git a/srcs/wordpress/wp-admin/js/editor.min.js b/srcs/wordpress/wp-admin/js/editor.min.js deleted file mode 100644 index 8664434..0000000 --- a/srcs/wordpress/wp-admin/js/editor.min.js +++ /dev/null @@ -1 +0,0 @@ -window.wp=window.wp||{},function(f,m){m.editor=m.editor||{},window.switchEditors=new function(){var s,d,n={};function e(){!s&&window.tinymce&&(s=window.tinymce,(d=s.$)(document).on("click",function(e){var t=d(e.target);t.hasClass("wp-switch-editor")&&r(t.attr("data-wp-editor-id"),t.hasClass("switch-tmce")?"tmce":"html")}))}function u(e){var t=d(".mce-toolbar-grp",e.getContainer())[0],n=t&&t.clientHeight;return n&&10<n&&n<200?parseInt(n,10):30}function r(e,t){e=e||"content",t=t||"toggle";var n,r,i=s.get(e),a=d("#wp-"+e+"-wrap"),o=d("#"+e),c=o[0];if("toggle"===t&&(t=i&&!i.isHidden()?"html":"tmce"),"tmce"===t||"tinymce"===t){if(i&&!i.isHidden())return!1;void 0!==window.QTags&&window.QTags.closeAllTags(e),n=parseInt(c.style.height,10)||0;(i?i.getParam("wp_keep_scroll_position"):window.tinyMCEPreInit.mceInit[e]&&window.tinyMCEPreInit.mceInit[e].wp_keep_scroll_position)&&function(e){if(!e||!e.length)return;var t=e[0],n=function(e,t){var n=t.cursorStart,r=t.cursorEnd,i=l(e,n);i&&(n=-1!==["area","base","br","col","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"].indexOf(i.tagType)?i.ltPos:i.gtPos);var a=l(e,r);a&&(r=a.gtPos);var o=g(e,n);o&&!o.showAsPlainText&&(n=o.urlAtStartOfContent?o.endIndex:o.startIndex);var c=g(e,r);c&&!c.showAsPlainText&&(r=c.urlAtEndOfContent?c.startIndex:c.endIndex);return{cursorStart:n,cursorEnd:r}}(t.value,{cursorStart:t.selectionStart,cursorEnd:t.selectionEnd}),r=n.cursorStart,i=n.cursorEnd,a=r!==i?"range":"single",o=null,c=b(d,"").attr("data-mce-type","bookmark");if("range"==a){var p=t.value.slice(r,i),s=c.clone().addClass("mce_SELRES_end");o=[p,s[0].outerHTML].join("")}t.value=[t.value.slice(0,r),c.clone().addClass("mce_SELRES_start")[0].outerHTML,o,t.value.slice(i)].join("")}(o),i?(i.show(),!s.Env.iOS&&n&&50<(n=n-u(i)+14)&&n<5e3&&i.theme.resizeTo(null,n),i.getParam("wp_keep_scroll_position")&&w(i)):s.init(window.tinyMCEPreInit.mceInit[e]),a.removeClass("html-active").addClass("tmce-active"),o.attr("aria-hidden",!0),window.setUserSetting("editor","tinymce")}else if("html"===t){if(i&&i.isHidden())return!1;if(i){s.Env.iOS||(n=(r=i.iframeElement)?parseInt(r.style.height,10):0)&&50<(n=n+u(i)-14)&&n<5e3&&(c.style.height=n+"px");var p=null;i.getParam("wp_keep_scroll_position")&&(p=function(e){var t=e.getWin().getSelection();if(!t||t.rangeCount<1)return;var n="SELRES_"+Math.random(),r=b(e.$,n),i=r.clone().addClass("mce_SELRES_start"),a=r.clone().addClass("mce_SELRES_end"),o=t.getRangeAt(0),c=o.startContainer,p=o.startOffset,s=o.cloneRange();0<e.$(c).parents(".mce-offscreen-selection").length?(c=e.$("[data-mce-selected]")[0],i.attr("data-mce-object-selection","true"),a.attr("data-mce-object-selection","true"),e.$(c).before(i[0]),e.$(c).after(a[0])):(s.collapse(!1),s.insertNode(a[0]),s.setStart(c,p),s.collapse(!0),s.insertNode(i[0]),o.setStartAfter(i[0]),o.setEndBefore(a[0]),t.removeAllRanges(),t.addRange(o));e.on("GetContent",x);var d=E(e.getContent());e.off("GetContent",x),i.remove(),a.remove();var l=new RegExp('<span[^>]*\\s*class="mce_SELRES_start"[^>]+>\\s*'+n+"[^<]*<\\/span>(\\s*)"),g=new RegExp('(\\s*)<span[^>]*\\s*class="mce_SELRES_end"[^>]+>\\s*'+n+"[^<]*<\\/span>"),u=d.match(l),w=d.match(g);if(!u)return null;var f=u.index,m=u[0].length,h=null;if(w){-1!==u[0].indexOf("data-mce-object-selection")&&(m-=u[1].length);var v=w.index;-1!==w[0].indexOf("data-mce-object-selection")&&(v-=w[1].length),h=v-m}return{start:f,end:h}}(i)),i.hide(),p&&function(e,t){if(!t)return;var n=e.getElement(),r=t.start,i=t.end||t.start;n.focus&&setTimeout(function(){n.setSelectionRange(r,i),n.blur&&n.blur(),n.focus()},100)}(i,p)}else o.css({display:"",visibility:""});a.removeClass("tmce-active").addClass("html-active"),o.attr("aria-hidden",!1),window.setUserSetting("editor","html")}}function l(e,t){var n=e.lastIndexOf("<",t-1);if(e.lastIndexOf(">",t)<n||">"===e.substr(t,1)){var r=e.substr(n),i=r.match(/<\s*(\/)?(\w+|\!-{2}.*-{2})/);if(!i)return null;var a=i[2];return{ltPos:n,gtPos:n+r.indexOf(">")+1,tagType:a,isClosingTag:!!i[1]}}return null}function g(e,t){for(var n=function(e){var t,n=function(e){var t=e.match(/\[+([\w_-])+/g),n=[];if(t)for(var r=0;r<t.length;r++){var i=t[r].replace(/^\[+/g,"");-1===n.indexOf(i)&&n.push(i)}return n}(e);if(0===n.length)return[];var r,i=m.shortcode.regexp(n.join("|")),a=[];for(;r=i.exec(e);){var o="["===r[1];t={shortcodeName:r[2],showAsPlainText:o,startIndex:r.index,endIndex:r.index+r[0].length,length:r[0].length},a.push(t)}var c=new RegExp('(^|[\\n\\r][\\n\\r]|<p>)(https?:\\/\\/[^s"]+?)(<\\/p>s*|[\\n\\r][\\n\\r]|$)',"gi");for(;r=c.exec(e);)t={shortcodeName:"url",showAsPlainText:!1,startIndex:r.index,endIndex:r.index+r[0].length,length:r[0].length,urlAtStartOfContent:""===r[1],urlAtEndOfContent:""===r[3]},a.push(t);return a}(e),r=0;r<n.length;r++){var i=n[r];if(t>=i.startIndex&&t<=i.endIndex)return i}}function b(e,t){return e("<span>").css({display:"inline-block",width:0,overflow:"hidden","line-height":0}).html(t||"")}function w(e){var t=e.$(".mce_SELRES_start").attr("data-mce-bogus",1),n=e.$(".mce_SELRES_end").attr("data-mce-bogus",1);if(t.length)if(e.focus(),n.length){var r=e.getDoc().createRange();r.setStartAfter(t[0]),r.setEndBefore(n[0]),e.selection.setRng(r)}else e.selection.select(t[0]);e.getParam("wp_keep_scroll_position")&&function(e,t){var n,r=e.$(t).offset().top,i=e.$(e.getContentAreaContainer()).offset().top,a=u(e),o=f("#wp-content-editor-tools"),c=0,p=0;o.length&&(c=o.height(),p=o.offset().top);var s,d=window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight,l=i+r,g=d-(c+a);if(l<g)return;s=e.settings.wp_autoresize_on?(n=f("html,body"),Math.max(l-g/2,p-c)):(n=f(e.contentDocument).find("html,body"),r);n.animate({scrollTop:parseInt(s,10)},100)}(e,t),i(t),i(n),e.save()}function i(e){var t=e.parent();e.remove(),!t.is("p")||t.children().length||t.text()||t.remove()}function x(e){e.content=e.content.replace(/<p>(?:<br ?\/?>|\u00a0|\uFEFF| )*<\/p>/g,"<p> </p>")}function E(e){var t="blockquote|ul|ol|li|dl|dt|dd|table|thead|tbody|tfoot|tr|th|td|h[1-6]|fieldset|figure",n=t+"|div|p",r=t+"|pre",i=!1,a=!1,o=[];return e?(-1===e.indexOf("<script")&&-1===e.indexOf("<style")||(e=e.replace(/<(script|style)[^>]*>[\s\S]*?<\/\1>/g,function(e){return o.push(e),"<wp-preserve>"})),-1!==e.indexOf("<pre")&&(i=!0,e=e.replace(/<pre[^>]*>[\s\S]+?<\/pre>/g,function(e){return(e=(e=e.replace(/<br ?\/?>(\r\n|\n)?/g,"<wp-line-break>")).replace(/<\/?p( [^>]*)?>(\r\n|\n)?/g,"<wp-line-break>")).replace(/\r?\n/g,"<wp-line-break>")})),-1!==e.indexOf("[caption")&&(a=!0,e=e.replace(/\[caption[\s\S]+?\[\/caption\]/g,function(e){return e.replace(/<br([^>]*)>/g,"<wp-temp-br$1>").replace(/[\r\n\t]+/,"")})),-1!==(e=(e=(e=(e=(e=(e=(e=(e=(e=(e=(e=(e=(e=(e=(e=e.replace(new RegExp("\\s*</("+n+")>\\s*","g"),"</$1>\n")).replace(new RegExp("\\s*<((?:"+n+")(?: [^>]*)?)>","g"),"\n<$1>")).replace(/(<p [^>]+>.*?)<\/p>/g,"$1</p#>")).replace(/<div( [^>]*)?>\s*<p>/gi,"<div$1>\n\n")).replace(/\s*<p>/gi,"")).replace(/\s*<\/p>\s*/gi,"\n\n")).replace(/\n[\s\u00a0]+\n/g,"\n\n")).replace(/(\s*)<br ?\/?>\s*/gi,function(e,t){return t&&-1!==t.indexOf("\n")?"\n\n":"\n"})).replace(/\s*<div/g,"\n<div")).replace(/<\/div>\s*/g,"</div>\n")).replace(/\s*\[caption([^\[]+)\[\/caption\]\s*/gi,"\n\n[caption$1[/caption]\n\n")).replace(/caption\]\n\n+\[caption/g,"caption]\n\n[caption")).replace(new RegExp("\\s*<((?:"+r+")(?: [^>]*)?)\\s*>","g"),"\n<$1>")).replace(new RegExp("\\s*</("+r+")>\\s*","g"),"</$1>\n")).replace(/<((li|dt|dd)[^>]*)>/g," \t<$1>")).indexOf("<option")&&(e=(e=e.replace(/\s*<option/g,"\n<option")).replace(/\s*<\/select>/g,"\n</select>")),-1!==e.indexOf("<hr")&&(e=e.replace(/\s*<hr( [^>]*)?>\s*/g,"\n\n<hr$1>\n\n")),-1!==e.indexOf("<object")&&(e=e.replace(/<object[\s\S]+?<\/object>/g,function(e){return e.replace(/[\r\n]+/g,"")})),e=(e=(e=(e=e.replace(/<\/p#>/g,"</p>\n")).replace(/\s*(<p [^>]+>[\s\S]*?<\/p>)/g,"\n$1")).replace(/^\s+/,"")).replace(/[\s\u00a0]+$/,""),i&&(e=e.replace(/<wp-line-break>/g,"\n")),a&&(e=e.replace(/<wp-temp-br([^>]*)>/g,"<br$1>")),o.length&&(e=e.replace(/<wp-preserve>/g,function(){return o.shift()})),e):""}function a(e){var t=!1,n=!1,r="table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|form|map|area|blockquote|address|math|style|p|h[1-6]|hr|fieldset|legend|section|article|aside|hgroup|header|footer|nav|figure|figcaption|details|menu|summary";return-1!==(e=e.replace(/\r\n|\r/g,"\n")).indexOf("<object")&&(e=e.replace(/<object[\s\S]+?<\/object>/g,function(e){return e.replace(/\n+/g,"")})),-1===(e=e.replace(/<[^<>]+>/g,function(e){return e.replace(/[\n\t ]+/g," ")})).indexOf("<pre")&&-1===e.indexOf("<script")||(t=!0,e=e.replace(/<(pre|script)[^>]*>[\s\S]*?<\/\1>/g,function(e){return e.replace(/\n/g,"<wp-line-break>")})),-1!==e.indexOf("<figcaption")&&(e=(e=e.replace(/\s*(<figcaption[^>]*>)/g,"$1")).replace(/<\/figcaption>\s*/g,"</figcaption>")),-1!==e.indexOf("[caption")&&(n=!0,e=e.replace(/\[caption[\s\S]+?\[\/caption\]/g,function(e){return(e=(e=e.replace(/<br([^>]*)>/g,"<wp-temp-br$1>")).replace(/<[^<>]+>/g,function(e){return e.replace(/[\n\t ]+/," ")})).replace(/\s*\n\s*/g,"<wp-temp-br />")})),e=(e=(e=(e=(e=(e=(e=(e=(e=(e=(e=(e=(e=(e=(e=(e=(e=(e=(e=(e=(e=(e+="\n\n").replace(/<br \/>\s*<br \/>/gi,"\n\n")).replace(new RegExp("(<(?:"+r+")(?: [^>]*)?>)","gi"),"\n\n$1")).replace(new RegExp("(</(?:"+r+")>)","gi"),"$1\n\n")).replace(/<hr( [^>]*)?>/gi,"<hr$1>\n\n")).replace(/\s*<option/gi,"<option")).replace(/<\/option>\s*/gi,"</option>")).replace(/\n\s*\n+/g,"\n\n")).replace(/([\s\S]+?)\n\n/g,"<p>$1</p>\n")).replace(/<p>\s*?<\/p>/gi,"")).replace(new RegExp("<p>\\s*(</?(?:"+r+")(?: [^>]*)?>)\\s*</p>","gi"),"$1")).replace(/<p>(<li.+?)<\/p>/gi,"$1")).replace(/<p>\s*<blockquote([^>]*)>/gi,"<blockquote$1><p>")).replace(/<\/blockquote>\s*<\/p>/gi,"</p></blockquote>")).replace(new RegExp("<p>\\s*(</?(?:"+r+")(?: [^>]*)?>)","gi"),"$1")).replace(new RegExp("(</?(?:"+r+")(?: [^>]*)?>)\\s*</p>","gi"),"$1")).replace(/(<br[^>]*>)\s*\n/gi,"$1")).replace(/\s*\n/g,"<br />\n")).replace(new RegExp("(</?(?:"+r+")[^>]*>)\\s*<br />","gi"),"$1")).replace(/<br \/>(\s*<\/?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)>)/gi,"$1")).replace(/(?:<p>|<br ?\/?>)*\s*\[caption([^\[]+)\[\/caption\]\s*(?:<\/p>|<br ?\/?>)*/gi,"[caption$1[/caption]")).replace(/(<(?:div|th|td|form|fieldset|dd)[^>]*>)(.*?)<\/p>/g,function(e,t,n){return n.match(/<p( [^>]*)?>/)?e:t+"<p>"+n+"</p>"}),t&&(e=e.replace(/<wp-line-break>/g,"\n")),n&&(e=e.replace(/<wp-temp-br([^>]*)>/g,"<br$1>")),e}function t(e){var t={o:n,data:e,unfiltered:e};return f&&f("body").trigger("beforePreWpautop",[t]),t.data=E(t.data),f&&f("body").trigger("afterPreWpautop",[t]),t.data}function o(e){var t={o:n,data:e,unfiltered:e};return f&&f("body").trigger("beforeWpautop",[t]),t.data=a(t.data),f&&f("body").trigger("afterWpautop",[t]),t.data}return f(document).on("tinymce-editor-init.keep-scroll-position",function(e,t){t.$(".mce_SELRES_start").length&&w(t)}),f?f(document).ready(e):document.addEventListener?(document.addEventListener("DOMContentLoaded",e,!1),window.addEventListener("load",e,!1)):window.attachEvent&&(window.attachEvent("onload",e),document.attachEvent("onreadystatechange",function(){"complete"===document.readyState&&e()})),m.editor.autop=o,m.editor.removep=t,n={go:r,wpautop:o,pre_wpautop:t,_wp_Autop:a,_wp_Nop:E}},m.editor.initialize=function(e,t){var n,r;if(f&&e&&m.editor.getDefaultSettings){if(r=m.editor.getDefaultSettings(),(t=t||{tinymce:!0}).tinymce&&t.quicktags){var i=f("#"+e),a=f("<div>").attr({class:"wp-core-ui wp-editor-wrap tmce-active",id:"wp-"+e+"-wrap"}),o=f('<div class="wp-editor-container">'),c=f("<button>").attr({type:"button","data-wp-editor-id":e}),p=f('<div class="wp-editor-tools">');if(t.mediaButtons){var s="Add Media";window._wpMediaViewsL10n&&window._wpMediaViewsL10n.addMedia&&(s=window._wpMediaViewsL10n.addMedia);var d=f('<button type="button" class="button insert-media add_media">');d.append('<span class="wp-media-buttons-icon"></span>'),d.append(document.createTextNode(" "+s)),d.data("editor",e),p.append(f('<div class="wp-media-buttons">').append(d))}a.append(p.append(f('<div class="wp-editor-tabs">').append(c.clone().attr({id:e+"-tmce",class:"wp-switch-editor switch-tmce"}).text(window.tinymce.translate("Visual"))).append(c.attr({id:e+"-html",class:"wp-switch-editor switch-html"}).text(window.tinymce.translate("Text")))).append(o)),i.after(a),o.append(i)}window.tinymce&&t.tinymce&&("object"!=typeof t.tinymce&&(t.tinymce={}),(n=f.extend({},r.tinymce,t.tinymce)).selector="#"+e,f(document).trigger("wp-before-tinymce-init",n),window.tinymce.init(n),window.wpActiveEditor||(window.wpActiveEditor=e)),window.quicktags&&t.quicktags&&("object"!=typeof t.quicktags&&(t.quicktags={}),(n=f.extend({},r.quicktags,t.quicktags)).id=e,f(document).trigger("wp-before-quicktags-init",n),window.quicktags(n),window.wpActiveEditor||(window.wpActiveEditor=n.id))}},m.editor.remove=function(e){var t,n,r=f("#wp-"+e+"-wrap");window.tinymce&&(t=window.tinymce.get(e))&&(t.isHidden()||t.save(),t.remove()),window.quicktags&&(n=window.QTags.getInstance(e))&&n.remove(),r.length&&(r.after(f("#"+e)),r.remove())},m.editor.getContent=function(e){var t;if(f&&e)return window.tinymce&&(t=window.tinymce.get(e))&&!t.isHidden()&&t.save(),f("#"+e).val()}}(window.jQuery,window.wp);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/farbtastic.js b/srcs/wordpress/wp-admin/js/farbtastic.js deleted file mode 100644 index 5404fb6..0000000 --- a/srcs/wordpress/wp-admin/js/farbtastic.js +++ /dev/null @@ -1,276 +0,0 @@ -/*! - * Farbtastic: jQuery color picker plug-in v1.3u - * - * Licensed under the GPL license: - * http://www.gnu.org/licenses/gpl.html - */ -(function($) { - -$.fn.farbtastic = function (options) { - $.farbtastic(this, options); - return this; -}; - -$.farbtastic = function (container, callback) { - var container = $(container).get(0); - return container.farbtastic || (container.farbtastic = new $._farbtastic(container, callback)); -}; - -$._farbtastic = function (container, callback) { - // Store farbtastic object - var fb = this; - - // Insert markup - $(container).html('<div class="farbtastic"><div class="color"></div><div class="wheel"></div><div class="overlay"></div><div class="h-marker marker"></div><div class="sl-marker marker"></div></div>'); - var e = $('.farbtastic', container); - fb.wheel = $('.wheel', container).get(0); - // Dimensions - fb.radius = 84; - fb.square = 100; - fb.width = 194; - - // Fix background PNGs in IE6 - if (navigator.appVersion.match(/MSIE [0-6]\./)) { - $('*', e).each(function () { - if (this.currentStyle.backgroundImage != 'none') { - var image = this.currentStyle.backgroundImage; - image = this.currentStyle.backgroundImage.substring(5, image.length - 2); - $(this).css({ - 'backgroundImage': 'none', - 'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')" - }); - } - }); - } - - /** - * Link to the given element(s) or callback. - */ - fb.linkTo = function (callback) { - // Unbind previous nodes - if (typeof fb.callback == 'object') { - $(fb.callback).unbind('keyup', fb.updateValue); - } - - // Reset color - fb.color = null; - - // Bind callback or elements - if (typeof callback == 'function') { - fb.callback = callback; - } - else if (typeof callback == 'object' || typeof callback == 'string') { - fb.callback = $(callback); - fb.callback.bind('keyup', fb.updateValue); - if (fb.callback.get(0).value) { - fb.setColor(fb.callback.get(0).value); - } - } - return this; - }; - fb.updateValue = function (event) { - if (this.value && this.value != fb.color) { - fb.setColor(this.value); - } - }; - - /** - * Change color with HTML syntax #123456 - */ - fb.setColor = function (color) { - var unpack = fb.unpack(color); - if (fb.color != color && unpack) { - fb.color = color; - fb.rgb = unpack; - fb.hsl = fb.RGBToHSL(fb.rgb); - fb.updateDisplay(); - } - return this; - }; - - /** - * Change color with HSL triplet [0..1, 0..1, 0..1] - */ - fb.setHSL = function (hsl) { - fb.hsl = hsl; - fb.rgb = fb.HSLToRGB(hsl); - fb.color = fb.pack(fb.rgb); - fb.updateDisplay(); - return this; - }; - - ///////////////////////////////////////////////////// - - /** - * Retrieve the coordinates of the given event relative to the center - * of the widget. - */ - fb.widgetCoords = function (event) { - var offset = $(fb.wheel).offset(); - return { x: (event.pageX - offset.left) - fb.width / 2, y: (event.pageY - offset.top) - fb.width / 2 }; - }; - - /** - * Mousedown handler - */ - fb.mousedown = function (event) { - // Capture mouse - if (!document.dragging) { - $(document).bind('mousemove', fb.mousemove).bind('mouseup', fb.mouseup); - document.dragging = true; - } - - // Check which area is being dragged - var pos = fb.widgetCoords(event); - fb.circleDrag = Math.max(Math.abs(pos.x), Math.abs(pos.y)) * 2 > fb.square; - - // Process - fb.mousemove(event); - return false; - }; - - /** - * Mousemove handler - */ - fb.mousemove = function (event) { - // Get coordinates relative to color picker center - var pos = fb.widgetCoords(event); - - // Set new HSL parameters - if (fb.circleDrag) { - var hue = Math.atan2(pos.x, -pos.y) / 6.28; - if (hue < 0) hue += 1; - fb.setHSL([hue, fb.hsl[1], fb.hsl[2]]); - } - else { - var sat = Math.max(0, Math.min(1, -(pos.x / fb.square) + .5)); - var lum = Math.max(0, Math.min(1, -(pos.y / fb.square) + .5)); - fb.setHSL([fb.hsl[0], sat, lum]); - } - return false; - }; - - /** - * Mouseup handler - */ - fb.mouseup = function () { - // Uncapture mouse - $(document).unbind('mousemove', fb.mousemove); - $(document).unbind('mouseup', fb.mouseup); - document.dragging = false; - }; - - /** - * Update the markers and styles - */ - fb.updateDisplay = function () { - // Markers - var angle = fb.hsl[0] * 6.28; - $('.h-marker', e).css({ - left: Math.round(Math.sin(angle) * fb.radius + fb.width / 2) + 'px', - top: Math.round(-Math.cos(angle) * fb.radius + fb.width / 2) + 'px' - }); - - $('.sl-marker', e).css({ - left: Math.round(fb.square * (.5 - fb.hsl[1]) + fb.width / 2) + 'px', - top: Math.round(fb.square * (.5 - fb.hsl[2]) + fb.width / 2) + 'px' - }); - - // Saturation/Luminance gradient - $('.color', e).css('backgroundColor', fb.pack(fb.HSLToRGB([fb.hsl[0], 1, 0.5]))); - - // Linked elements or callback - if (typeof fb.callback == 'object') { - // Set background/foreground color - $(fb.callback).css({ - backgroundColor: fb.color, - color: fb.hsl[2] > 0.5 ? '#000' : '#fff' - }); - - // Change linked value - $(fb.callback).each(function() { - if (this.value && this.value != fb.color) { - this.value = fb.color; - } - }); - } - else if (typeof fb.callback == 'function') { - fb.callback.call(fb, fb.color); - } - }; - - /* Various color utility functions */ - fb.pack = function (rgb) { - var r = Math.round(rgb[0] * 255); - var g = Math.round(rgb[1] * 255); - var b = Math.round(rgb[2] * 255); - return '#' + (r < 16 ? '0' : '') + r.toString(16) + - (g < 16 ? '0' : '') + g.toString(16) + - (b < 16 ? '0' : '') + b.toString(16); - }; - - fb.unpack = function (color) { - if (color.length == 7) { - return [parseInt('0x' + color.substring(1, 3)) / 255, - parseInt('0x' + color.substring(3, 5)) / 255, - parseInt('0x' + color.substring(5, 7)) / 255]; - } - else if (color.length == 4) { - return [parseInt('0x' + color.substring(1, 2)) / 15, - parseInt('0x' + color.substring(2, 3)) / 15, - parseInt('0x' + color.substring(3, 4)) / 15]; - } - }; - - fb.HSLToRGB = function (hsl) { - var m1, m2, r, g, b; - var h = hsl[0], s = hsl[1], l = hsl[2]; - m2 = (l <= 0.5) ? l * (s + 1) : l + s - l*s; - m1 = l * 2 - m2; - return [this.hueToRGB(m1, m2, h+0.33333), - this.hueToRGB(m1, m2, h), - this.hueToRGB(m1, m2, h-0.33333)]; - }; - - fb.hueToRGB = function (m1, m2, h) { - h = (h < 0) ? h + 1 : ((h > 1) ? h - 1 : h); - if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; - if (h * 2 < 1) return m2; - if (h * 3 < 2) return m1 + (m2 - m1) * (0.66666 - h) * 6; - return m1; - }; - - fb.RGBToHSL = function (rgb) { - var min, max, delta, h, s, l; - var r = rgb[0], g = rgb[1], b = rgb[2]; - min = Math.min(r, Math.min(g, b)); - max = Math.max(r, Math.max(g, b)); - delta = max - min; - l = (min + max) / 2; - s = 0; - if (l > 0 && l < 1) { - s = delta / (l < 0.5 ? (2 * l) : (2 - 2 * l)); - } - h = 0; - if (delta > 0) { - if (max == r && max != g) h += (g - b) / delta; - if (max == g && max != b) h += (2 + (b - r) / delta); - if (max == b && max != r) h += (4 + (r - g) / delta); - h /= 6; - } - return [h, s, l]; - }; - - // Install mousedown handler (the others are set on the document on-demand) - $('*', e).mousedown(fb.mousedown); - - // Init color - fb.setColor('#000000'); - - // Set linked elements/callback - if (callback) { - fb.linkTo(callback); - } -}; - -})(jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/gallery.js b/srcs/wordpress/wp-admin/js/gallery.js deleted file mode 100644 index 36cb086..0000000 --- a/srcs/wordpress/wp-admin/js/gallery.js +++ /dev/null @@ -1,241 +0,0 @@ -/** - * @output wp-admin/js/gallery.js - */ - -/* global unescape, getUserSetting, setUserSetting, wpgallery, tinymce */ - -jQuery(document).ready(function($) { - var gallerySortable, gallerySortableInit, sortIt, clearAll, w, desc = false; - - gallerySortableInit = function() { - gallerySortable = $('#media-items').sortable( { - items: 'div.media-item', - placeholder: 'sorthelper', - axis: 'y', - distance: 2, - handle: 'div.filename', - stop: function() { - // When an update has occurred, adjust the order for each item - var all = $('#media-items').sortable('toArray'), len = all.length; - $.each(all, function(i, id) { - var order = desc ? (len - i) : (1 + i); - $('#' + id + ' .menu_order input').val(order); - }); - } - } ); - }; - - sortIt = function() { - var all = $('.menu_order_input'), len = all.length; - all.each(function(i){ - var order = desc ? (len - i) : (1 + i); - $(this).val(order); - }); - }; - - clearAll = function(c) { - c = c || 0; - $('.menu_order_input').each( function() { - if ( this.value === '0' || c ) { - this.value = ''; - } - }); - }; - - $('#asc').click( function( e ) { - e.preventDefault(); - desc = false; - sortIt(); - }); - $('#desc').click( function( e ) { - e.preventDefault(); - desc = true; - sortIt(); - }); - $('#clear').click( function( e ) { - e.preventDefault(); - clearAll(1); - }); - $('#showall').click( function( e ) { - e.preventDefault(); - $('#sort-buttons span a').toggle(); - $('a.describe-toggle-on').hide(); - $('a.describe-toggle-off, table.slidetoggle').show(); - $('img.pinkynail').toggle(false); - }); - $('#hideall').click( function( e ) { - e.preventDefault(); - $('#sort-buttons span a').toggle(); - $('a.describe-toggle-on').show(); - $('a.describe-toggle-off, table.slidetoggle').hide(); - $('img.pinkynail').toggle(true); - }); - - // initialize sortable - gallerySortableInit(); - clearAll(); - - if ( $('#media-items>*').length > 1 ) { - w = wpgallery.getWin(); - - $('#save-all, #gallery-settings').show(); - if ( typeof w.tinyMCE !== 'undefined' && w.tinyMCE.activeEditor && ! w.tinyMCE.activeEditor.isHidden() ) { - wpgallery.mcemode = true; - wpgallery.init(); - } else { - $('#insert-gallery').show(); - } - } -}); - -jQuery(window).unload( function () { window.tinymce = window.tinyMCE = window.wpgallery = null; } ); // Cleanup - -/* gallery settings */ -window.tinymce = null; - -window.wpgallery = { - mcemode : false, - editor : {}, - dom : {}, - is_update : false, - el : {}, - - I : function(e) { - return document.getElementById(e); - }, - - init: function() { - var t = this, li, q, i, it, w = t.getWin(); - - if ( ! t.mcemode ) { - return; - } - - li = ('' + document.location.search).replace(/^\?/, '').split('&'); - q = {}; - for (i=0; i<li.length; i++) { - it = li[i].split('='); - q[unescape(it[0])] = unescape(it[1]); - } - - if ( q.mce_rdomain ) { - document.domain = q.mce_rdomain; - } - - // Find window & API - window.tinymce = w.tinymce; - window.tinyMCE = w.tinyMCE; - t.editor = tinymce.EditorManager.activeEditor; - - t.setup(); - }, - - getWin : function() { - return window.dialogArguments || opener || parent || top; - }, - - setup : function() { - var t = this, a, ed = t.editor, g, columns, link, order, orderby; - if ( ! t.mcemode ) { - return; - } - - t.el = ed.selection.getNode(); - - if ( t.el.nodeName !== 'IMG' || ! ed.dom.hasClass(t.el, 'wpGallery') ) { - if ( ( g = ed.dom.select('img.wpGallery') ) && g[0] ) { - t.el = g[0]; - } else { - if ( getUserSetting('galfile') === '1' ) { - t.I('linkto-file').checked = 'checked'; - } - if ( getUserSetting('galdesc') === '1' ) { - t.I('order-desc').checked = 'checked'; - } - if ( getUserSetting('galcols') ) { - t.I('columns').value = getUserSetting('galcols'); - } - if ( getUserSetting('galord') ) { - t.I('orderby').value = getUserSetting('galord'); - } - jQuery('#insert-gallery').show(); - return; - } - } - - a = ed.dom.getAttrib(t.el, 'title'); - a = ed.dom.decode(a); - - if ( a ) { - jQuery('#update-gallery').show(); - t.is_update = true; - - columns = a.match(/columns=['"]([0-9]+)['"]/); - link = a.match(/link=['"]([^'"]+)['"]/i); - order = a.match(/order=['"]([^'"]+)['"]/i); - orderby = a.match(/orderby=['"]([^'"]+)['"]/i); - - if ( link && link[1] ) { - t.I('linkto-file').checked = 'checked'; - } - if ( order && order[1] ) { - t.I('order-desc').checked = 'checked'; - } - if ( columns && columns[1] ) { - t.I('columns').value = '' + columns[1]; - } - if ( orderby && orderby[1] ) { - t.I('orderby').value = orderby[1]; - } - } else { - jQuery('#insert-gallery').show(); - } - }, - - update : function() { - var t = this, ed = t.editor, all = '', s; - - if ( ! t.mcemode || ! t.is_update ) { - s = '[gallery' + t.getSettings() + ']'; - t.getWin().send_to_editor(s); - return; - } - - if ( t.el.nodeName !== 'IMG' ) { - return; - } - - all = ed.dom.decode( ed.dom.getAttrib( t.el, 'title' ) ); - all = all.replace(/\s*(order|link|columns|orderby)=['"]([^'"]+)['"]/gi, ''); - all += t.getSettings(); - - ed.dom.setAttrib(t.el, 'title', all); - t.getWin().tb_remove(); - }, - - getSettings : function() { - var I = this.I, s = ''; - - if ( I('linkto-file').checked ) { - s += ' link="file"'; - setUserSetting('galfile', '1'); - } - - if ( I('order-desc').checked ) { - s += ' order="DESC"'; - setUserSetting('galdesc', '1'); - } - - if ( I('columns').value !== 3 ) { - s += ' columns="' + I('columns').value + '"'; - setUserSetting('galcols', I('columns').value); - } - - if ( I('orderby').value !== 'menu_order' ) { - s += ' orderby="' + I('orderby').value + '"'; - setUserSetting('galord', I('orderby').value); - } - - return s; - } -}; diff --git a/srcs/wordpress/wp-admin/js/gallery.min.js b/srcs/wordpress/wp-admin/js/gallery.min.js deleted file mode 100644 index 96de02f..0000000 --- a/srcs/wordpress/wp-admin/js/gallery.min.js +++ /dev/null @@ -1 +0,0 @@ -jQuery(document).ready(function(l){var e,t,i,n,o=!1;e=function(){l("#media-items").sortable({items:"div.media-item",placeholder:"sorthelper",axis:"y",distance:2,handle:"div.filename",stop:function(){var e=l("#media-items").sortable("toArray"),n=e.length;l.each(e,function(e,t){var i=o?n-e:1+e;l("#"+t+" .menu_order input").val(i)})}})},t=function(){var e=l(".menu_order_input"),i=e.length;e.each(function(e){var t=o?i-e:1+e;l(this).val(t)})},i=function(e){e=e||0,l(".menu_order_input").each(function(){"0"!==this.value&&!e||(this.value="")})},l("#asc").click(function(e){e.preventDefault(),o=!1,t()}),l("#desc").click(function(e){e.preventDefault(),o=!0,t()}),l("#clear").click(function(e){e.preventDefault(),i(1)}),l("#showall").click(function(e){e.preventDefault(),l("#sort-buttons span a").toggle(),l("a.describe-toggle-on").hide(),l("a.describe-toggle-off, table.slidetoggle").show(),l("img.pinkynail").toggle(!1)}),l("#hideall").click(function(e){e.preventDefault(),l("#sort-buttons span a").toggle(),l("a.describe-toggle-on").show(),l("a.describe-toggle-off, table.slidetoggle").hide(),l("img.pinkynail").toggle(!0)}),e(),i(),1<l("#media-items>*").length&&(n=wpgallery.getWin(),l("#save-all, #gallery-settings").show(),void 0!==n.tinyMCE&&n.tinyMCE.activeEditor&&!n.tinyMCE.activeEditor.isHidden()?(wpgallery.mcemode=!0,wpgallery.init()):l("#insert-gallery").show())}),jQuery(window).unload(function(){window.tinymce=window.tinyMCE=window.wpgallery=null}),window.tinymce=null,window.wpgallery={mcemode:!1,editor:{},dom:{},is_update:!1,el:{},I:function(e){return document.getElementById(e)},init:function(){var e,t,i,n,l=this,o=l.getWin();if(l.mcemode){for(e=(""+document.location.search).replace(/^\?/,"").split("&"),t={},i=0;i<e.length;i++)n=e[i].split("="),t[unescape(n[0])]=unescape(n[1]);t.mce_rdomain&&(document.domain=t.mce_rdomain),window.tinymce=o.tinymce,window.tinyMCE=o.tinyMCE,l.editor=tinymce.EditorManager.activeEditor,l.setup()}},getWin:function(){return window.dialogArguments||opener||parent||top},setup:function(){var e,t,i,n,l,o,r=this,a=r.editor;if(r.mcemode){if(r.el=a.selection.getNode(),"IMG"!==r.el.nodeName||!a.dom.hasClass(r.el,"wpGallery")){if(!(t=a.dom.select("img.wpGallery"))||!t[0])return"1"===getUserSetting("galfile")&&(r.I("linkto-file").checked="checked"),"1"===getUserSetting("galdesc")&&(r.I("order-desc").checked="checked"),getUserSetting("galcols")&&(r.I("columns").value=getUserSetting("galcols")),getUserSetting("galord")&&(r.I("orderby").value=getUserSetting("galord")),void jQuery("#insert-gallery").show();r.el=t[0]}e=a.dom.getAttrib(r.el,"title"),(e=a.dom.decode(e))?(jQuery("#update-gallery").show(),r.is_update=!0,i=e.match(/columns=['"]([0-9]+)['"]/),n=e.match(/link=['"]([^'"]+)['"]/i),l=e.match(/order=['"]([^'"]+)['"]/i),o=e.match(/orderby=['"]([^'"]+)['"]/i),n&&n[1]&&(r.I("linkto-file").checked="checked"),l&&l[1]&&(r.I("order-desc").checked="checked"),i&&i[1]&&(r.I("columns").value=""+i[1]),o&&o[1]&&(r.I("orderby").value=o[1])):jQuery("#insert-gallery").show()}},update:function(){var e,t=this,i=t.editor,n="";if(!t.mcemode||!t.is_update)return e="[gallery"+t.getSettings()+"]",void t.getWin().send_to_editor(e);"IMG"===t.el.nodeName&&(n=(n=i.dom.decode(i.dom.getAttrib(t.el,"title"))).replace(/\s*(order|link|columns|orderby)=['"]([^'"]+)['"]/gi,""),n+=t.getSettings(),i.dom.setAttrib(t.el,"title",n),t.getWin().tb_remove())},getSettings:function(){var e=this.I,t="";return e("linkto-file").checked&&(t+=' link="file"',setUserSetting("galfile","1")),e("order-desc").checked&&(t+=' order="DESC"',setUserSetting("galdesc","1")),3!==e("columns").value&&(t+=' columns="'+e("columns").value+'"',setUserSetting("galcols",e("columns").value)),"menu_order"!==e("orderby").value&&(t+=' orderby="'+e("orderby").value+'"',setUserSetting("galord",e("orderby").value)),t}};
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/image-edit.js b/srcs/wordpress/wp-admin/js/image-edit.js deleted file mode 100644 index 100f26e..0000000 --- a/srcs/wordpress/wp-admin/js/image-edit.js +++ /dev/null @@ -1,1126 +0,0 @@ -/** - * The functions necessary for editing images. - * - * @since 2.9.0 - * @output wp-admin/js/image-edit.js - */ - - /* global imageEditL10n, ajaxurl, confirm */ - -(function($) { - - /** - * Contains all the methods to initialise and control the image editor. - * - * @namespace imageEdit - */ - var imageEdit = window.imageEdit = { - iasapi : {}, - hold : {}, - postid : '', - _view : false, - - /** - * Handle crop tool clicks. - */ - handleCropToolClick: function( postid, nonce, cropButton ) { - var img = $( '#image-preview-' + postid ), - selection = this.iasapi.getSelection(); - - // Ensure selection is available, otherwise reset to full image. - if ( isNaN( selection.x1 ) ) { - this.setCropSelection( postid, { 'x1': 0, 'y1': 0, 'x2': img.innerWidth(), 'y2': img.innerHeight(), 'width': img.innerWidth(), 'height': img.innerHeight() } ); - selection = this.iasapi.getSelection(); - } - - // If we don't already have a selection, select the entire image. - if ( 0 === selection.x1 && 0 === selection.y1 && 0 === selection.x2 && 0 === selection.y2 ) { - this.iasapi.setSelection( 0, 0, img.innerWidth(), img.innerHeight(), true ); - this.iasapi.setOptions( { show: true } ); - this.iasapi.update(); - } else { - - // Otherwise, perform the crop. - imageEdit.crop( postid, nonce , cropButton ); - } - }, - - /** - * Converts a value to an integer. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} f The float value that should be converted. - * - * @return {number} The integer representation from the float value. - */ - intval : function(f) { - /* - * Bitwise OR operator: one of the obscure ways to truncate floating point figures, - * worth reminding JavaScript doesn't have a distinct "integer" type. - */ - return f | 0; - }, - - /** - * Adds the disabled attribute and class to a single form element or a field set. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {jQuery} el The element that should be modified. - * @param {bool|number} s The state for the element. If set to true - * the element is disabled, - * otherwise the element is enabled. - * The function is sometimes called with a 0 or 1 - * instead of true or false. - * - * @returns {void} - */ - setDisabled : function( el, s ) { - /* - * `el` can be a single form element or a fieldset. Before #28864, the disabled state on - * some text fields was handled targeting $('input', el). Now we need to handle the - * disabled state on buttons too so we can just target `el` regardless if it's a single - * element or a fieldset because when a fieldset is disabled, its descendants are disabled too. - */ - if ( s ) { - el.removeClass( 'disabled' ).prop( 'disabled', false ); - } else { - el.addClass( 'disabled' ).prop( 'disabled', true ); - } - }, - - /** - * Initializes the image editor. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} postid The post id. - * - * @returns {void} - */ - init : function(postid) { - var t = this, old = $('#image-editor-' + t.postid), - x = t.intval( $('#imgedit-x-' + postid).val() ), - y = t.intval( $('#imgedit-y-' + postid).val() ); - - if ( t.postid !== postid && old.length ) { - t.close(t.postid); - } - - t.hold.w = t.hold.ow = x; - t.hold.h = t.hold.oh = y; - t.hold.xy_ratio = x / y; - t.hold.sizer = parseFloat( $('#imgedit-sizer-' + postid).val() ); - t.postid = postid; - $('#imgedit-response-' + postid).empty(); - - $('input[type="text"]', '#imgedit-panel-' + postid).keypress(function(e) { - var k = e.keyCode; - - // Key codes 37 thru 40 are the arrow keys. - if ( 36 < k && k < 41 ) { - $(this).blur(); - } - - // The key code 13 is the enter key. - if ( 13 === k ) { - e.preventDefault(); - e.stopPropagation(); - return false; - } - }); - }, - - /** - * Toggles the wait/load icon in the editor. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} postid The post id. - * @param {number} toggle Is 0 or 1, fades the icon in then 1 and out when 0. - * - * @returns {void} - */ - toggleEditor : function(postid, toggle) { - var wait = $('#imgedit-wait-' + postid); - - if ( toggle ) { - wait.fadeIn( 'fast' ); - } else { - wait.fadeOut('fast'); - } - }, - - /** - * Shows or hides the image edit help box. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {HTMLElement} el The element to create the help window in. - * - * @returns {boolean} Always returns false. - */ - toggleHelp : function(el) { - var $el = $( el ); - $el - .attr( 'aria-expanded', 'false' === $el.attr( 'aria-expanded' ) ? 'true' : 'false' ) - .parents( '.imgedit-group-top' ).toggleClass( 'imgedit-help-toggled' ).find( '.imgedit-help' ).slideToggle( 'fast' ); - - return false; - }, - - /** - * Gets the value from the image edit target. - * - * The image edit target contains the image sizes where the (possible) changes - * have to be applied to. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} postid The post id. - * - * @returns {string} The value from the imagedit-save-target input field when available, - * or 'full' when not available. - */ - getTarget : function(postid) { - return $('input[name="imgedit-target-' + postid + '"]:checked', '#imgedit-save-target-' + postid).val() || 'full'; - }, - - /** - * Recalculates the height or width and keeps the original aspect ratio. - * - * If the original image size is exceeded a red exclamation mark is shown. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} postid The current post id. - * @param {number} x Is 0 when it applies the y-axis - * and 1 when applicable for the x-axis. - * @param {jQuery} el Element. - * - * @returns {void} - */ - scaleChanged : function( postid, x, el ) { - var w = $('#imgedit-scale-width-' + postid), h = $('#imgedit-scale-height-' + postid), - warn = $('#imgedit-scale-warn-' + postid), w1 = '', h1 = ''; - - if ( false === this.validateNumeric( el ) ) { - return; - } - - if ( x ) { - h1 = ( w.val() !== '' ) ? Math.round( w.val() / this.hold.xy_ratio ) : ''; - h.val( h1 ); - } else { - w1 = ( h.val() !== '' ) ? Math.round( h.val() * this.hold.xy_ratio ) : ''; - w.val( w1 ); - } - - if ( ( h1 && h1 > this.hold.oh ) || ( w1 && w1 > this.hold.ow ) ) { - warn.css('visibility', 'visible'); - } else { - warn.css('visibility', 'hidden'); - } - }, - - /** - * Gets the selected aspect ratio. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} postid The post id. - * - * @returns {string} The aspect ratio. - */ - getSelRatio : function(postid) { - var x = this.hold.w, y = this.hold.h, - X = this.intval( $('#imgedit-crop-width-' + postid).val() ), - Y = this.intval( $('#imgedit-crop-height-' + postid).val() ); - - if ( X && Y ) { - return X + ':' + Y; - } - - if ( x && y ) { - return x + ':' + y; - } - - return '1:1'; - }, - - /** - * Removes the last action from the image edit history. - * The history consist of (edit) actions performed on the image. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} postid The post id. - * @param {number} setSize 0 or 1, when 1 the image resets to its original size. - * - * @returns {string} JSON string containing the history or an empty string if no history exists. - */ - filterHistory : function(postid, setSize) { - // Apply undo state to history. - var history = $('#imgedit-history-' + postid).val(), pop, n, o, i, op = []; - - if ( history !== '' ) { - // Read the JSON string with the image edit history. - history = JSON.parse(history); - pop = this.intval( $('#imgedit-undone-' + postid).val() ); - if ( pop > 0 ) { - while ( pop > 0 ) { - history.pop(); - pop--; - } - } - - // Reset size to it's original state. - if ( setSize ) { - if ( !history.length ) { - this.hold.w = this.hold.ow; - this.hold.h = this.hold.oh; - return ''; - } - - // Restore original 'o'. - o = history[history.length - 1]; - - // c = 'crop', r = 'rotate', f = 'flip' - o = o.c || o.r || o.f || false; - - if ( o ) { - // fw = Full image width - this.hold.w = o.fw; - // fh = Full image height - this.hold.h = o.fh; - } - } - - // Filter the last step/action from the history. - for ( n in history ) { - i = history[n]; - if ( i.hasOwnProperty('c') ) { - op[n] = { 'c': { 'x': i.c.x, 'y': i.c.y, 'w': i.c.w, 'h': i.c.h } }; - } else if ( i.hasOwnProperty('r') ) { - op[n] = { 'r': i.r.r }; - } else if ( i.hasOwnProperty('f') ) { - op[n] = { 'f': i.f.f }; - } - } - return JSON.stringify(op); - } - return ''; - }, - /** - * Binds the necessary events to the image. - * - * When the image source is reloaded the image will be reloaded. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} postid The post id. - * @param {string} nonce The nonce to verify the request. - * @param {function} callback Function to execute when the image is loaded. - * - * @returns {void} - */ - refreshEditor : function(postid, nonce, callback) { - var t = this, data, img; - - t.toggleEditor(postid, 1); - data = { - 'action': 'imgedit-preview', - '_ajax_nonce': nonce, - 'postid': postid, - 'history': t.filterHistory(postid, 1), - 'rand': t.intval(Math.random() * 1000000) - }; - - img = $( '<img id="image-preview-' + postid + '" alt="" />' ) - .on( 'load', { history: data.history }, function( event ) { - var max1, max2, - parent = $( '#imgedit-crop-' + postid ), - t = imageEdit, - historyObj; - - // Checks if there already is some image-edit history. - if ( '' !== event.data.history ) { - historyObj = JSON.parse( event.data.history ); - // If last executed action in history is a crop action. - if ( historyObj[historyObj.length - 1].hasOwnProperty( 'c' ) ) { - /* - * A crop action has completed and the crop button gets disabled - * ensure the undo button is enabled. - */ - t.setDisabled( $( '#image-undo-' + postid) , true ); - // Move focus to the undo button to avoid a focus loss. - $( '#image-undo-' + postid ).focus(); - } - } - - parent.empty().append(img); - - // w, h are the new full size dims - max1 = Math.max( t.hold.w, t.hold.h ); - max2 = Math.max( $(img).width(), $(img).height() ); - t.hold.sizer = max1 > max2 ? max2 / max1 : 1; - - t.initCrop(postid, img, parent); - - if ( (typeof callback !== 'undefined') && callback !== null ) { - callback(); - } - - if ( $('#imgedit-history-' + postid).val() && $('#imgedit-undone-' + postid).val() === '0' ) { - $('input.imgedit-submit-btn', '#imgedit-panel-' + postid).removeAttr('disabled'); - } else { - $('input.imgedit-submit-btn', '#imgedit-panel-' + postid).prop('disabled', true); - } - - t.toggleEditor(postid, 0); - }) - .on('error', function() { - $('#imgedit-crop-' + postid).empty().append('<div class="error"><p>' + imageEditL10n.error + '</p></div>'); - t.toggleEditor(postid, 0); - }) - .attr('src', ajaxurl + '?' + $.param(data)); - }, - /** - * Performs an image edit action. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} postid The post id. - * @param {string} nonce The nonce to verify the request. - * @param {string} action The action to perform on the image. - * The possible actions are: "scale" and "restore". - * - * @returns {boolean|void} Executes a post request that refreshes the page - * when the action is performed. - * Returns false if a invalid action is given, - * or when the action cannot be performed. - */ - action : function(postid, nonce, action) { - var t = this, data, w, h, fw, fh; - - if ( t.notsaved(postid) ) { - return false; - } - - data = { - 'action': 'image-editor', - '_ajax_nonce': nonce, - 'postid': postid - }; - - if ( 'scale' === action ) { - w = $('#imgedit-scale-width-' + postid), - h = $('#imgedit-scale-height-' + postid), - fw = t.intval(w.val()), - fh = t.intval(h.val()); - - if ( fw < 1 ) { - w.focus(); - return false; - } else if ( fh < 1 ) { - h.focus(); - return false; - } - - if ( fw === t.hold.ow || fh === t.hold.oh ) { - return false; - } - - data['do'] = 'scale'; - data.fwidth = fw; - data.fheight = fh; - } else if ( 'restore' === action ) { - data['do'] = 'restore'; - } else { - return false; - } - - t.toggleEditor(postid, 1); - $.post(ajaxurl, data, function(r) { - $('#image-editor-' + postid).empty().append(r); - t.toggleEditor(postid, 0); - // refresh the attachment model so that changes propagate - if ( t._view ) { - t._view.refresh(); - } - }); - }, - - /** - * Stores the changes that are made to the image. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} postid The post id to get the image from the database. - * @param {string} nonce The nonce to verify the request. - * - * @returns {boolean|void} If the actions are successfully saved a response message is shown. - * Returns false if there is no image editing history, - * thus there are not edit-actions performed on the image. - */ - save : function(postid, nonce) { - var data, - target = this.getTarget(postid), - history = this.filterHistory(postid, 0), - self = this; - - if ( '' === history ) { - return false; - } - - this.toggleEditor(postid, 1); - data = { - 'action': 'image-editor', - '_ajax_nonce': nonce, - 'postid': postid, - 'history': history, - 'target': target, - 'context': $('#image-edit-context').length ? $('#image-edit-context').val() : null, - 'do': 'save' - }; - // Post the image edit data to the backend. - $.post(ajaxurl, data, function(r) { - // Read the response. - var ret = JSON.parse(r); - - // If a response is returned, close the editor and show an error. - if ( ret.error ) { - $('#imgedit-response-' + postid).html('<div class="error"><p>' + ret.error + '</p></div>'); - imageEdit.close(postid); - return; - } - - if ( ret.fw && ret.fh ) { - $('#media-dims-' + postid).html( ret.fw + ' × ' + ret.fh ); - } - - if ( ret.thumbnail ) { - $('.thumbnail', '#thumbnail-head-' + postid).attr('src', ''+ret.thumbnail); - } - - if ( ret.msg ) { - $('#imgedit-response-' + postid).html('<div class="updated"><p>' + ret.msg + '</p></div>'); - } - - if ( self._view ) { - self._view.save(); - } else { - imageEdit.close(postid); - } - }); - }, - - /** - * Creates the image edit window. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} postid The post id for the image. - * @param {string} nonce The nonce to verify the request. - * @param {object} view The image editor view to be used for the editing. - * - * @returns {void|promise} Either returns void if the button was already activated - * or returns an instance of the image editor, wrapped in a promise. - */ - open : function( postid, nonce, view ) { - this._view = view; - - var dfd, data, elem = $('#image-editor-' + postid), head = $('#media-head-' + postid), - btn = $('#imgedit-open-btn-' + postid), spin = btn.siblings('.spinner'); - - /* - * Instead of disabling the button, which causes a focus loss and makes screen - * readers announce "unavailable", return if the button was already clicked. - */ - if ( btn.hasClass( 'button-activated' ) ) { - return; - } - - spin.addClass( 'is-active' ); - - data = { - 'action': 'image-editor', - '_ajax_nonce': nonce, - 'postid': postid, - 'do': 'open' - }; - - dfd = $.ajax({ - url: ajaxurl, - type: 'post', - data: data, - beforeSend: function() { - btn.addClass( 'button-activated' ); - } - }).done(function( html ) { - elem.html( html ); - head.fadeOut('fast', function(){ - elem.fadeIn('fast'); - btn.removeClass( 'button-activated' ); - spin.removeClass( 'is-active' ); - }); - // Initialise the Image Editor now that everything is ready. - imageEdit.init( postid ); - }); - - return dfd; - }, - - /** - * Initializes the cropping tool and sets a default cropping selection. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} postid The post id. - * - * @returns {void} - */ - imgLoaded : function(postid) { - var img = $('#image-preview-' + postid), parent = $('#imgedit-crop-' + postid); - - // Ensure init has run even when directly loaded. - if ( 'undefined' === typeof this.hold.sizer ) { - this.init( postid ); - } - - this.initCrop(postid, img, parent); - this.setCropSelection( postid, { 'x1': 0, 'y1': 0, 'x2': 0, 'y2': 0, 'width': img.innerWidth(), 'height': img.innerHeight() } ); - - this.toggleEditor(postid, 0); - // Editor is ready, move focus to the first focusable element. - $( '.imgedit-wrap .imgedit-help-toggle' ).eq( 0 ).focus(); - }, - - /** - * Initializes the cropping tool. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} postid The post id. - * @param {HTMLElement} image The preview image. - * @param {HTMLElement} parent The preview image container. - * - * @returns {void} - */ - initCrop : function(postid, image, parent) { - var t = this, - selW = $('#imgedit-sel-width-' + postid), - selH = $('#imgedit-sel-height-' + postid), - $img; - - t.iasapi = $(image).imgAreaSelect({ - parent: parent, - instance: true, - handles: true, - keys: true, - minWidth: 3, - minHeight: 3, - - /** - * Sets the CSS styles and binds events for locking the aspect ratio. - * - * @ignore - * - * @param {jQuery} img The preview image. - */ - onInit: function( img ) { - // Ensure that the imgAreaSelect wrapper elements are position:absolute. - // (even if we're in a position:fixed modal) - $img = $( img ); - $img.next().css( 'position', 'absolute' ) - .nextAll( '.imgareaselect-outer' ).css( 'position', 'absolute' ); - /** - * Binds mouse down event to the cropping container. - * - * @returns {void} - */ - parent.children().on( 'mousedown, touchstart', function(e){ - var ratio = false, sel, defRatio; - - if ( e.shiftKey ) { - sel = t.iasapi.getSelection(); - defRatio = t.getSelRatio(postid); - ratio = ( sel && sel.width && sel.height ) ? sel.width + ':' + sel.height : defRatio; - } - - t.iasapi.setOptions({ - aspectRatio: ratio - }); - }); - }, - - /** - * Event triggered when starting a selection. - * - * @ignore - * - * @returns {void} - */ - onSelectStart: function() { - imageEdit.setDisabled($('#imgedit-crop-sel-' + postid), 1); - }, - /** - * Event triggered when the selection is ended. - * - * @ignore - * - * @param {object} img jQuery object representing the image. - * @param {object} c The selection. - * - * @returns {object} - */ - onSelectEnd: function(img, c) { - imageEdit.setCropSelection(postid, c); - }, - - /** - * Event triggered when the selection changes. - * - * @ignore - * - * @param {object} img jQuery object representing the image. - * @param {object} c The selection. - * - * @returns {void} - */ - onSelectChange: function(img, c) { - var sizer = imageEdit.hold.sizer; - selW.val( imageEdit.round(c.width / sizer) ); - selH.val( imageEdit.round(c.height / sizer) ); - } - }); - }, - - /** - * Stores the current crop selection. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} postid The post id. - * @param {object} c The selection. - * - * @returns {boolean} - */ - setCropSelection : function(postid, c) { - var sel; - - c = c || 0; - - if ( !c || ( c.width < 3 && c.height < 3 ) ) { - this.setDisabled( $( '.imgedit-crop', '#imgedit-panel-' + postid ), 1 ); - this.setDisabled( $( '#imgedit-crop-sel-' + postid ), 1 ); - $('#imgedit-sel-width-' + postid).val(''); - $('#imgedit-sel-height-' + postid).val(''); - $('#imgedit-selection-' + postid).val(''); - return false; - } - - sel = { 'x': c.x1, 'y': c.y1, 'w': c.width, 'h': c.height }; - this.setDisabled($('.imgedit-crop', '#imgedit-panel-' + postid), 1); - $('#imgedit-selection-' + postid).val( JSON.stringify(sel) ); - }, - - - /** - * Closes the image editor. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} postid The post id. - * @param {bool} warn Warning message. - * - * @returns {void|bool} Returns false if there is a warning. - */ - close : function(postid, warn) { - warn = warn || false; - - if ( warn && this.notsaved(postid) ) { - return false; - } - - this.iasapi = {}; - this.hold = {}; - - // If we've loaded the editor in the context of a Media Modal, then switch to the previous view, - // whatever that might have been. - if ( this._view ){ - this._view.back(); - } - - // In case we are not accessing the image editor in the context of a View, close the editor the old-skool way - else { - $('#image-editor-' + postid).fadeOut('fast', function() { - $( '#media-head-' + postid ).fadeIn( 'fast', function() { - // Move focus back to the Edit Image button. Runs also when saving. - $( '#imgedit-open-btn-' + postid ).focus(); - }); - $(this).empty(); - }); - } - - - }, - - /** - * Checks if the image edit history is saved. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} postid The post id. - * - * @returns {boolean} Returns true if the history is not saved. - */ - notsaved : function(postid) { - var h = $('#imgedit-history-' + postid).val(), - history = ( h !== '' ) ? JSON.parse(h) : [], - pop = this.intval( $('#imgedit-undone-' + postid).val() ); - - if ( pop < history.length ) { - if ( confirm( $('#imgedit-leaving-' + postid).html() ) ) { - return false; - } - return true; - } - return false; - }, - - /** - * Adds an image edit action to the history. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {object} op The original position. - * @param {number} postid The post id. - * @param {string} nonce The nonce. - * - * @returns {void} - */ - addStep : function(op, postid, nonce) { - var t = this, elem = $('#imgedit-history-' + postid), - history = ( elem.val() !== '' ) ? JSON.parse( elem.val() ) : [], - undone = $( '#imgedit-undone-' + postid ), - pop = t.intval( undone.val() ); - - while ( pop > 0 ) { - history.pop(); - pop--; - } - undone.val(0); // reset - - history.push(op); - elem.val( JSON.stringify(history) ); - - t.refreshEditor(postid, nonce, function() { - t.setDisabled($('#image-undo-' + postid), true); - t.setDisabled($('#image-redo-' + postid), false); - }); - }, - - /** - * Rotates the image. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {string} angle The angle the image is rotated with. - * @param {number} postid The post id. - * @param {string} nonce The nonce. - * @param {object} t The target element. - * - * @returns {boolean} - */ - rotate : function(angle, postid, nonce, t) { - if ( $(t).hasClass('disabled') ) { - return false; - } - - this.addStep({ 'r': { 'r': angle, 'fw': this.hold.h, 'fh': this.hold.w }}, postid, nonce); - }, - - /** - * Flips the image. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} axis The axle the image is flipped on. - * @param {number} postid The post id. - * @param {string} nonce The nonce. - * @param {object} t The target element. - * - * @returns {boolean} - */ - flip : function (axis, postid, nonce, t) { - if ( $(t).hasClass('disabled') ) { - return false; - } - - this.addStep({ 'f': { 'f': axis, 'fw': this.hold.w, 'fh': this.hold.h }}, postid, nonce); - }, - - /** - * Crops the image. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} postid The post id. - * @param {string} nonce The nonce. - * @param {object} t The target object. - * - * @returns {void|boolean} Returns false if the crop button is disabled. - */ - crop : function (postid, nonce, t) { - var sel = $('#imgedit-selection-' + postid).val(), - w = this.intval( $('#imgedit-sel-width-' + postid).val() ), - h = this.intval( $('#imgedit-sel-height-' + postid).val() ); - - if ( $(t).hasClass('disabled') || sel === '' ) { - return false; - } - - sel = JSON.parse(sel); - if ( sel.w > 0 && sel.h > 0 && w > 0 && h > 0 ) { - sel.fw = w; - sel.fh = h; - this.addStep({ 'c': sel }, postid, nonce); - } - }, - - /** - * Undoes an image edit action. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} postid The post id. - * @param {string} nonce The nonce. - * - * @returns {void|false} Returns false if the undo button is disabled. - */ - undo : function (postid, nonce) { - var t = this, button = $('#image-undo-' + postid), elem = $('#imgedit-undone-' + postid), - pop = t.intval( elem.val() ) + 1; - - if ( button.hasClass('disabled') ) { - return; - } - - elem.val(pop); - t.refreshEditor(postid, nonce, function() { - var elem = $('#imgedit-history-' + postid), - history = ( elem.val() !== '' ) ? JSON.parse( elem.val() ) : []; - - t.setDisabled($('#image-redo-' + postid), true); - t.setDisabled(button, pop < history.length); - // When undo gets disabled, move focus to the redo button to avoid a focus loss. - if ( history.length === pop ) { - $( '#image-redo-' + postid ).focus(); - } - }); - }, - - /** - * Reverts a undo action. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} postid The post id. - * @param {string} nonce The nonce. - * - * @returns {void} - */ - redo : function(postid, nonce) { - var t = this, button = $('#image-redo-' + postid), elem = $('#imgedit-undone-' + postid), - pop = t.intval( elem.val() ) - 1; - - if ( button.hasClass('disabled') ) { - return; - } - - elem.val(pop); - t.refreshEditor(postid, nonce, function() { - t.setDisabled($('#image-undo-' + postid), true); - t.setDisabled(button, pop > 0); - // When redo gets disabled, move focus to the undo button to avoid a focus loss. - if ( 0 === pop ) { - $( '#image-undo-' + postid ).focus(); - } - }); - }, - - /** - * Sets the selection for the height and width in pixels. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} postid The post id. - * @param {jQuery} el The element containing the values. - * - * @returns {void|boolean} Returns false when the x or y value is lower than 1, - * void when the value is not numeric or when the operation - * is successful. - */ - setNumSelection : function( postid, el ) { - var sel, elX = $('#imgedit-sel-width-' + postid), elY = $('#imgedit-sel-height-' + postid), - x = this.intval( elX.val() ), y = this.intval( elY.val() ), - img = $('#image-preview-' + postid), imgh = img.height(), imgw = img.width(), - sizer = this.hold.sizer, x1, y1, x2, y2, ias = this.iasapi; - - if ( false === this.validateNumeric( el ) ) { - return; - } - - if ( x < 1 ) { - elX.val(''); - return false; - } - - if ( y < 1 ) { - elY.val(''); - return false; - } - - if ( x && y && ( sel = ias.getSelection() ) ) { - x2 = sel.x1 + Math.round( x * sizer ); - y2 = sel.y1 + Math.round( y * sizer ); - x1 = sel.x1; - y1 = sel.y1; - - if ( x2 > imgw ) { - x1 = 0; - x2 = imgw; - elX.val( Math.round( x2 / sizer ) ); - } - - if ( y2 > imgh ) { - y1 = 0; - y2 = imgh; - elY.val( Math.round( y2 / sizer ) ); - } - - ias.setSelection( x1, y1, x2, y2 ); - ias.update(); - this.setCropSelection(postid, ias.getSelection()); - } - }, - - /** - * Rounds a number to a whole. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} num The number. - * - * @returns {number} The number rounded to a whole number. - */ - round : function(num) { - var s; - num = Math.round(num); - - if ( this.hold.sizer > 0.6 ) { - return num; - } - - s = num.toString().slice(-1); - - if ( '1' === s ) { - return num - 1; - } else if ( '9' === s ) { - return num + 1; - } - - return num; - }, - - /** - * Sets a locked aspect ratio for the selection. - * - * @memberof imageEdit - * @since 2.9.0 - * - * @param {number} postid The post id. - * @param {number} n The ratio to set. - * @param {jQuery} el The element containing the values. - * - * @returns {void} - */ - setRatioSelection : function(postid, n, el) { - var sel, r, x = this.intval( $('#imgedit-crop-width-' + postid).val() ), - y = this.intval( $('#imgedit-crop-height-' + postid).val() ), - h = $('#image-preview-' + postid).height(); - - if ( false === this.validateNumeric( el ) ) { - return; - } - - if ( x && y ) { - this.iasapi.setOptions({ - aspectRatio: x + ':' + y - }); - - if ( sel = this.iasapi.getSelection(true) ) { - r = Math.ceil( sel.y1 + ( ( sel.x2 - sel.x1 ) / ( x / y ) ) ); - - if ( r > h ) { - r = h; - if ( n ) { - $('#imgedit-crop-height-' + postid).val(''); - } else { - $('#imgedit-crop-width-' + postid).val(''); - } - } - - this.iasapi.setSelection( sel.x1, sel.y1, sel.x2, r ); - this.iasapi.update(); - } - } - }, - - /** - * Validates if a value in a jQuery.HTMLElement is numeric. - * - * @memberof imageEdit - * @since 4.6 - * - * @param {jQuery} el The html element. - * - * @returns {void|boolean} Returns false if the value is not numeric, - * void when it is. - */ - validateNumeric: function( el ) { - if ( ! this.intval( $( el ).val() ) ) { - $( el ).val( '' ); - return false; - } - } -}; -})(jQuery); diff --git a/srcs/wordpress/wp-admin/js/image-edit.min.js b/srcs/wordpress/wp-admin/js/image-edit.min.js deleted file mode 100644 index 219ca38..0000000 --- a/srcs/wordpress/wp-admin/js/image-edit.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(m){var l=window.imageEdit={iasapi:{},hold:{},postid:"",_view:!1,handleCropToolClick:function(i,t,e){var a=m("#image-preview-"+i),s=this.iasapi.getSelection();isNaN(s.x1)&&(this.setCropSelection(i,{x1:0,y1:0,x2:a.innerWidth(),y2:a.innerHeight(),width:a.innerWidth(),height:a.innerHeight()}),s=this.iasapi.getSelection()),0===s.x1&&0===s.y1&&0===s.x2&&0===s.y2?(this.iasapi.setSelection(0,0,a.innerWidth(),a.innerHeight(),!0),this.iasapi.setOptions({show:!0}),this.iasapi.update()):l.crop(i,t,e)},intval:function(i){return 0|i},setDisabled:function(i,t){t?i.removeClass("disabled").prop("disabled",!1):i.addClass("disabled").prop("disabled",!0)},init:function(i){var t=this,e=m("#image-editor-"+t.postid),a=t.intval(m("#imgedit-x-"+i).val()),s=t.intval(m("#imgedit-y-"+i).val());t.postid!==i&&e.length&&t.close(t.postid),t.hold.w=t.hold.ow=a,t.hold.h=t.hold.oh=s,t.hold.xy_ratio=a/s,t.hold.sizer=parseFloat(m("#imgedit-sizer-"+i).val()),t.postid=i,m("#imgedit-response-"+i).empty(),m('input[type="text"]',"#imgedit-panel-"+i).keypress(function(i){var t=i.keyCode;if(36<t&&t<41&&m(this).blur(),13===t)return i.preventDefault(),i.stopPropagation(),!1})},toggleEditor:function(i,t){var e=m("#imgedit-wait-"+i);t?e.fadeIn("fast"):e.fadeOut("fast")},toggleHelp:function(i){var t=m(i);return t.attr("aria-expanded","false"===t.attr("aria-expanded")?"true":"false").parents(".imgedit-group-top").toggleClass("imgedit-help-toggled").find(".imgedit-help").slideToggle("fast"),!1},getTarget:function(i){return m('input[name="imgedit-target-'+i+'"]:checked',"#imgedit-save-target-"+i).val()||"full"},scaleChanged:function(i,t,e){var a=m("#imgedit-scale-width-"+i),s=m("#imgedit-scale-height-"+i),o=m("#imgedit-scale-warn-"+i),n="",d="";!1!==this.validateNumeric(e)&&(t?(d=""!==a.val()?Math.round(a.val()/this.hold.xy_ratio):"",s.val(d)):(n=""!==s.val()?Math.round(s.val()*this.hold.xy_ratio):"",a.val(n)),d&&d>this.hold.oh||n&&n>this.hold.ow?o.css("visibility","visible"):o.css("visibility","hidden"))},getSelRatio:function(i){var t=this.hold.w,e=this.hold.h,a=this.intval(m("#imgedit-crop-width-"+i).val()),s=this.intval(m("#imgedit-crop-height-"+i).val());return a&&s?a+":"+s:t&&e?t+":"+e:"1:1"},filterHistory:function(i,t){var e,a,s,o,n=m("#imgedit-history-"+i).val(),d=[];if(""===n)return"";if(n=JSON.parse(n),0<(e=this.intval(m("#imgedit-undone-"+i).val())))for(;0<e;)n.pop(),e--;if(t){if(!n.length)return this.hold.w=this.hold.ow,this.hold.h=this.hold.oh,"";(s=(s=n[n.length-1]).c||s.r||s.f||!1)&&(this.hold.w=s.fw,this.hold.h=s.fh)}for(a in n)(o=n[a]).hasOwnProperty("c")?d[a]={c:{x:o.c.x,y:o.c.y,w:o.c.w,h:o.c.h}}:o.hasOwnProperty("r")?d[a]={r:o.r.r}:o.hasOwnProperty("f")&&(d[a]={f:o.f.f});return JSON.stringify(d)},refreshEditor:function(n,i,d){var t,r,e=this;e.toggleEditor(n,1),t={action:"imgedit-preview",_ajax_nonce:i,postid:n,history:e.filterHistory(n,1),rand:e.intval(1e6*Math.random())},r=m('<img id="image-preview-'+n+'" alt="" />').on("load",{history:t.history},function(i){var t,e,a,s=m("#imgedit-crop-"+n),o=l;""!==i.data.history&&(a=JSON.parse(i.data.history))[a.length-1].hasOwnProperty("c")&&(o.setDisabled(m("#image-undo-"+n),!0),m("#image-undo-"+n).focus()),s.empty().append(r),t=Math.max(o.hold.w,o.hold.h),e=Math.max(m(r).width(),m(r).height()),o.hold.sizer=e<t?e/t:1,o.initCrop(n,r,s),null!=d&&d(),m("#imgedit-history-"+n).val()&&"0"===m("#imgedit-undone-"+n).val()?m("input.imgedit-submit-btn","#imgedit-panel-"+n).removeAttr("disabled"):m("input.imgedit-submit-btn","#imgedit-panel-"+n).prop("disabled",!0),o.toggleEditor(n,0)}).on("error",function(){m("#imgedit-crop-"+n).empty().append('<div class="error"><p>'+imageEditL10n.error+"</p></div>"),e.toggleEditor(n,0)}).attr("src",ajaxurl+"?"+m.param(t))},action:function(t,i,e){var a,s,o,n,d,r=this;if(r.notsaved(t))return!1;if(a={action:"image-editor",_ajax_nonce:i,postid:t},"scale"===e){if(s=m("#imgedit-scale-width-"+t),o=m("#imgedit-scale-height-"+t),n=r.intval(s.val()),d=r.intval(o.val()),n<1)return s.focus(),!1;if(d<1)return o.focus(),!1;if(n===r.hold.ow||d===r.hold.oh)return!1;a.do="scale",a.fwidth=n,a.fheight=d}else{if("restore"!==e)return!1;a.do="restore"}r.toggleEditor(t,1),m.post(ajaxurl,a,function(i){m("#image-editor-"+t).empty().append(i),r.toggleEditor(t,0),r._view&&r._view.refresh()})},save:function(e,i){var t,a=this.getTarget(e),s=this.filterHistory(e,0),o=this;if(""===s)return!1;this.toggleEditor(e,1),t={action:"image-editor",_ajax_nonce:i,postid:e,history:s,target:a,context:m("#image-edit-context").length?m("#image-edit-context").val():null,do:"save"},m.post(ajaxurl,t,function(i){var t=JSON.parse(i);if(t.error)return m("#imgedit-response-"+e).html('<div class="error"><p>'+t.error+"</p></div>"),void l.close(e);t.fw&&t.fh&&m("#media-dims-"+e).html(t.fw+" × "+t.fh),t.thumbnail&&m(".thumbnail","#thumbnail-head-"+e).attr("src",""+t.thumbnail),t.msg&&m("#imgedit-response-"+e).html('<div class="updated"><p>'+t.msg+"</p></div>"),o._view?o._view.save():l.close(e)})},open:function(t,i,e){this._view=e;var a,s=m("#image-editor-"+t),o=m("#media-head-"+t),n=m("#imgedit-open-btn-"+t),d=n.siblings(".spinner");if(!n.hasClass("button-activated"))return d.addClass("is-active"),a={action:"image-editor",_ajax_nonce:i,postid:t,do:"open"},m.ajax({url:ajaxurl,type:"post",data:a,beforeSend:function(){n.addClass("button-activated")}}).done(function(i){s.html(i),o.fadeOut("fast",function(){s.fadeIn("fast"),n.removeClass("button-activated"),d.removeClass("is-active")}),l.init(t)})},imgLoaded:function(i){var t=m("#image-preview-"+i),e=m("#imgedit-crop-"+i);void 0===this.hold.sizer&&this.init(i),this.initCrop(i,t,e),this.setCropSelection(i,{x1:0,y1:0,x2:0,y2:0,width:t.innerWidth(),height:t.innerHeight()}),this.toggleEditor(i,0),m(".imgedit-wrap .imgedit-help-toggle").eq(0).focus()},initCrop:function(s,i,t){var o=this,a=m("#imgedit-sel-width-"+s),n=m("#imgedit-sel-height-"+s);o.iasapi=m(i).imgAreaSelect({parent:t,instance:!0,handles:!0,keys:!0,minWidth:3,minHeight:3,onInit:function(i){m(i).next().css("position","absolute").nextAll(".imgareaselect-outer").css("position","absolute"),t.children().on("mousedown, touchstart",function(i){var t,e,a=!1;i.shiftKey&&(t=o.iasapi.getSelection(),e=o.getSelRatio(s),a=t&&t.width&&t.height?t.width+":"+t.height:e),o.iasapi.setOptions({aspectRatio:a})})},onSelectStart:function(){l.setDisabled(m("#imgedit-crop-sel-"+s),1)},onSelectEnd:function(i,t){l.setCropSelection(s,t)},onSelectChange:function(i,t){var e=l.hold.sizer;a.val(l.round(t.width/e)),n.val(l.round(t.height/e))}})},setCropSelection:function(i,t){var e;if(!(t=t||0)||t.width<3&&t.height<3)return this.setDisabled(m(".imgedit-crop","#imgedit-panel-"+i),1),this.setDisabled(m("#imgedit-crop-sel-"+i),1),m("#imgedit-sel-width-"+i).val(""),m("#imgedit-sel-height-"+i).val(""),m("#imgedit-selection-"+i).val(""),!1;e={x:t.x1,y:t.y1,w:t.width,h:t.height},this.setDisabled(m(".imgedit-crop","#imgedit-panel-"+i),1),m("#imgedit-selection-"+i).val(JSON.stringify(e))},close:function(i,t){if((t=t||!1)&&this.notsaved(i))return!1;this.iasapi={},this.hold={},this._view?this._view.back():m("#image-editor-"+i).fadeOut("fast",function(){m("#media-head-"+i).fadeIn("fast",function(){m("#imgedit-open-btn-"+i).focus()}),m(this).empty()})},notsaved:function(i){var t=m("#imgedit-history-"+i).val(),e=""!==t?JSON.parse(t):[];return this.intval(m("#imgedit-undone-"+i).val())<e.length&&!confirm(m("#imgedit-leaving-"+i).html())},addStep:function(i,t,e){for(var a=this,s=m("#imgedit-history-"+t),o=""!==s.val()?JSON.parse(s.val()):[],n=m("#imgedit-undone-"+t),d=a.intval(n.val());0<d;)o.pop(),d--;n.val(0),o.push(i),s.val(JSON.stringify(o)),a.refreshEditor(t,e,function(){a.setDisabled(m("#image-undo-"+t),!0),a.setDisabled(m("#image-redo-"+t),!1)})},rotate:function(i,t,e,a){if(m(a).hasClass("disabled"))return!1;this.addStep({r:{r:i,fw:this.hold.h,fh:this.hold.w}},t,e)},flip:function(i,t,e,a){if(m(a).hasClass("disabled"))return!1;this.addStep({f:{f:i,fw:this.hold.w,fh:this.hold.h}},t,e)},crop:function(i,t,e){var a=m("#imgedit-selection-"+i).val(),s=this.intval(m("#imgedit-sel-width-"+i).val()),o=this.intval(m("#imgedit-sel-height-"+i).val());if(m(e).hasClass("disabled")||""===a)return!1;0<(a=JSON.parse(a)).w&&0<a.h&&0<s&&0<o&&(a.fw=s,a.fh=o,this.addStep({c:a},i,t))},undo:function(e,i){var a=this,s=m("#image-undo-"+e),t=m("#imgedit-undone-"+e),o=a.intval(t.val())+1;s.hasClass("disabled")||(t.val(o),a.refreshEditor(e,i,function(){var i=m("#imgedit-history-"+e),t=""!==i.val()?JSON.parse(i.val()):[];a.setDisabled(m("#image-redo-"+e),!0),a.setDisabled(s,o<t.length),t.length===o&&m("#image-redo-"+e).focus()}))},redo:function(i,t){var e=this,a=m("#image-redo-"+i),s=m("#imgedit-undone-"+i),o=e.intval(s.val())-1;a.hasClass("disabled")||(s.val(o),e.refreshEditor(i,t,function(){e.setDisabled(m("#image-undo-"+i),!0),e.setDisabled(a,0<o),0==o&&m("#image-undo-"+i).focus()}))},setNumSelection:function(i,t){var e,a,s,o,n,d=m("#imgedit-sel-width-"+i),r=m("#imgedit-sel-height-"+i),l=this.intval(d.val()),h=this.intval(r.val()),g=m("#image-preview-"+i),c=g.height(),v=g.width(),p=this.hold.sizer,u=this.iasapi;if(!1!==this.validateNumeric(t))return l<1?(d.val(""),!1):h<1?(r.val(""),!1):void(l&&h&&(e=u.getSelection())&&(o=e.x1+Math.round(l*p),n=e.y1+Math.round(h*p),a=e.x1,s=e.y1,v<o&&(a=0,o=v,d.val(Math.round(o/p))),c<n&&(s=0,n=c,r.val(Math.round(n/p))),u.setSelection(a,s,o,n),u.update(),this.setCropSelection(i,u.getSelection())))},round:function(i){var t;return i=Math.round(i),.6<this.hold.sizer?i:"1"===(t=i.toString().slice(-1))?i-1:"9"===t?i+1:i},setRatioSelection:function(i,t,e){var a,s,o=this.intval(m("#imgedit-crop-width-"+i).val()),n=this.intval(m("#imgedit-crop-height-"+i).val()),d=m("#image-preview-"+i).height();!1!==this.validateNumeric(e)&&o&&n&&(this.iasapi.setOptions({aspectRatio:o+":"+n}),(a=this.iasapi.getSelection(!0))&&(d<(s=Math.ceil(a.y1+(a.x2-a.x1)/(o/n)))&&(s=d,t?m("#imgedit-crop-height-"+i).val(""):m("#imgedit-crop-width-"+i).val("")),this.iasapi.setSelection(a.x1,a.y1,a.x2,s),this.iasapi.update()))},validateNumeric:function(i){if(!this.intval(m(i).val()))return m(i).val(""),!1}}}(jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/inline-edit-post.js b/srcs/wordpress/wp-admin/js/inline-edit-post.js deleted file mode 100644 index b39b9b6..0000000 --- a/srcs/wordpress/wp-admin/js/inline-edit-post.js +++ /dev/null @@ -1,555 +0,0 @@ -/** - * This file contains the functions needed for the inline editing of posts. - * - * @since 2.7.0 - * @output wp-admin/js/inline-edit-post.js - */ - -/* global inlineEditL10n, ajaxurl, typenow, inlineEditPost */ - -window.wp = window.wp || {}; - -/** - * Manages the quick edit and bulk edit windows for editing posts or pages. - * - * @namespace inlineEditPost - * - * @since 2.7.0 - * - * @type {Object} - * - * @property {string} type The type of inline editor. - * @property {string} what The prefix before the post id. - * - */ -( function( $, wp ) { - - window.inlineEditPost = { - - /** - * Initializes the inline and bulk post editor. - * - * Binds event handlers to the escape key to close the inline editor - * and to the save and close buttons. Changes DOM to be ready for inline - * editing. Adds event handler to bulk edit. - * - * @memberof inlineEditPost - * @since 2.7.0 - * - * @returns {void} - */ - init : function(){ - var t = this, qeRow = $('#inline-edit'), bulkRow = $('#bulk-edit'); - - t.type = $('table.widefat').hasClass('pages') ? 'page' : 'post'; - // Post id prefix. - t.what = '#post-'; - - /** - * Binds the escape key to revert the changes and close the quick editor. - * - * @returns {boolean} The result of revert. - */ - qeRow.keyup(function(e){ - // Revert changes if escape key is pressed. - if ( e.which === 27 ) { - return inlineEditPost.revert(); - } - }); - - /** - * Binds the escape key to revert the changes and close the bulk editor. - * - * @returns {boolean} The result of revert. - */ - bulkRow.keyup(function(e){ - // Revert changes if escape key is pressed. - if ( e.which === 27 ) { - return inlineEditPost.revert(); - } - }); - - /** - * Reverts changes and close the quick editor if the cancel button is clicked. - * - * @returns {boolean} The result of revert. - */ - $( '.cancel', qeRow ).click( function() { - return inlineEditPost.revert(); - }); - - /** - * Saves changes in the quick editor if the save(named: update) button is clicked. - * - * @returns {boolean} The result of save. - */ - $( '.save', qeRow ).click( function() { - return inlineEditPost.save(this); - }); - - /** - * If enter is pressed, and the target is not the cancel button, save the post. - * - * @returns {boolean} The result of save. - */ - $('td', qeRow).keydown(function(e){ - if ( e.which === 13 && ! $( e.target ).hasClass( 'cancel' ) ) { - return inlineEditPost.save(this); - } - }); - - /** - * Reverts changes and close the bulk editor if the cancel button is clicked. - * - * @returns {boolean} The result of revert. - */ - $( '.cancel', bulkRow ).click( function() { - return inlineEditPost.revert(); - }); - - /** - * Disables the password input field when the private post checkbox is checked. - */ - $('#inline-edit .inline-edit-private input[value="private"]').click( function(){ - var pw = $('input.inline-edit-password-input'); - if ( $(this).prop('checked') ) { - pw.val('').prop('disabled', true); - } else { - pw.prop('disabled', false); - } - }); - - /** - * Binds click event to the .editinline button which opens the quick editor. - */ - $( '#the-list' ).on( 'click', '.editinline', function() { - $( this ).attr( 'aria-expanded', 'true' ); - inlineEditPost.edit( this ); - }); - - $('#bulk-edit').find('fieldset:first').after( - $('#inline-edit fieldset.inline-edit-categories').clone() - ).siblings( 'fieldset:last' ).prepend( - $('#inline-edit label.inline-edit-tags').clone() - ); - - $('select[name="_status"] option[value="future"]', bulkRow).remove(); - - /** - * Adds onclick events to the apply buttons. - */ - $('#doaction, #doaction2').click(function(e){ - var n; - - t.whichBulkButtonId = $( this ).attr( 'id' ); - n = t.whichBulkButtonId.substr( 2 ); - - if ( 'edit' === $( 'select[name="' + n + '"]' ).val() ) { - e.preventDefault(); - t.setBulk(); - } else if ( $('form#posts-filter tr.inline-editor').length > 0 ) { - t.revert(); - } - }); - }, - - /** - * Toggles the quick edit window, hiding it when it's active and showing it when - * inactive. - * - * @memberof inlineEditPost - * @since 2.7.0 - * - * @param {Object} el Element within a post table row. - */ - toggle : function(el){ - var t = this; - $( t.what + t.getId( el ) ).css( 'display' ) === 'none' ? t.revert() : t.edit( el ); - }, - - /** - * Creates the bulk editor row to edit multiple posts at once. - * - * @memberof inlineEditPost - * @since 2.7.0 - */ - setBulk : function(){ - var te = '', type = this.type, c = true; - this.revert(); - - $( '#bulk-edit td' ).attr( 'colspan', $( 'th:visible, td:visible', '.widefat:first thead' ).length ); - - // Insert the editor at the top of the table with an empty row above to maintain zebra striping. - $('table.widefat tbody').prepend( $('#bulk-edit') ).prepend('<tr class="hidden"></tr>'); - $('#bulk-edit').addClass('inline-editor').show(); - - /** - * Create a HTML div with the title and a link(delete-icon) for each selected - * post. - * - * Get the selected posts based on the checked checkboxes in the post table. - */ - $( 'tbody th.check-column input[type="checkbox"]' ).each( function() { - - // If the checkbox for a post is selected, add the post to the edit list. - if ( $(this).prop('checked') ) { - c = false; - var id = $(this).val(), theTitle; - theTitle = $('#inline_'+id+' .post_title').html() || inlineEditL10n.notitle; - te += '<div id="ttle'+id+'"><a id="_'+id+'" class="ntdelbutton" title="'+inlineEditL10n.ntdeltitle+'">X</a>'+theTitle+'</div>'; - } - }); - - // If no checkboxes where checked, just hide the quick/bulk edit rows. - if ( c ) { - return this.revert(); - } - - // Add onclick events to the delete-icons in the bulk editors the post title list. - $('#bulk-titles').html(te); - /** - * Binds on click events to the checkboxes before the posts in the table. - * - * @listens click - */ - $('#bulk-titles a').click(function(){ - var id = $(this).attr('id').substr(1); - - $('table.widefat input[value="' + id + '"]').prop('checked', false); - $('#ttle'+id).remove(); - }); - - // Enable auto-complete for tags when editing posts. - if ( 'post' === type ) { - $( 'tr.inline-editor textarea[data-wp-taxonomy]' ).each( function ( i, element ) { - /* - * While Quick Edit clones the form each time, Bulk Edit always re-uses - * the same form. Let's check if an autocomplete instance already exists. - */ - if ( $( element ).autocomplete( 'instance' ) ) { - // jQuery equivalent of `continue` within an `each()` loop. - return; - } - - $( element ).wpTagsSuggest(); - } ); - } - - // Scrolls to the top of the table where the editor is rendered. - $('html, body').animate( { scrollTop: 0 }, 'fast' ); - }, - - /** - * Creates a quick edit window for the post that has been clicked. - * - * @memberof inlineEditPost - * @since 2.7.0 - * - * @param {number|Object} id The id of the clicked post or an element within a post - * table row. - * @returns {boolean} Always returns false at the end of execution. - */ - edit : function(id) { - var t = this, fields, editRow, rowData, status, pageOpt, pageLevel, nextPage, pageLoop = true, nextLevel, f, val, pw; - t.revert(); - - if ( typeof(id) === 'object' ) { - id = t.getId(id); - } - - fields = ['post_title', 'post_name', 'post_author', '_status', 'jj', 'mm', 'aa', 'hh', 'mn', 'ss', 'post_password', 'post_format', 'menu_order', 'page_template']; - if ( t.type === 'page' ) { - fields.push('post_parent'); - } - - // Add the new edit row with an extra blank row underneath to maintain zebra striping. - editRow = $('#inline-edit').clone(true); - $( 'td', editRow ).attr( 'colspan', $( 'th:visible, td:visible', '.widefat:first thead' ).length ); - - $(t.what+id).removeClass('is-expanded').hide().after(editRow).after('<tr class="hidden"></tr>'); - - // Populate fields in the quick edit window. - rowData = $('#inline_'+id); - if ( !$(':input[name="post_author"] option[value="' + $('.post_author', rowData).text() + '"]', editRow).val() ) { - - // The post author no longer has edit capabilities, so we need to add them to the list of authors. - $(':input[name="post_author"]', editRow).prepend('<option value="' + $('.post_author', rowData).text() + '">' + $('#' + t.type + '-' + id + ' .author').text() + '</option>'); - } - if ( $( ':input[name="post_author"] option', editRow ).length === 1 ) { - $('label.inline-edit-author', editRow).hide(); - } - - for ( f = 0; f < fields.length; f++ ) { - val = $('.'+fields[f], rowData); - - /** - * Replaces the image for a Twemoji(Twitter emoji) with it's alternate text. - * - * @returns Alternate text from the image. - */ - val.find( 'img' ).replaceWith( function() { return this.alt; } ); - val = val.text(); - $(':input[name="' + fields[f] + '"]', editRow).val( val ); - } - - if ( $( '.comment_status', rowData ).text() === 'open' ) { - $( 'input[name="comment_status"]', editRow ).prop( 'checked', true ); - } - if ( $( '.ping_status', rowData ).text() === 'open' ) { - $( 'input[name="ping_status"]', editRow ).prop( 'checked', true ); - } - if ( $( '.sticky', rowData ).text() === 'sticky' ) { - $( 'input[name="sticky"]', editRow ).prop( 'checked', true ); - } - - /** - * Creates the select boxes for the categories. - */ - $('.post_category', rowData).each(function(){ - var taxname, - term_ids = $(this).text(); - - if ( term_ids ) { - taxname = $(this).attr('id').replace('_'+id, ''); - $('ul.'+taxname+'-checklist :checkbox', editRow).val(term_ids.split(',')); - } - }); - - /** - * Gets all the taxonomies for live auto-fill suggestions when typing the name - * of a tag. - */ - $('.tags_input', rowData).each(function(){ - var terms = $(this), - taxname = $(this).attr('id').replace('_' + id, ''), - textarea = $('textarea.tax_input_' + taxname, editRow), - comma = inlineEditL10n.comma; - - terms.find( 'img' ).replaceWith( function() { return this.alt; } ); - terms = terms.text(); - - if ( terms ) { - if ( ',' !== comma ) { - terms = terms.replace(/,/g, comma); - } - textarea.val(terms); - } - - textarea.wpTagsSuggest(); - }); - - // Handle the post status. - status = $('._status', rowData).text(); - if ( 'future' !== status ) { - $('select[name="_status"] option[value="future"]', editRow).remove(); - } - - pw = $( '.inline-edit-password-input' ).prop( 'disabled', false ); - if ( 'private' === status ) { - $('input[name="keep_private"]', editRow).prop('checked', true); - pw.val( '' ).prop( 'disabled', true ); - } - - // Remove the current page and children from the parent dropdown. - pageOpt = $('select[name="post_parent"] option[value="' + id + '"]', editRow); - if ( pageOpt.length > 0 ) { - pageLevel = pageOpt[0].className.split('-')[1]; - nextPage = pageOpt; - while ( pageLoop ) { - nextPage = nextPage.next('option'); - if ( nextPage.length === 0 ) { - break; - } - - nextLevel = nextPage[0].className.split('-')[1]; - - if ( nextLevel <= pageLevel ) { - pageLoop = false; - } else { - nextPage.remove(); - nextPage = pageOpt; - } - } - pageOpt.remove(); - } - - $(editRow).attr('id', 'edit-'+id).addClass('inline-editor').show(); - $('.ptitle', editRow).focus(); - - return false; - }, - - /** - * Saves the changes made in the quick edit window to the post. - * AJAX saving is only for Quick Edit and not for bulk edit. - * - * @since 2.7.0 - * - * @param {int} id The id for the post that has been changed. - * @returns {boolean} false, so the form does not submit when pressing - * Enter on a focused field. - */ - save : function(id) { - var params, fields, page = $('.post_status_page').val() || ''; - - if ( typeof(id) === 'object' ) { - id = this.getId(id); - } - - $( 'table.widefat .spinner' ).addClass( 'is-active' ); - - params = { - action: 'inline-save', - post_type: typenow, - post_ID: id, - edit_date: 'true', - post_status: page - }; - - fields = $('#edit-'+id).find(':input').serialize(); - params = fields + '&' + $.param(params); - - // Make ajax request. - $.post( ajaxurl, params, - function(r) { - var $errorNotice = $( '#edit-' + id + ' .inline-edit-save .notice-error' ), - $error = $errorNotice.find( '.error' ); - - $( 'table.widefat .spinner' ).removeClass( 'is-active' ); - $( '.ac_results' ).hide(); - - if (r) { - if ( -1 !== r.indexOf( '<tr' ) ) { - $(inlineEditPost.what+id).siblings('tr.hidden').addBack().remove(); - $('#edit-'+id).before(r).remove(); - $( inlineEditPost.what + id ).hide().fadeIn( 400, function() { - // Move focus back to the Quick Edit button. $( this ) is the row being animated. - $( this ).find( '.editinline' ) - .attr( 'aria-expanded', 'false' ) - .focus(); - wp.a11y.speak( inlineEditL10n.saved ); - }); - } else { - r = r.replace( /<.[^<>]*?>/g, '' ); - $errorNotice.removeClass( 'hidden' ); - $error.html( r ); - wp.a11y.speak( $error.text() ); - } - } else { - $errorNotice.removeClass( 'hidden' ); - $error.html( inlineEditL10n.error ); - wp.a11y.speak( inlineEditL10n.error ); - } - }, - 'html'); - - // Prevent submitting the form when pressing Enter on a focused field. - return false; - }, - - /** - * Hides and empties the Quick Edit and/or Bulk Edit windows. - * - * @memberof inlineEditPost - * @since 2.7.0 - * - * @returns {boolean} Always returns false. - */ - revert : function(){ - var $tableWideFat = $( '.widefat' ), - id = $( '.inline-editor', $tableWideFat ).attr( 'id' ); - - if ( id ) { - $( '.spinner', $tableWideFat ).removeClass( 'is-active' ); - $( '.ac_results' ).hide(); - - if ( 'bulk-edit' === id ) { - - // Hide the bulk editor. - $( '#bulk-edit', $tableWideFat ).removeClass( 'inline-editor' ).hide().siblings( '.hidden' ).remove(); - $('#bulk-titles').empty(); - - // Store the empty bulk editor in a hidden element. - $('#inlineedit').append( $('#bulk-edit') ); - - // Move focus back to the Bulk Action button that was activated. - $( '#' + inlineEditPost.whichBulkButtonId ).focus(); - } else { - - // Remove both the inline-editor and its hidden tr siblings. - $('#'+id).siblings('tr.hidden').addBack().remove(); - id = id.substr( id.lastIndexOf('-') + 1 ); - - // Show the post row and move focus back to the Quick Edit button. - $( this.what + id ).show().find( '.editinline' ) - .attr( 'aria-expanded', 'false' ) - .focus(); - } - } - - return false; - }, - - /** - * Gets the id for a the post that you want to quick edit from the row in the quick - * edit table. - * - * @memberof inlineEditPost - * @since 2.7.0 - * - * @param {Object} o DOM row object to get the id for. - * @returns {string} The post id extracted from the table row in the object. - */ - getId : function(o) { - var id = $(o).closest('tr').attr('id'), - parts = id.split('-'); - return parts[parts.length - 1]; - } -}; - -$( document ).ready( function(){ inlineEditPost.init(); } ); - -// Show/hide locks on posts. -$( document ).on( 'heartbeat-tick.wp-check-locked-posts', function( e, data ) { - var locked = data['wp-check-locked-posts'] || {}; - - $('#the-list tr').each( function(i, el) { - var key = el.id, row = $(el), lock_data, avatar; - - if ( locked.hasOwnProperty( key ) ) { - if ( ! row.hasClass('wp-locked') ) { - lock_data = locked[key]; - row.find('.column-title .locked-text').text( lock_data.text ); - row.find('.check-column checkbox').prop('checked', false); - - if ( lock_data.avatar_src ) { - avatar = $( '<img class="avatar avatar-18 photo" width="18" height="18" alt="" />' ).attr( 'src', lock_data.avatar_src.replace( /&/g, '&' ) ); - row.find('.column-title .locked-avatar').empty().append( avatar ); - } - row.addClass('wp-locked'); - } - } else if ( row.hasClass('wp-locked') ) { - row.removeClass( 'wp-locked' ).find( '.locked-info span' ).empty(); - } - }); -}).on( 'heartbeat-send.wp-check-locked-posts', function( e, data ) { - var check = []; - - $('#the-list tr').each( function(i, el) { - if ( el.id ) { - check.push( el.id ); - } - }); - - if ( check.length ) { - data['wp-check-locked-posts'] = check; - } -}).ready( function() { - - // Set the heartbeat interval to 15 sec. - if ( typeof wp !== 'undefined' && wp.heartbeat ) { - wp.heartbeat.interval( 15 ); - } -}); - -})( jQuery, window.wp ); diff --git a/srcs/wordpress/wp-admin/js/inline-edit-post.min.js b/srcs/wordpress/wp-admin/js/inline-edit-post.min.js deleted file mode 100644 index d9d8d68..0000000 --- a/srcs/wordpress/wp-admin/js/inline-edit-post.min.js +++ /dev/null @@ -1 +0,0 @@ -window.wp=window.wp||{},function(h,a){window.inlineEditPost={init:function(){var i=this,t=h("#inline-edit"),e=h("#bulk-edit");i.type=h("table.widefat").hasClass("pages")?"page":"post",i.what="#post-",t.keyup(function(t){if(27===t.which)return inlineEditPost.revert()}),e.keyup(function(t){if(27===t.which)return inlineEditPost.revert()}),h(".cancel",t).click(function(){return inlineEditPost.revert()}),h(".save",t).click(function(){return inlineEditPost.save(this)}),h("td",t).keydown(function(t){if(13===t.which&&!h(t.target).hasClass("cancel"))return inlineEditPost.save(this)}),h(".cancel",e).click(function(){return inlineEditPost.revert()}),h('#inline-edit .inline-edit-private input[value="private"]').click(function(){var t=h("input.inline-edit-password-input");h(this).prop("checked")?t.val("").prop("disabled",!0):t.prop("disabled",!1)}),h("#the-list").on("click",".editinline",function(){h(this).attr("aria-expanded","true"),inlineEditPost.edit(this)}),h("#bulk-edit").find("fieldset:first").after(h("#inline-edit fieldset.inline-edit-categories").clone()).siblings("fieldset:last").prepend(h("#inline-edit label.inline-edit-tags").clone()),h('select[name="_status"] option[value="future"]',e).remove(),h("#doaction, #doaction2").click(function(t){var e;i.whichBulkButtonId=h(this).attr("id"),e=i.whichBulkButtonId.substr(2),"edit"===h('select[name="'+e+'"]').val()?(t.preventDefault(),i.setBulk()):0<h("form#posts-filter tr.inline-editor").length&&i.revert()})},toggle:function(t){var e=this;"none"===h(e.what+e.getId(t)).css("display")?e.revert():e.edit(t)},setBulk:function(){var i="",t=this.type,n=!0;if(this.revert(),h("#bulk-edit td").attr("colspan",h("th:visible, td:visible",".widefat:first thead").length),h("table.widefat tbody").prepend(h("#bulk-edit")).prepend('<tr class="hidden"></tr>'),h("#bulk-edit").addClass("inline-editor").show(),h('tbody th.check-column input[type="checkbox"]').each(function(){if(h(this).prop("checked")){n=!1;var t,e=h(this).val();t=h("#inline_"+e+" .post_title").html()||inlineEditL10n.notitle,i+='<div id="ttle'+e+'"><a id="_'+e+'" class="ntdelbutton" title="'+inlineEditL10n.ntdeltitle+'">X</a>'+t+"</div>"}}),n)return this.revert();h("#bulk-titles").html(i),h("#bulk-titles a").click(function(){var t=h(this).attr("id").substr(1);h('table.widefat input[value="'+t+'"]').prop("checked",!1),h("#ttle"+t).remove()}),"post"===t&&h("tr.inline-editor textarea[data-wp-taxonomy]").each(function(t,e){h(e).autocomplete("instance")||h(e).wpTagsSuggest()}),h("html, body").animate({scrollTop:0},"fast")},edit:function(a){var t,s,e,i,n,o,l,r,d,c,p=this,u=!0;for(p.revert(),"object"==typeof a&&(a=p.getId(a)),t=["post_title","post_name","post_author","_status","jj","mm","aa","hh","mn","ss","post_password","post_format","menu_order","page_template"],"page"===p.type&&t.push("post_parent"),s=h("#inline-edit").clone(!0),h("td",s).attr("colspan",h("th:visible, td:visible",".widefat:first thead").length),h(p.what+a).removeClass("is-expanded").hide().after(s).after('<tr class="hidden"></tr>'),e=h("#inline_"+a),h(':input[name="post_author"] option[value="'+h(".post_author",e).text()+'"]',s).val()||h(':input[name="post_author"]',s).prepend('<option value="'+h(".post_author",e).text()+'">'+h("#"+p.type+"-"+a+" .author").text()+"</option>"),1===h(':input[name="post_author"] option',s).length&&h("label.inline-edit-author",s).hide(),r=0;r<t.length;r++)(d=h("."+t[r],e)).find("img").replaceWith(function(){return this.alt}),d=d.text(),h(':input[name="'+t[r]+'"]',s).val(d);if("open"===h(".comment_status",e).text()&&h('input[name="comment_status"]',s).prop("checked",!0),"open"===h(".ping_status",e).text()&&h('input[name="ping_status"]',s).prop("checked",!0),"sticky"===h(".sticky",e).text()&&h('input[name="sticky"]',s).prop("checked",!0),h(".post_category",e).each(function(){var t,e=h(this).text();e&&(t=h(this).attr("id").replace("_"+a,""),h("ul."+t+"-checklist :checkbox",s).val(e.split(",")))}),h(".tags_input",e).each(function(){var t=h(this),e=h(this).attr("id").replace("_"+a,""),i=h("textarea.tax_input_"+e,s),n=inlineEditL10n.comma;t.find("img").replaceWith(function(){return this.alt}),(t=t.text())&&(","!==n&&(t=t.replace(/,/g,n)),i.val(t)),i.wpTagsSuggest()}),"future"!==(i=h("._status",e).text())&&h('select[name="_status"] option[value="future"]',s).remove(),c=h(".inline-edit-password-input").prop("disabled",!1),"private"===i&&(h('input[name="keep_private"]',s).prop("checked",!0),c.val("").prop("disabled",!0)),0<(n=h('select[name="post_parent"] option[value="'+a+'"]',s)).length){for(o=n[0].className.split("-")[1],l=n;u&&0!==(l=l.next("option")).length;)l[0].className.split("-")[1]<=o?u=!1:(l.remove(),l=n);n.remove()}return h(s).attr("id","edit-"+a).addClass("inline-editor").show(),h(".ptitle",s).focus(),!1},save:function(n){var t,e=h(".post_status_page").val()||"";return"object"==typeof n&&(n=this.getId(n)),h("table.widefat .spinner").addClass("is-active"),t={action:"inline-save",post_type:typenow,post_ID:n,edit_date:"true",post_status:e},t=h("#edit-"+n).find(":input").serialize()+"&"+h.param(t),h.post(ajaxurl,t,function(t){var e=h("#edit-"+n+" .inline-edit-save .notice-error"),i=e.find(".error");h("table.widefat .spinner").removeClass("is-active"),h(".ac_results").hide(),t?-1!==t.indexOf("<tr")?(h(inlineEditPost.what+n).siblings("tr.hidden").addBack().remove(),h("#edit-"+n).before(t).remove(),h(inlineEditPost.what+n).hide().fadeIn(400,function(){h(this).find(".editinline").attr("aria-expanded","false").focus(),a.a11y.speak(inlineEditL10n.saved)})):(t=t.replace(/<.[^<>]*?>/g,""),e.removeClass("hidden"),i.html(t),a.a11y.speak(i.text())):(e.removeClass("hidden"),i.html(inlineEditL10n.error),a.a11y.speak(inlineEditL10n.error))},"html"),!1},revert:function(){var t=h(".widefat"),e=h(".inline-editor",t).attr("id");return e&&(h(".spinner",t).removeClass("is-active"),h(".ac_results").hide(),"bulk-edit"===e?(h("#bulk-edit",t).removeClass("inline-editor").hide().siblings(".hidden").remove(),h("#bulk-titles").empty(),h("#inlineedit").append(h("#bulk-edit")),h("#"+inlineEditPost.whichBulkButtonId).focus()):(h("#"+e).siblings("tr.hidden").addBack().remove(),e=e.substr(e.lastIndexOf("-")+1),h(this.what+e).show().find(".editinline").attr("aria-expanded","false").focus())),!1},getId:function(t){var e=h(t).closest("tr").attr("id").split("-");return e[e.length-1]}},h(document).ready(function(){inlineEditPost.init()}),h(document).on("heartbeat-tick.wp-check-locked-posts",function(t,e){var o=e["wp-check-locked-posts"]||{};h("#the-list tr").each(function(t,e){var i,n,a=e.id,s=h(e);o.hasOwnProperty(a)?s.hasClass("wp-locked")||(i=o[a],s.find(".column-title .locked-text").text(i.text),s.find(".check-column checkbox").prop("checked",!1),i.avatar_src&&(n=h('<img class="avatar avatar-18 photo" width="18" height="18" alt="" />').attr("src",i.avatar_src.replace(/&/g,"&")),s.find(".column-title .locked-avatar").empty().append(n)),s.addClass("wp-locked")):s.hasClass("wp-locked")&&s.removeClass("wp-locked").find(".locked-info span").empty()})}).on("heartbeat-send.wp-check-locked-posts",function(t,e){var i=[];h("#the-list tr").each(function(t,e){e.id&&i.push(e.id)}),i.length&&(e["wp-check-locked-posts"]=i)}).ready(function(){void 0!==a&&a.heartbeat&&a.heartbeat.interval(15)})}(jQuery,window.wp);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/inline-edit-tax.js b/srcs/wordpress/wp-admin/js/inline-edit-tax.js deleted file mode 100644 index bea0196..0000000 --- a/srcs/wordpress/wp-admin/js/inline-edit-tax.js +++ /dev/null @@ -1,294 +0,0 @@ -/** - * This file is used on the term overview page to power quick-editing terms. - * - * @output wp-admin/js/inline-edit-tax.js - */ - -/* global inlineEditL10n, ajaxurl, inlineEditTax */ - -window.wp = window.wp || {}; - -/** - * Consists of functions relevant to the inline taxonomy editor. - * - * @namespace inlineEditTax - * - * @property {string} type The type of inline edit we are currently on. - * @property {string} what The type property with a hash prefixed and a dash - * suffixed. - */ -( function( $, wp ) { - -window.inlineEditTax = { - - /** - * Initializes the inline taxonomy editor by adding event handlers to be able to - * quick edit. - * - * @since 2.7.0 - * - * @this inlineEditTax - * @memberof inlineEditTax - * @returns {void} - */ - init : function() { - var t = this, row = $('#inline-edit'); - - t.type = $('#the-list').attr('data-wp-lists').substr(5); - t.what = '#'+t.type+'-'; - - $( '#the-list' ).on( 'click', '.editinline', function() { - $( this ).attr( 'aria-expanded', 'true' ); - inlineEditTax.edit( this ); - }); - - /** - * Cancels inline editing when pressing escape inside the inline editor. - * - * @param {Object} e The keyup event that has been triggered. - */ - row.keyup( function( e ) { - // 27 = [escape] - if ( e.which === 27 ) { - return inlineEditTax.revert(); - } - }); - - /** - * Cancels inline editing when clicking the cancel button. - */ - $( '.cancel', row ).click( function() { - return inlineEditTax.revert(); - }); - - /** - * Saves the inline edits when clicking the save button. - */ - $( '.save', row ).click( function() { - return inlineEditTax.save(this); - }); - - /** - * Saves the inline edits when pressing enter inside the inline editor. - */ - $( 'input, select', row ).keydown( function( e ) { - // 13 = [enter] - if ( e.which === 13 ) { - return inlineEditTax.save( this ); - } - }); - - /** - * Saves the inline edits on submitting the inline edit form. - */ - $( '#posts-filter input[type="submit"]' ).mousedown( function() { - t.revert(); - }); - }, - - /** - * Toggles the quick edit based on if it is currently shown or hidden. - * - * @since 2.7.0 - * - * @this inlineEditTax - * @memberof inlineEditTax - * - * @param {HTMLElement} el An element within the table row or the table row - * itself that we want to quick edit. - * @returns {void} - */ - toggle : function(el) { - var t = this; - - $(t.what+t.getId(el)).css('display') === 'none' ? t.revert() : t.edit(el); - }, - - /** - * Shows the quick editor - * - * @since 2.7.0 - * - * @this inlineEditTax - * @memberof inlineEditTax - * - * @param {string|HTMLElement} id The ID of the term we want to quick edit or an - * element within the table row or the - * table row itself. - * @returns {boolean} Always returns false. - */ - edit : function(id) { - var editRow, rowData, val, - t = this; - t.revert(); - - // Makes sure we can pass an HTMLElement as the ID. - if ( typeof(id) === 'object' ) { - id = t.getId(id); - } - - editRow = $('#inline-edit').clone(true), rowData = $('#inline_'+id); - $( 'td', editRow ).attr( 'colspan', $( 'th:visible, td:visible', '.wp-list-table.widefat:first thead' ).length ); - - $(t.what+id).hide().after(editRow).after('<tr class="hidden"></tr>'); - - val = $('.name', rowData); - val.find( 'img' ).replaceWith( function() { return this.alt; } ); - val = val.text(); - $(':input[name="name"]', editRow).val( val ); - - val = $('.slug', rowData); - val.find( 'img' ).replaceWith( function() { return this.alt; } ); - val = val.text(); - $(':input[name="slug"]', editRow).val( val ); - - $(editRow).attr('id', 'edit-'+id).addClass('inline-editor').show(); - $('.ptitle', editRow).eq(0).focus(); - - return false; - }, - - /** - * Saves the quick edit data. - * - * Saves the quick edit data to the server and replaces the table row with the - * HTML retrieved from the server. - * - * @since 2.7.0 - * - * @this inlineEditTax - * @memberof inlineEditTax - * - * @param {string|HTMLElement} id The ID of the term we want to quick edit or an - * element within the table row or the - * table row itself. - * @returns {boolean} Always returns false. - */ - save : function(id) { - var params, fields, tax = $('input[name="taxonomy"]').val() || ''; - - // Makes sure we can pass an HTMLElement as the ID. - if( typeof(id) === 'object' ) { - id = this.getId(id); - } - - $( 'table.widefat .spinner' ).addClass( 'is-active' ); - - params = { - action: 'inline-save-tax', - tax_type: this.type, - tax_ID: id, - taxonomy: tax - }; - - fields = $('#edit-'+id).find(':input').serialize(); - params = fields + '&' + $.param(params); - - // Do the ajax request to save the data to the server. - $.post( ajaxurl, params, - /** - * Handles the response from the server - * - * Handles the response from the server, replaces the table row with the response - * from the server. - * - * @param {string} r The string with which to replace the table row. - */ - function(r) { - var row, new_id, option_value, - $errorNotice = $( '#edit-' + id + ' .inline-edit-save .notice-error' ), - $error = $errorNotice.find( '.error' ); - - $( 'table.widefat .spinner' ).removeClass( 'is-active' ); - - if (r) { - if ( -1 !== r.indexOf( '<tr' ) ) { - $(inlineEditTax.what+id).siblings('tr.hidden').addBack().remove(); - new_id = $(r).attr('id'); - - $('#edit-'+id).before(r).remove(); - - if ( new_id ) { - option_value = new_id.replace( inlineEditTax.type + '-', '' ); - row = $( '#' + new_id ); - } else { - option_value = id; - row = $( inlineEditTax.what + id ); - } - - // Update the value in the Parent dropdown. - $( '#parent' ).find( 'option[value=' + option_value + ']' ).text( row.find( '.row-title' ).text() ); - - row.hide().fadeIn( 400, function() { - // Move focus back to the Quick Edit button. - row.find( '.editinline' ) - .attr( 'aria-expanded', 'false' ) - .focus(); - wp.a11y.speak( inlineEditL10n.saved ); - }); - - } else { - $errorNotice.removeClass( 'hidden' ); - $error.html( r ); - /* - * Some error strings may contain HTML entities (e.g. `“`), let's use - * the HTML element's text. - */ - wp.a11y.speak( $error.text() ); - } - } else { - $errorNotice.removeClass( 'hidden' ); - $error.html( inlineEditL10n.error ); - wp.a11y.speak( inlineEditL10n.error ); - } - } - ); - - // Prevent submitting the form when pressing Enter on a focused field. - return false; - }, - - /** - * Closes the quick edit form. - * - * @since 2.7.0 - * - * @this inlineEditTax - * @memberof inlineEditTax - * @returns {void} - */ - revert : function() { - var id = $('table.widefat tr.inline-editor').attr('id'); - - if ( id ) { - $( 'table.widefat .spinner' ).removeClass( 'is-active' ); - $('#'+id).siblings('tr.hidden').addBack().remove(); - id = id.substr( id.lastIndexOf('-') + 1 ); - - // Show the taxonomy row and move focus back to the Quick Edit button. - $( this.what + id ).show().find( '.editinline' ) - .attr( 'aria-expanded', 'false' ) - .focus(); - } - }, - - /** - * Retrieves the ID of the term of the element inside the table row. - * - * @since 2.7.0 - * - * @memberof inlineEditTax - * - * @param {HTMLElement} o An element within the table row or the table row itself. - * @returns {string} The ID of the term based on the element. - */ - getId : function(o) { - var id = o.tagName === 'TR' ? o.id : $(o).parents('tr').attr('id'), parts = id.split('-'); - - return parts[parts.length - 1]; - } -}; - -$(document).ready(function(){inlineEditTax.init();}); - -})( jQuery, window.wp ); diff --git a/srcs/wordpress/wp-admin/js/inline-edit-tax.min.js b/srcs/wordpress/wp-admin/js/inline-edit-tax.min.js deleted file mode 100644 index 4b3df35..0000000 --- a/srcs/wordpress/wp-admin/js/inline-edit-tax.min.js +++ /dev/null @@ -1 +0,0 @@ -window.wp=window.wp||{},function(s,l){window.inlineEditTax={init:function(){var t=this,i=s("#inline-edit");t.type=s("#the-list").attr("data-wp-lists").substr(5),t.what="#"+t.type+"-",s("#the-list").on("click",".editinline",function(){s(this).attr("aria-expanded","true"),inlineEditTax.edit(this)}),i.keyup(function(t){if(27===t.which)return inlineEditTax.revert()}),s(".cancel",i).click(function(){return inlineEditTax.revert()}),s(".save",i).click(function(){return inlineEditTax.save(this)}),s("input, select",i).keydown(function(t){if(13===t.which)return inlineEditTax.save(this)}),s('#posts-filter input[type="submit"]').mousedown(function(){t.revert()})},toggle:function(t){var i=this;"none"===s(i.what+i.getId(t)).css("display")?i.revert():i.edit(t)},edit:function(t){var i,e,n,a=this;return a.revert(),"object"==typeof t&&(t=a.getId(t)),i=s("#inline-edit").clone(!0),e=s("#inline_"+t),s("td",i).attr("colspan",s("th:visible, td:visible",".wp-list-table.widefat:first thead").length),s(a.what+t).hide().after(i).after('<tr class="hidden"></tr>'),(n=s(".name",e)).find("img").replaceWith(function(){return this.alt}),n=n.text(),s(':input[name="name"]',i).val(n),(n=s(".slug",e)).find("img").replaceWith(function(){return this.alt}),n=n.text(),s(':input[name="slug"]',i).val(n),s(i).attr("id","edit-"+t).addClass("inline-editor").show(),s(".ptitle",i).eq(0).focus(),!1},save:function(d){var t,i=s('input[name="taxonomy"]').val()||"";return"object"==typeof d&&(d=this.getId(d)),s("table.widefat .spinner").addClass("is-active"),t={action:"inline-save-tax",tax_type:this.type,tax_ID:d,taxonomy:i},t=s("#edit-"+d).find(":input").serialize()+"&"+s.param(t),s.post(ajaxurl,t,function(t){var i,e,n,a=s("#edit-"+d+" .inline-edit-save .notice-error"),r=a.find(".error");s("table.widefat .spinner").removeClass("is-active"),t?-1!==t.indexOf("<tr")?(s(inlineEditTax.what+d).siblings("tr.hidden").addBack().remove(),e=s(t).attr("id"),s("#edit-"+d).before(t).remove(),i=e?(n=e.replace(inlineEditTax.type+"-",""),s("#"+e)):(n=d,s(inlineEditTax.what+d)),s("#parent").find("option[value="+n+"]").text(i.find(".row-title").text()),i.hide().fadeIn(400,function(){i.find(".editinline").attr("aria-expanded","false").focus(),l.a11y.speak(inlineEditL10n.saved)})):(a.removeClass("hidden"),r.html(t),l.a11y.speak(r.text())):(a.removeClass("hidden"),r.html(inlineEditL10n.error),l.a11y.speak(inlineEditL10n.error))}),!1},revert:function(){var t=s("table.widefat tr.inline-editor").attr("id");t&&(s("table.widefat .spinner").removeClass("is-active"),s("#"+t).siblings("tr.hidden").addBack().remove(),t=t.substr(t.lastIndexOf("-")+1),s(this.what+t).show().find(".editinline").attr("aria-expanded","false").focus())},getId:function(t){var i=("TR"===t.tagName?t.id:s(t).parents("tr").attr("id")).split("-");return i[i.length-1]}},s(document).ready(function(){inlineEditTax.init()})}(jQuery,window.wp);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/iris.min.js b/srcs/wordpress/wp-admin/js/iris.min.js deleted file mode 100644 index e9ae4b6..0000000 --- a/srcs/wordpress/wp-admin/js/iris.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! Iris Color Picker - v1.1.0-beta - 2016-10-25 -* https://github.com/Automattic/Iris -* Copyright (c) 2016 Matt Wiebe; Licensed GPLv2 */ -!function(a,b){function c(){var b,c,d="backgroundImage";j?k="filter":(b=a('<div id="iris-gradtest" />'),c="linear-gradient(top,#fff,#000)",a.each(l,function(a,e){if(b.css(d,e+c),b.css(d).match("gradient"))return k=a,!1}),k===!1&&(b.css("background","-webkit-gradient(linear,0% 0%,0% 100%,from(#fff),to(#000))"),b.css(d).match("gradient")&&(k="webkit")),b.remove())}function d(b,c){return b="top"===b?"top":"left",c=a.isArray(c)?c:Array.prototype.slice.call(arguments,1),"webkit"===k?f(b,c):l[k]+"linear-gradient("+b+", "+c.join(", ")+")"}function e(b,c){var d,e,f,h,i,j,k,l,m;b="top"===b?"top":"left",c=a.isArray(c)?c:Array.prototype.slice.call(arguments,1),d="top"===b?0:1,e=a(this),f=c.length-1,h="filter",i=1===d?"left":"top",j=1===d?"right":"bottom",k=1===d?"height":"width",l='<div class="iris-ie-gradient-shim" style="position:absolute;'+k+":100%;"+i+":%start%;"+j+":%end%;"+h+':%filter%;" data-color:"%color%"></div>',m="","static"===e.css("position")&&e.css({position:"relative"}),c=g(c),a.each(c,function(a,b){var e,g,h;return a!==f&&(e=c[a+1],void(b.stop!==e.stop&&(g=100-parseFloat(e.stop)+"%",b.octoHex=new Color(b.color).toIEOctoHex(),e.octoHex=new Color(e.color).toIEOctoHex(),h="progid:DXImageTransform.Microsoft.Gradient(GradientType="+d+", StartColorStr='"+b.octoHex+"', EndColorStr='"+e.octoHex+"')",m+=l.replace("%start%",b.stop).replace("%end%",g).replace("%filter%",h))))}),e.find(".iris-ie-gradient-shim").remove(),a(m).prependTo(e)}function f(b,c){var d=[];return b="top"===b?"0% 0%,0% 100%,":"0% 100%,100% 100%,",c=g(c),a.each(c,function(a,b){d.push("color-stop("+parseFloat(b.stop)/100+", "+b.color+")")}),"-webkit-gradient(linear,"+b+d.join(",")+")"}function g(b){var c=[],d=[],e=[],f=b.length-1;return a.each(b,function(a,b){var e=b,f=!1,g=b.match(/1?[0-9]{1,2}%$/);g&&(e=b.replace(/\s?1?[0-9]{1,2}%$/,""),f=g.shift()),c.push(e),d.push(f)}),d[0]===!1&&(d[0]="0%"),d[f]===!1&&(d[f]="100%"),d=h(d),a.each(d,function(a){e[a]={color:c[a],stop:d[a]}}),e}function h(b){var c,d,e,f,g=0,i=b.length-1,j=0,k=!1;if(b.length<=2||a.inArray(!1,b)<0)return b;for(;j<b.length-1;)k||b[j]!==!1?k&&b[j]!==!1&&(i=j,j=b.length):(g=j-1,k=!0),j++;for(d=i-g,f=parseInt(b[g].replace("%"),10),c=(parseFloat(b[i].replace("%"))-f)/d,j=g+1,e=1;j<i;)b[j]=f+e*c+"%",e++,j++;return h(b)}var i,j,k,l,m,n,o,p,q;return i='<div class="iris-picker"><div class="iris-picker-inner"><div class="iris-square"><a class="iris-square-value" href="#"><span class="iris-square-handle ui-slider-handle"></span></a><div class="iris-square-inner iris-square-horiz"></div><div class="iris-square-inner iris-square-vert"></div></div><div class="iris-slider iris-strip"><div class="iris-slider-offset"></div></div></div></div>',m='.iris-picker{display:block;position:relative}.iris-picker,.iris-picker *{-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input+.iris-picker{margin-top:4px}.iris-error{background-color:#ffafaf}.iris-border{border-radius:3px;border:1px solid #aaa;width:200px;background-color:#fff}.iris-picker-inner{position:absolute;top:0;right:0;left:0;bottom:0}.iris-border .iris-picker-inner{top:10px;right:10px;left:10px;bottom:10px}.iris-picker .iris-square-inner{position:absolute;left:0;right:0;top:0;bottom:0}.iris-picker .iris-square,.iris-picker .iris-slider,.iris-picker .iris-square-inner,.iris-picker .iris-palette{border-radius:3px;box-shadow:inset 0 0 5px rgba(0,0,0,.4);height:100%;width:12.5%;float:left;margin-right:5%}.iris-only-strip .iris-slider{width:100%}.iris-picker .iris-square{width:76%;margin-right:10%;position:relative}.iris-only-strip .iris-square{display:none}.iris-picker .iris-square-inner{width:auto;margin:0}.iris-ie-9 .iris-square,.iris-ie-9 .iris-slider,.iris-ie-9 .iris-square-inner,.iris-ie-9 .iris-palette{box-shadow:none;border-radius:0}.iris-ie-9 .iris-square,.iris-ie-9 .iris-slider,.iris-ie-9 .iris-palette{outline:1px solid rgba(0,0,0,.1)}.iris-ie-lt9 .iris-square,.iris-ie-lt9 .iris-slider,.iris-ie-lt9 .iris-square-inner,.iris-ie-lt9 .iris-palette{outline:1px solid #aaa}.iris-ie-lt9 .iris-square .ui-slider-handle{outline:1px solid #aaa;background-color:#fff;-ms-filter:"alpha(Opacity=30)"}.iris-ie-lt9 .iris-square .iris-square-handle{background:0 0;border:3px solid #fff;-ms-filter:"alpha(Opacity=50)"}.iris-picker .iris-strip{margin-right:0;position:relative}.iris-picker .iris-strip .ui-slider-handle{position:absolute;background:0 0;margin:0;right:-3px;left:-3px;border:4px solid #aaa;border-width:4px 3px;width:auto;height:6px;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.2);opacity:.9;z-index:5;cursor:ns-resize}.iris-strip-horiz .iris-strip .ui-slider-handle{right:auto;left:auto;bottom:-3px;top:-3px;height:auto;width:6px;cursor:ew-resize}.iris-strip .ui-slider-handle:before{content:" ";position:absolute;left:-2px;right:-2px;top:-3px;bottom:-3px;border:2px solid #fff;border-radius:3px}.iris-picker .iris-slider-offset{position:absolute;top:11px;left:0;right:0;bottom:-3px;width:auto;height:auto;background:transparent;border:0;border-radius:0}.iris-strip-horiz .iris-slider-offset{top:0;bottom:0;right:11px;left:-3px}.iris-picker .iris-square-handle{background:transparent;border:5px solid #aaa;border-radius:50%;border-color:rgba(128,128,128,.5);box-shadow:none;width:12px;height:12px;position:absolute;left:-10px;top:-10px;cursor:move;opacity:1;z-index:10}.iris-picker .ui-state-focus .iris-square-handle{opacity:.8}.iris-picker .iris-square-handle:hover{border-color:#999}.iris-picker .iris-square-value:focus .iris-square-handle{box-shadow:0 0 2px rgba(0,0,0,.75);opacity:.8}.iris-picker .iris-square-handle:hover::after{border-color:#fff}.iris-picker .iris-square-handle::after{position:absolute;bottom:-4px;right:-4px;left:-4px;top:-4px;border:3px solid #f9f9f9;border-color:rgba(255,255,255,.8);border-radius:50%;content:" "}.iris-picker .iris-square-value{width:8px;height:8px;position:absolute}.iris-ie-lt9 .iris-square-value,.iris-mozilla .iris-square-value{width:1px;height:1px}.iris-palette-container{position:absolute;bottom:0;left:0;margin:0;padding:0}.iris-border .iris-palette-container{left:10px;bottom:10px}.iris-picker .iris-palette{margin:0;cursor:pointer}.iris-square-handle,.ui-slider-handle{border:0;outline:0}',o=navigator.userAgent.toLowerCase(),p="Microsoft Internet Explorer"===navigator.appName,q=p?parseFloat(o.match(/msie ([0-9]{1,}[\.0-9]{0,})/)[1]):0,j=p&&q<10,k=!1,l=["-moz-","-webkit-","-o-","-ms-"],j&&q<=7?(a.fn.iris=a.noop,void(a.support.iris=!1)):(a.support.iris=!0,a.fn.gradient=function(){var b=arguments;return this.each(function(){j?e.apply(this,b):a(this).css("backgroundImage",d.apply(this,b))})},a.fn.rainbowGradient=function(b,c){var d,e,f,g;for(b=b||"top",d=a.extend({},{s:100,l:50},c),e="hsl(%h%,"+d.s+"%,"+d.l+"%)",f=0,g=[];f<=360;)g.push(e.replace("%h%",f)),f+=30;return this.each(function(){a(this).gradient(b,g)})},n={options:{color:!1,mode:"hsl",controls:{horiz:"s",vert:"l",strip:"h"},hide:!0,border:!0,target:!1,width:200,palettes:!1,type:"full",slider:"horizontal"},_color:"",_palettes:["#000","#fff","#d33","#d93","#ee2","#81d742","#1e73be","#8224e3"],_inited:!1,_defaultHSLControls:{horiz:"s",vert:"l",strip:"h"},_defaultHSVControls:{horiz:"h",vert:"v",strip:"s"},_scale:{h:360,s:100,l:100,v:100},_create:function(){var b=this,d=b.element,e=b.options.color||d.val();k===!1&&c(),d.is("input")?(b.options.target?b.picker=a(i).appendTo(b.options.target):b.picker=a(i).insertAfter(d),b._addInputListeners(d)):(d.append(i),b.picker=d.find(".iris-picker")),p?9===q?b.picker.addClass("iris-ie-9"):q<=8&&b.picker.addClass("iris-ie-lt9"):o.indexOf("compatible")<0&&o.indexOf("khtml")<0&&o.match(/mozilla/)&&b.picker.addClass("iris-mozilla"),b.options.palettes&&b._addPalettes(),b.onlySlider="hue"===b.options.type,b.horizontalSlider=b.onlySlider&&"horizontal"===b.options.slider,b.onlySlider&&(b.options.controls.strip="h",e||(e="hsl(10,100,50)")),b._color=new Color(e).setHSpace(b.options.mode),b.options.color=b._color.toString(),b.controls={square:b.picker.find(".iris-square"),squareDrag:b.picker.find(".iris-square-value"),horiz:b.picker.find(".iris-square-horiz"),vert:b.picker.find(".iris-square-vert"),strip:b.picker.find(".iris-strip"),stripSlider:b.picker.find(".iris-strip .iris-slider-offset")},"hsv"===b.options.mode&&b._has("l",b.options.controls)?b.options.controls=b._defaultHSVControls:"hsl"===b.options.mode&&b._has("v",b.options.controls)&&(b.options.controls=b._defaultHSLControls),b.hue=b._color.h(),b.options.hide&&b.picker.hide(),b.options.border&&!b.onlySlider&&b.picker.addClass("iris-border"),b._initControls(),b.active="external",b._dimensions(),b._change()},_has:function(b,c){var d=!1;return a.each(c,function(a,c){if(b===c)return d=!0,!1}),d},_addPalettes:function(){var b=a('<div class="iris-palette-container" />'),c=a('<a class="iris-palette" tabindex="0" />'),d=a.isArray(this.options.palettes)?this.options.palettes:this._palettes;this.picker.find(".iris-palette-container").length&&(b=this.picker.find(".iris-palette-container").detach().html("")),a.each(d,function(a,d){c.clone().data("color",d).css("backgroundColor",d).appendTo(b).height(10).width(10)}),this.picker.append(b)},_paint:function(){var a=this;a.horizontalSlider?a._paintDimension("left","strip"):a._paintDimension("top","strip"),a._paintDimension("top","vert"),a._paintDimension("left","horiz")},_paintDimension:function(a,b){var c,d=this,e=d._color,f=d.options.mode,g=d._getHSpaceColor(),h=d.controls[b],i=d.options.controls;if(b!==d.active&&("square"!==d.active||"strip"===b))switch(i[b]){case"h":if("hsv"===f){switch(g=e.clone(),b){case"horiz":g[i.vert](100);break;case"vert":g[i.horiz](100);break;case"strip":g.setHSpace("hsl")}c=g.toHsl()}else c="strip"===b?{s:g.s,l:g.l}:{s:100,l:g.l};h.rainbowGradient(a,c);break;case"s":"hsv"===f?"vert"===b?c=[e.clone().a(0).s(0).toCSS("rgba"),e.clone().a(1).s(0).toCSS("rgba")]:"strip"===b?c=[e.clone().s(100).toCSS("hsl"),e.clone().s(0).toCSS("hsl")]:"horiz"===b&&(c=["#fff","hsl("+g.h+",100%,50%)"]):c="vert"===b&&"h"===d.options.controls.horiz?["hsla(0, 0%, "+g.l+"%, 0)","hsla(0, 0%, "+g.l+"%, 1)"]:["hsl("+g.h+",0%,50%)","hsl("+g.h+",100%,50%)"],h.gradient(a,c);break;case"l":c="strip"===b?["hsl("+g.h+",100%,100%)","hsl("+g.h+", "+g.s+"%,50%)","hsl("+g.h+",100%,0%)"]:["#fff","rgba(255,255,255,0) 50%","rgba(0,0,0,0) 50%","rgba(0,0,0,1)"],h.gradient(a,c);break;case"v":c="strip"===b?[e.clone().v(100).toCSS(),e.clone().v(0).toCSS()]:["rgba(0,0,0,0)","#000"],h.gradient(a,c)}},_getHSpaceColor:function(){return"hsv"===this.options.mode?this._color.toHsv():this._color.toHsl()},_stripOnlyDimensions:function(){var a=this,b=this.options.width,c=.12*b;a.horizontalSlider?a.picker.css({width:b,height:c}).addClass("iris-only-strip iris-strip-horiz"):a.picker.css({width:c,height:b}).addClass("iris-only-strip iris-strip-vert")},_dimensions:function(b){if("hue"===this.options.type)return this._stripOnlyDimensions();var c,d,e,f,g=this,h=g.options,i=g.controls,j=i.square,k=g.picker.find(".iris-strip"),l="77.5%",m="12%",n=20,o=h.border?h.width-n:h.width,p=a.isArray(h.palettes)?h.palettes.length:g._palettes.length;return b&&(j.css("width",""),k.css("width",""),g.picker.css({width:"",height:""})),l=o*(parseFloat(l)/100),m=o*(parseFloat(m)/100),c=h.border?l+n:l,j.width(l).height(l),k.height(l).width(m),g.picker.css({width:h.width,height:c}),h.palettes?(d=2*l/100,f=l-(p-1)*d,e=f/p,g.picker.find(".iris-palette").each(function(b){var c=0===b?0:d;a(this).css({width:e,height:e,marginLeft:c})}),g.picker.css("paddingBottom",e+d),void k.height(e+d+l)):g.picker.css("paddingBottom","")},_addInputListeners:function(a){var b=this,c=100,d=function(c){var d=new Color(a.val()),e=a.val().replace(/^#/,"");a.removeClass("iris-error"),d.error?""!==e&&a.addClass("iris-error"):d.toString()!==b._color.toString()&&("keyup"===c.type&&e.match(/^[0-9a-fA-F]{3}$/)||b._setOption("color",d.toString()))};a.on("change",d).on("keyup",b._debounce(d,c)),b.options.hide&&a.one("focus",function(){b.show()})},_initControls:function(){var b=this,c=b.controls,d=c.square,e=b.options.controls,f=b._scale[e.strip],g=b.horizontalSlider?"horizontal":"vertical";c.stripSlider.slider({orientation:g,max:f,slide:function(a,c){b.active="strip","h"===e.strip&&"vertical"===g&&(c.value=f-c.value),b._color[e.strip](c.value),b._change.apply(b,arguments)}}),c.squareDrag.draggable({containment:c.square.find(".iris-square-inner"),zIndex:1e3,cursor:"move",drag:function(a,c){b._squareDrag(a,c)},start:function(){d.addClass("iris-dragging"),a(this).addClass("ui-state-focus")},stop:function(){d.removeClass("iris-dragging"),a(this).removeClass("ui-state-focus")}}).on("mousedown mouseup",function(c){var d="ui-state-focus";c.preventDefault(),"mousedown"===c.type?(b.picker.find("."+d).removeClass(d).blur(),a(this).addClass(d).focus()):a(this).removeClass(d)}).on("keydown",function(a){var d=c.square,e=c.squareDrag,f=e.position(),g=b.options.width/100;switch(a.altKey&&(g*=10),a.keyCode){case 37:f.left-=g;break;case 38:f.top-=g;break;case 39:f.left+=g;break;case 40:f.top+=g;break;default:return!0}f.left=Math.max(0,Math.min(f.left,d.width())),f.top=Math.max(0,Math.min(f.top,d.height())),e.css(f),b._squareDrag(a,{position:f}),a.preventDefault()}),d.mousedown(function(c){var d,e;1===c.which&&a(c.target).is("div")&&(d=b.controls.square.offset(),e={top:c.pageY-d.top,left:c.pageX-d.left},c.preventDefault(),b._squareDrag(c,{position:e}),c.target=b.controls.squareDrag.get(0),b.controls.squareDrag.css(e).trigger(c))}),b.options.palettes&&b._paletteListeners()},_paletteListeners:function(){var b=this;b.picker.find(".iris-palette-container").on("click.palette",".iris-palette",function(){b._color.fromCSS(a(this).data("color")),b.active="external",b._change()}).on("keydown.palette",".iris-palette",function(b){return 13!==b.keyCode&&32!==b.keyCode||(b.stopPropagation(),void a(this).click())})},_squareDrag:function(a,b){var c=this,d=c.options.controls,e=c._squareDimensions(),f=Math.round((e.h-b.position.top)/e.h*c._scale[d.vert]),g=c._scale[d.horiz]-Math.round((e.w-b.position.left)/e.w*c._scale[d.horiz]);c._color[d.horiz](g)[d.vert](f),c.active="square",c._change.apply(c,arguments)},_setOption:function(b,c){var d,e,f,g=this,h=g.options[b],i=!1;switch(g.options[b]=c,b){case"color":g.onlySlider?(c=parseInt(c,10),c=isNaN(c)||c<0||c>359?h:"hsl("+c+",100,50)",g.options.color=g.options[b]=c,g._color=new Color(c).setHSpace(g.options.mode),g.active="external",g._change()):(c=""+c,d=c.replace(/^#/,""),e=new Color(c).setHSpace(g.options.mode),e.error?g.options[b]=h:(g._color=e,g.options.color=g.options[b]=g._color.toString(),g.active="external",g._change()));break;case"palettes":i=!0,c?g._addPalettes():g.picker.find(".iris-palette-container").remove(),h||g._paletteListeners();break;case"width":i=!0;break;case"border":i=!0,f=c?"addClass":"removeClass",g.picker[f]("iris-border");break;case"mode":case"controls":if(h===c)return;return f=g.element,h=g.options,h.hide=!g.picker.is(":visible"),g.destroy(),g.picker.remove(),a(g.element).iris(h)}i&&g._dimensions(!0)},_squareDimensions:function(a){var c,d,e=this.controls.square;return a!==b&&e.data("dimensions")?e.data("dimensions"):(d=this.controls.squareDrag,c={w:e.width(),h:e.height()},e.data("dimensions",c),c)},_isNonHueControl:function(a,b){return"square"===a&&"h"===this.options.controls.strip||"external"!==b&&("h"!==b||"strip"!==a)},_change:function(){var b=this,c=b.controls,d=b._getHSpaceColor(),e=["square","strip"],f=b.options.controls,g=f[b.active]||"external",h=b.hue;"strip"===b.active?e=[]:"external"!==b.active&&e.pop(),a.each(e,function(a,e){var g,h,i;if(e!==b.active)switch(e){case"strip":g="h"!==f.strip||b.horizontalSlider?d[f.strip]:b._scale[f.strip]-d[f.strip],c.stripSlider.slider("value",g);break;case"square":h=b._squareDimensions(),i={left:d[f.horiz]/b._scale[f.horiz]*h.w,top:h.h-d[f.vert]/b._scale[f.vert]*h.h},b.controls.squareDrag.css(i)}}),d.h!==h&&b._isNonHueControl(b.active,g)&&b._color.h(h),b.hue=b._color.h(),b.options.color=b._color.toString(),b._inited&&b._trigger("change",{type:b.active},{color:b._color}),b.element.is(":input")&&!b._color.error&&(b.element.removeClass("iris-error"),b.onlySlider?b.element.val()!==b.hue&&b.element.val(b.hue):b.element.val()!==b._color.toString()&&b.element.val(b._color.toString())),b._paint(),b._inited=!0,b.active=!1},_debounce:function(a,b,c){var d,e;return function(){var f,g,h=this,i=arguments;return f=function(){d=null,c||(e=a.apply(h,i))},g=c&&!d,clearTimeout(d),d=setTimeout(f,b),g&&(e=a.apply(h,i)),e}},show:function(){this.picker.show()},hide:function(){this.picker.hide()},toggle:function(){this.picker.toggle()},color:function(a){return a===!0?this._color.clone():a===b?this._color.toString():void this.option("color",a)}},a.widget("a8c.iris",n),void a('<style id="iris-css">'+m+"</style>").appendTo("head"))}(jQuery),function(a,b){var c=function(a,b){return this instanceof c?this._init(a,b):new c(a,b)};c.fn=c.prototype={_color:0,_alpha:1,error:!1,_hsl:{h:0,s:0,l:0},_hsv:{h:0,s:0,v:0},_hSpace:"hsl",_init:function(a){var c="noop";switch(typeof a){case"object":return a.a!==b&&this.a(a.a),c=a.r!==b?"fromRgb":a.l!==b?"fromHsl":a.v!==b?"fromHsv":c,this[c](a);case"string":return this.fromCSS(a);case"number":return this.fromInt(parseInt(a,10))}return this},_error:function(){return this.error=!0,this},clone:function(){for(var a=new c(this.toInt()),b=["_alpha","_hSpace","_hsl","_hsv","error"],d=b.length-1;d>=0;d--)a[b[d]]=this[b[d]];return a},setHSpace:function(a){return this._hSpace="hsv"===a?a:"hsl",this},noop:function(){return this},fromCSS:function(a){var b,c=/^(rgb|hs(l|v))a?\(/;if(this.error=!1,a=a.replace(/^\s+/,"").replace(/\s+$/,"").replace(/;$/,""),a.match(c)&&a.match(/\)$/)){if(b=a.replace(/(\s|%)/g,"").replace(c,"").replace(/,?\);?$/,"").split(","),b.length<3)return this._error();if(4===b.length&&(this.a(parseFloat(b.pop())),this.error))return this;for(var d=b.length-1;d>=0;d--)if(b[d]=parseInt(b[d],10),isNaN(b[d]))return this._error();return a.match(/^rgb/)?this.fromRgb({r:b[0],g:b[1],b:b[2]}):a.match(/^hsv/)?this.fromHsv({h:b[0],s:b[1],v:b[2]}):this.fromHsl({h:b[0],s:b[1],l:b[2]})}return this.fromHex(a)},fromRgb:function(a,c){return"object"!=typeof a||a.r===b||a.g===b||a.b===b?this._error():(this.error=!1,this.fromInt(parseInt((a.r<<16)+(a.g<<8)+a.b,10),c))},fromHex:function(a){return a=a.replace(/^#/,"").replace(/^0x/,""),3===a.length&&(a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]),this.error=!/^[0-9A-F]{6}$/i.test(a),this.fromInt(parseInt(a,16))},fromHsl:function(a){var c,d,e,f,g,h,i,j;return"object"!=typeof a||a.h===b||a.s===b||a.l===b?this._error():(this._hsl=a,this._hSpace="hsl",h=a.h/360,i=a.s/100,j=a.l/100,0===i?c=d=e=j:(f=j<.5?j*(1+i):j+i-j*i,g=2*j-f,c=this.hue2rgb(g,f,h+1/3),d=this.hue2rgb(g,f,h),e=this.hue2rgb(g,f,h-1/3)),this.fromRgb({r:255*c,g:255*d,b:255*e},!0))},fromHsv:function(a){var c,d,e,f,g,h,i,j,k,l,m;if("object"!=typeof a||a.h===b||a.s===b||a.v===b)return this._error();switch(this._hsv=a,this._hSpace="hsv",c=a.h/360,d=a.s/100,e=a.v/100,i=Math.floor(6*c),j=6*c-i,k=e*(1-d),l=e*(1-j*d),m=e*(1-(1-j)*d),i%6){case 0:f=e,g=m,h=k;break;case 1:f=l,g=e,h=k;break;case 2:f=k,g=e,h=m;break;case 3:f=k,g=l,h=e;break;case 4:f=m,g=k,h=e;break;case 5:f=e,g=k,h=l}return this.fromRgb({r:255*f,g:255*g,b:255*h},!0)},fromInt:function(a,c){return this._color=parseInt(a,10),isNaN(this._color)&&(this._color=0),this._color>16777215?this._color=16777215:this._color<0&&(this._color=0),c===b&&(this._hsv.h=this._hsv.s=this._hsl.h=this._hsl.s=0),this},hue2rgb:function(a,b,c){return c<0&&(c+=1),c>1&&(c-=1),c<1/6?a+6*(b-a)*c:c<.5?b:c<2/3?a+(b-a)*(2/3-c)*6:a},toString:function(){var a=parseInt(this._color,10).toString(16);if(this.error)return"";if(a.length<6)for(var b=6-a.length-1;b>=0;b--)a="0"+a;return"#"+a},toCSS:function(a,b){switch(a=a||"hex",b=parseFloat(b||this._alpha),a){case"rgb":case"rgba":var c=this.toRgb();return b<1?"rgba( "+c.r+", "+c.g+", "+c.b+", "+b+" )":"rgb( "+c.r+", "+c.g+", "+c.b+" )";case"hsl":case"hsla":var d=this.toHsl();return b<1?"hsla( "+d.h+", "+d.s+"%, "+d.l+"%, "+b+" )":"hsl( "+d.h+", "+d.s+"%, "+d.l+"% )";default:return this.toString()}},toRgb:function(){return{r:255&this._color>>16,g:255&this._color>>8,b:255&this._color}},toHsl:function(){var a,b,c=this.toRgb(),d=c.r/255,e=c.g/255,f=c.b/255,g=Math.max(d,e,f),h=Math.min(d,e,f),i=(g+h)/2;if(g===h)a=b=0;else{var j=g-h;switch(b=i>.5?j/(2-g-h):j/(g+h),g){case d:a=(e-f)/j+(e<f?6:0);break;case e:a=(f-d)/j+2;break;case f:a=(d-e)/j+4}a/=6}return a=Math.round(360*a),0===a&&this._hsl.h!==a&&(a=this._hsl.h),b=Math.round(100*b),0===b&&this._hsl.s&&(b=this._hsl.s),{h:a,s:b,l:Math.round(100*i)}},toHsv:function(){var a,b,c=this.toRgb(),d=c.r/255,e=c.g/255,f=c.b/255,g=Math.max(d,e,f),h=Math.min(d,e,f),i=g,j=g-h;if(b=0===g?0:j/g,g===h)a=b=0;else{switch(g){case d:a=(e-f)/j+(e<f?6:0);break;case e:a=(f-d)/j+2;break;case f:a=(d-e)/j+4}a/=6}return a=Math.round(360*a),0===a&&this._hsv.h!==a&&(a=this._hsv.h),b=Math.round(100*b),0===b&&this._hsv.s&&(b=this._hsv.s),{h:a,s:b,v:Math.round(100*i)}},toInt:function(){return this._color},toIEOctoHex:function(){var a=this.toString(),b=parseInt(255*this._alpha,10).toString(16);return 1===b.length&&(b="0"+b),"#"+b+a.replace(/^#/,"")},toLuminosity:function(){var a=this.toRgb(),b={};for(var c in a)if(a.hasOwnProperty(c)){var d=a[c]/255;b[c]=d<=.03928?d/12.92:Math.pow((d+.055)/1.055,2.4)}return.2126*b.r+.7152*b.g+.0722*b.b},getDistanceLuminosityFrom:function(a){if(!(a instanceof c))throw"getDistanceLuminosityFrom requires a Color object";var b=this.toLuminosity(),d=a.toLuminosity();return b>d?(b+.05)/(d+.05):(d+.05)/(b+.05)},getMaxContrastColor:function(){var a=this.getDistanceLuminosityFrom(new c("#000")),b=this.getDistanceLuminosityFrom(new c("#fff")),d=a>=b?"#000":"#fff";return new c(d)},getReadableContrastingColor:function(a,d){if(!(a instanceof c))return this;var e,f,g,h=d===b?5:d,i=a.getDistanceLuminosityFrom(this);if(i>=h)return this;if(e=a.getMaxContrastColor(),f=e.getDistanceLuminosityFrom(a),f<=h)return e;for(g=0===e.toInt()?-1:1;i<h&&(this.l(g,!0),i=this.getDistanceLuminosityFrom(a),0!==this._color&&16777215!==this._color););return this},a:function(a){if(a===b)return this._alpha;var c=parseFloat(a);return isNaN(c)?this._error():(this._alpha=c,this)},darken:function(a){return a=a||5,this.l(-a,!0)},lighten:function(a){return a=a||5,this.l(a,!0)},saturate:function(a){return a=a||15,this.s(a,!0)},desaturate:function(a){return a=a||15,this.s(-a,!0)},toGrayscale:function(){return this.setHSpace("hsl").s(0)},getComplement:function(){return this.h(180,!0)},getSplitComplement:function(a){a=a||1;var b=180+30*a;return this.h(b,!0)},getAnalog:function(a){a=a||1;var b=30*a;return this.h(b,!0)},getTetrad:function(a){a=a||1;var b=60*a;return this.h(b,!0)},getTriad:function(a){a=a||1;var b=120*a;return this.h(b,!0)},_partial:function(a){var c=d[a];return function(d,e){var f=this._spaceFunc("to",c.space);return d===b?f[a]:(e===!0&&(d=f[a]+d),c.mod&&(d%=c.mod),c.range&&(d=d<c.range[0]?c.range[0]:d>c.range[1]?c.range[1]:d),f[a]=d,this._spaceFunc("from",c.space,f))}},_spaceFunc:function(a,b,c){var d=b||this._hSpace,e=a+d.charAt(0).toUpperCase()+d.substr(1);return this[e](c)}};var d={h:{mod:360},s:{range:[0,100]},l:{space:"hsl",range:[0,100]},v:{space:"hsv",range:[0,100]},r:{space:"rgb",range:[0,255]},g:{space:"rgb",range:[0,255]},b:{space:"rgb",range:[0,255]}};for(var e in d)d.hasOwnProperty(e)&&(c.fn[e]=c.fn._partial(e));"object"==typeof exports?module.exports=c:a.Color=c}(this);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/language-chooser.js b/srcs/wordpress/wp-admin/js/language-chooser.js deleted file mode 100644 index 8eb33b4..0000000 --- a/srcs/wordpress/wp-admin/js/language-chooser.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @output wp-admin/js/language-chooser.js - */ - -jQuery( function($) { -/* - * Set the correct translation to the continue button and show a spinner - * when downloading a language. - */ -var select = $( '#language' ), - submit = $( '#language-continue' ); - -if ( ! $( 'body' ).hasClass( 'language-chooser' ) ) { - return; -} - -select.focus().on( 'change', function() { - /* - * When a language is selected, set matching translation to continue button - * and attach the language attribute. - */ - var option = select.children( 'option:selected' ); - submit.attr({ - value: option.data( 'continue' ), - lang: option.attr( 'lang' ) - }); -}); - -$( 'form' ).submit( function() { - // Show spinner for languages that need to be downloaded. - if ( ! select.children( 'option:selected' ).data( 'installed' ) ) { - $( this ).find( '.step .spinner' ).css( 'visibility', 'visible' ); - } -}); - -}); diff --git a/srcs/wordpress/wp-admin/js/language-chooser.min.js b/srcs/wordpress/wp-admin/js/language-chooser.min.js deleted file mode 100644 index eb39175..0000000 --- a/srcs/wordpress/wp-admin/js/language-chooser.min.js +++ /dev/null @@ -1 +0,0 @@ -jQuery(function(n){var a=n("#language"),e=n("#language-continue");n("body").hasClass("language-chooser")&&(a.focus().on("change",function(){var n=a.children("option:selected");e.attr({value:n.data("continue"),lang:n.attr("lang")})}),n("form").submit(function(){a.children("option:selected").data("installed")||n(this).find(".step .spinner").css("visibility","visible")}))});
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/link.js b/srcs/wordpress/wp-admin/js/link.js deleted file mode 100644 index 5b73fe6..0000000 --- a/srcs/wordpress/wp-admin/js/link.js +++ /dev/null @@ -1,136 +0,0 @@ -/** - * @output wp-admin/js/link.js - */ - -/* global postboxes, deleteUserSetting, setUserSetting, getUserSetting */ - -jQuery(document).ready( function($) { - - var newCat, noSyncChecks = false, syncChecks, catAddAfter; - - $('#link_name').focus(); - // postboxes - postboxes.add_postbox_toggles('link'); - - /** - * Adds event that opens a particular category tab. - * - * @ignore - * - * @return {boolean} Always returns false to prevent the default behavior. - */ - $('#category-tabs a').click(function(){ - var t = $(this).attr('href'); - $(this).parent().addClass('tabs').siblings('li').removeClass('tabs'); - $('.tabs-panel').hide(); - $(t).show(); - if ( '#categories-all' == t ) - deleteUserSetting('cats'); - else - setUserSetting('cats','pop'); - return false; - }); - if ( getUserSetting('cats') ) - $('#category-tabs a[href="#categories-pop"]').click(); - - // Ajax Cat - newCat = $('#newcat').one( 'focus', function() { $(this).val( '' ).removeClass( 'form-input-tip' ); } ); - - /** - * After adding a new category, focus on the category add input field. - * - * @return {void} - */ - $('#link-category-add-submit').click( function() { newCat.focus(); } ); - - /** - * Synchronize category checkboxes. - * - * This function makes sure that the checkboxes are synced between the all - * categories tab and the most used categories tab. - * - * @since 2.5.0 - * - * @return {void} - */ - syncChecks = function() { - if ( noSyncChecks ) - return; - noSyncChecks = true; - var th = $(this), c = th.is(':checked'), id = th.val().toString(); - $('#in-link-category-' + id + ', #in-popular-link_category-' + id).prop( 'checked', c ); - noSyncChecks = false; - }; - - /** - * Adds event listeners to an added category. - * - * This is run on the addAfter event to make sure the correct event listeners - * are bound to the DOM elements. - * - * @since 2.5.0 - * - * @param {string} r Raw XML response returned from the server after adding a - * category. - * @param {Object} s List manager configuration object; settings for the Ajax - * request. - * - * @return {void} - */ - catAddAfter = function( r, s ) { - $(s.what + ' response_data', r).each( function() { - var t = $($(this).text()); - t.find( 'label' ).each( function() { - var th = $(this), val = th.find('input').val(), id = th.find('input')[0].id, name = $.trim( th.text() ), o; - $('#' + id).change( syncChecks ); - o = $( '<option value="' + parseInt( val, 10 ) + '"></option>' ).text( name ); - } ); - } ); - }; - - /* - * Instantiates the list manager. - * - * @see js/_enqueues/lib/lists.js - */ - $('#categorychecklist').wpList( { - // CSS class name for alternate styling. - alt: '', - - // The type of list. - what: 'link-category', - - // ID of the element the parsed Ajax response will be stored in. - response: 'category-ajax-response', - - // Callback that's run after an item got added to the list. - addAfter: catAddAfter - } ); - - // All categories is the default tab, so we delete the user setting. - $('a[href="#categories-all"]').click(function(){deleteUserSetting('cats');}); - - // Set a preference for the popular categories to cookies. - $('a[href="#categories-pop"]').click(function(){setUserSetting('cats','pop');}); - - if ( 'pop' == getUserSetting('cats') ) - $('a[href="#categories-pop"]').click(); - - /** - * Adds event handler that shows the interface controls to add a new category. - * - * @ignore - * - * @param {Event} event The event object. - * @returns {boolean} Always returns false to prevent regular link - * functionality. - */ - $('#category-add-toggle').click( function() { - $(this).parents('div:first').toggleClass( 'wp-hidden-children' ); - $('#category-tabs a[href="#categories-all"]').click(); - $('#newcategory').focus(); - return false; - } ); - - $('.categorychecklist :checkbox').change( syncChecks ).filter( ':checked' ).change(); -}); diff --git a/srcs/wordpress/wp-admin/js/link.min.js b/srcs/wordpress/wp-admin/js/link.min.js deleted file mode 100644 index a881271..0000000 --- a/srcs/wordpress/wp-admin/js/link.min.js +++ /dev/null @@ -1 +0,0 @@ -jQuery(document).ready(function(i){var t,s,e,c=!1;i("#link_name").focus(),postboxes.add_postbox_toggles("link"),i("#category-tabs a").click(function(){var t=i(this).attr("href");return i(this).parent().addClass("tabs").siblings("li").removeClass("tabs"),i(".tabs-panel").hide(),i(t).show(),"#categories-all"==t?deleteUserSetting("cats"):setUserSetting("cats","pop"),!1}),getUserSetting("cats")&&i('#category-tabs a[href="#categories-pop"]').click(),t=i("#newcat").one("focus",function(){i(this).val("").removeClass("form-input-tip")}),i("#link-category-add-submit").click(function(){t.focus()}),s=function(){if(!c){c=!0;var t=i(this),e=t.is(":checked"),a=t.val().toString();i("#in-link-category-"+a+", #in-popular-link_category-"+a).prop("checked",e),c=!1}},e=function(t,e){i(e.what+" response_data",t).each(function(){i(i(this).text()).find("label").each(function(){var t=i(this),e=t.find("input").val(),a=t.find("input")[0].id,c=i.trim(t.text());i("#"+a).change(s),i('<option value="'+parseInt(e,10)+'"></option>').text(c)})})},i("#categorychecklist").wpList({alt:"",what:"link-category",response:"category-ajax-response",addAfter:e}),i('a[href="#categories-all"]').click(function(){deleteUserSetting("cats")}),i('a[href="#categories-pop"]').click(function(){setUserSetting("cats","pop")}),"pop"==getUserSetting("cats")&&i('a[href="#categories-pop"]').click(),i("#category-add-toggle").click(function(){return i(this).parents("div:first").toggleClass("wp-hidden-children"),i('#category-tabs a[href="#categories-all"]').click(),i("#newcategory").focus(),!1}),i(".categorychecklist :checkbox").change(s).filter(":checked").change()});
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/media-gallery.js b/srcs/wordpress/wp-admin/js/media-gallery.js deleted file mode 100644 index 725d2be..0000000 --- a/srcs/wordpress/wp-admin/js/media-gallery.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * This file is used on media-upload.php which has been replaced by media-new.php and upload.php - * - * @deprecated 3.5.0 - * @output wp-admin/js/media-gallery.js - */ - - /* global ajaxurl */ -jQuery(function($) { - /** - * Adds a click event handler to the element with a 'wp-gallery' class. - */ - $( 'body' ).bind( 'click.wp-gallery', function(e) { - var target = $( e.target ), id, img_size; - - if ( target.hasClass( 'wp-set-header' ) ) { - // Opens the image to preview it full size. - ( window.dialogArguments || opener || parent || top ).location.href = target.data( 'location' ); - e.preventDefault(); - } else if ( target.hasClass( 'wp-set-background' ) ) { - // Sets the image as background of the theme. - id = target.data( 'attachment-id' ); - img_size = $( 'input[name="attachments[' + id + '][image-size]"]:checked').val(); - - /** - * This AJAX action has been deprecated since 3.5.0, see custom-background.php - */ - jQuery.post(ajaxurl, { - action: 'set-background-image', - attachment_id: id, - size: img_size - }, function() { - var win = window.dialogArguments || opener || parent || top; - win.tb_remove(); - win.location.reload(); - }); - - e.preventDefault(); - } - }); -}); diff --git a/srcs/wordpress/wp-admin/js/media-gallery.min.js b/srcs/wordpress/wp-admin/js/media-gallery.min.js deleted file mode 100644 index 73e161a..0000000 --- a/srcs/wordpress/wp-admin/js/media-gallery.min.js +++ /dev/null @@ -1 +0,0 @@ -jQuery(function(o){o("body").bind("click.wp-gallery",function(a){var e,t,n=o(a.target);n.hasClass("wp-set-header")?((window.dialogArguments||opener||parent||top).location.href=n.data("location"),a.preventDefault()):n.hasClass("wp-set-background")&&(e=n.data("attachment-id"),t=o('input[name="attachments['+e+'][image-size]"]:checked').val(),jQuery.post(ajaxurl,{action:"set-background-image",attachment_id:e,size:t},function(){var a=window.dialogArguments||opener||parent||top;a.tb_remove(),a.location.reload()}),a.preventDefault())})});
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/media-upload.js b/srcs/wordpress/wp-admin/js/media-upload.js deleted file mode 100644 index 9055cf9..0000000 --- a/srcs/wordpress/wp-admin/js/media-upload.js +++ /dev/null @@ -1,113 +0,0 @@ -/** - * Contains global functions for the media upload within the post edit screen. - * - * Updates the ThickBox anchor href and the ThickBox's own properties in order - * to set the size and position on every resize event. Also adds a function to - * send HTML or text to the currently active editor. - * - * @file - * @since 2.5.0 - * @output wp-admin/js/media-upload.js - * - * @requires jQuery - */ - -/* global tinymce, QTags, wpActiveEditor, tb_position */ - -/** - * Sends the HTML passed in the parameters to TinyMCE. - * - * @since 2.5.0 - * - * @global - * - * @param {string} html The HTML to be sent to the editor. - * @returns {void|boolean} Returns false when both TinyMCE and QTags instances - * are unavailable. This means that the HTML was not - * sent to the editor. - */ -window.send_to_editor = function( html ) { - var editor, - hasTinymce = typeof tinymce !== 'undefined', - hasQuicktags = typeof QTags !== 'undefined'; - - // If no active editor is set, try to set it. - if ( ! wpActiveEditor ) { - if ( hasTinymce && tinymce.activeEditor ) { - editor = tinymce.activeEditor; - window.wpActiveEditor = editor.id; - } else if ( ! hasQuicktags ) { - return false; - } - } else if ( hasTinymce ) { - editor = tinymce.get( wpActiveEditor ); - } - - // If the editor is set and not hidden, insert the HTML into the content of the - // editor. - if ( editor && ! editor.isHidden() ) { - editor.execCommand( 'mceInsertContent', false, html ); - } else if ( hasQuicktags ) { - // If quick tags are available, insert the HTML into its content. - QTags.insertContent( html ); - } else { - // If neither the TinyMCE editor and the quick tags are available, add the HTML - // to the current active editor. - document.getElementById( wpActiveEditor ).value += html; - } - - // If the old thickbox remove function exists, call it. - if ( window.tb_remove ) { - try { window.tb_remove(); } catch( e ) {} - } -}; - -(function($) { - /** - * Recalculates and applies the new ThickBox position based on the current - * window size. - * - * @since 2.6.0 - * - * @global - * - * @returns {Object[]} Array containing jQuery objects for all the found - * ThickBox anchors. - */ - window.tb_position = function() { - var tbWindow = $('#TB_window'), - width = $(window).width(), - H = $(window).height(), - W = ( 833 < width ) ? 833 : width, - adminbar_height = 0; - - if ( $('#wpadminbar').length ) { - adminbar_height = parseInt( $('#wpadminbar').css('height'), 10 ); - } - - if ( tbWindow.length ) { - tbWindow.width( W - 50 ).height( H - 45 - adminbar_height ); - $('#TB_iframeContent').width( W - 50 ).height( H - 75 - adminbar_height ); - tbWindow.css({'margin-left': '-' + parseInt( ( ( W - 50 ) / 2 ), 10 ) + 'px'}); - if ( typeof document.body.style.maxWidth !== 'undefined' ) - tbWindow.css({'top': 20 + adminbar_height + 'px', 'margin-top': '0'}); - } - - /** - * Recalculates the new height and width for all links with a ThickBox class. - * - * @since 2.6.0 - */ - return $('a.thickbox').each( function() { - var href = $(this).attr('href'); - if ( ! href ) return; - href = href.replace(/&width=[0-9]+/g, ''); - href = href.replace(/&height=[0-9]+/g, ''); - $(this).attr( 'href', href + '&width=' + ( W - 80 ) + '&height=' + ( H - 85 - adminbar_height ) ); - }); - }; - - // Add handler to recalculates the ThickBox position when the window is resized. - $(window).resize(function(){ tb_position(); }); - -})(jQuery); diff --git a/srcs/wordpress/wp-admin/js/media-upload.min.js b/srcs/wordpress/wp-admin/js/media-upload.min.js deleted file mode 100644 index 4933865..0000000 --- a/srcs/wordpress/wp-admin/js/media-upload.min.js +++ /dev/null @@ -1 +0,0 @@ -window.send_to_editor=function(t){var e,i="undefined"!=typeof tinymce,n="undefined"!=typeof QTags;if(wpActiveEditor)i&&(e=tinymce.get(wpActiveEditor));else if(i&&tinymce.activeEditor)e=tinymce.activeEditor,window.wpActiveEditor=e.id;else if(!n)return!1;if(e&&!e.isHidden()?e.execCommand("mceInsertContent",!1,t):n?QTags.insertContent(t):document.getElementById(wpActiveEditor).value+=t,window.tb_remove)try{window.tb_remove()}catch(t){}},function(d){window.tb_position=function(){var t=d("#TB_window"),e=d(window).width(),i=d(window).height(),n=833<e?833:e,o=0;return d("#wpadminbar").length&&(o=parseInt(d("#wpadminbar").css("height"),10)),t.length&&(t.width(n-50).height(i-45-o),d("#TB_iframeContent").width(n-50).height(i-75-o),t.css({"margin-left":"-"+parseInt((n-50)/2,10)+"px"}),void 0!==document.body.style.maxWidth&&t.css({top:20+o+"px","margin-top":"0"})),d("a.thickbox").each(function(){var t=d(this).attr("href");t&&(t=(t=t.replace(/&width=[0-9]+/g,"")).replace(/&height=[0-9]+/g,""),d(this).attr("href",t+"&width="+(n-80)+"&height="+(i-85-o)))})},d(window).resize(function(){tb_position()})}(jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/media.js b/srcs/wordpress/wp-admin/js/media.js deleted file mode 100644 index 4d9a5ec..0000000 --- a/srcs/wordpress/wp-admin/js/media.js +++ /dev/null @@ -1,207 +0,0 @@ -/** - * Creates a dialog containing posts that can have a particular media attached - * to it. - * - * @since 2.7.0 - * @output wp-admin/js/media.js - * - * @namespace findPosts - * - * @requires jQuery - */ - -/* global ajaxurl, attachMediaBoxL10n, _wpMediaGridSettings, showNotice, findPosts */ - -( function( $ ){ - window.findPosts = { - /** - * Opens a dialog to attach media to a post. - * - * Adds an overlay prior to retrieving a list of posts to attach the media to. - * - * @since 2.7.0 - * - * @memberOf findPosts - * - * @param {string} af_name The name of the affected element. - * @param {string} af_val The value of the affected post element. - * - * @returns {boolean} Always returns false. - */ - open: function( af_name, af_val ) { - var overlay = $( '.ui-find-overlay' ); - - if ( overlay.length === 0 ) { - $( 'body' ).append( '<div class="ui-find-overlay"></div>' ); - findPosts.overlay(); - } - - overlay.show(); - - if ( af_name && af_val ) { - // #affected is a hidden input field in the dialog that keeps track of which media should be attached. - $( '#affected' ).attr( 'name', af_name ).val( af_val ); - } - - $( '#find-posts' ).show(); - - // Close the dialog when the escape key is pressed. - $('#find-posts-input').focus().keyup( function( event ){ - if ( event.which == 27 ) { - findPosts.close(); - } - }); - - // Retrieves a list of applicable posts for media attachment and shows them. - findPosts.send(); - - return false; - }, - - /** - * Clears the found posts lists before hiding the attach media dialog. - * - * @since 2.7.0 - * - * @memberOf findPosts - * - * @returns {void} - */ - close: function() { - $('#find-posts-response').empty(); - $('#find-posts').hide(); - $( '.ui-find-overlay' ).hide(); - }, - - /** - * Binds a click event listener to the overlay which closes the attach media - * dialog. - * - * @since 3.5.0 - * - * @memberOf findPosts - * - * @returns {void} - */ - overlay: function() { - $( '.ui-find-overlay' ).on( 'click', function () { - findPosts.close(); - }); - }, - - /** - * Retrieves and displays posts based on the search term. - * - * Sends a post request to the admin_ajax.php, requesting posts based on the - * search term provided by the user. Defaults to all posts if no search term is - * provided. - * - * @since 2.7.0 - * - * @memberOf findPosts - * - * @returns {void} - */ - send: function() { - var post = { - ps: $( '#find-posts-input' ).val(), - action: 'find_posts', - _ajax_nonce: $('#_ajax_nonce').val() - }, - spinner = $( '.find-box-search .spinner' ); - - spinner.addClass( 'is-active' ); - - /** - * Send a POST request to admin_ajax.php, hide the spinner and replace the list - * of posts with the response data. If an error occurs, display it. - */ - $.ajax( ajaxurl, { - type: 'POST', - data: post, - dataType: 'json' - }).always( function() { - spinner.removeClass( 'is-active' ); - }).done( function( x ) { - if ( ! x.success ) { - $( '#find-posts-response' ).text( attachMediaBoxL10n.error ); - } - - $( '#find-posts-response' ).html( x.data ); - }).fail( function() { - $( '#find-posts-response' ).text( attachMediaBoxL10n.error ); - }); - } - }; - - /** - * Initializes the file once the DOM is fully loaded and attaches events to the - * various form elements. - * - * @returns {void} - */ - $( document ).ready( function() { - var settings, $mediaGridWrap = $( '#wp-media-grid' ); - - // Opens a manage media frame into the grid. - if ( $mediaGridWrap.length && window.wp && window.wp.media ) { - settings = _wpMediaGridSettings; - - window.wp.media({ - frame: 'manage', - container: $mediaGridWrap, - library: settings.queryVars - }).open(); - } - - // Prevents form submission if no post has been selected. - $( '#find-posts-submit' ).click( function( event ) { - if ( ! $( '#find-posts-response input[type="radio"]:checked' ).length ) - event.preventDefault(); - }); - - // Submits the search query when hitting the enter key in the search input. - $( '#find-posts .find-box-search :input' ).keypress( function( event ) { - if ( 13 == event.which ) { - findPosts.send(); - return false; - } - }); - - // Binds the click event to the search button. - $( '#find-posts-search' ).click( findPosts.send ); - - // Binds the close dialog click event. - $( '#find-posts-close' ).click( findPosts.close ); - - // Binds the bulk action events to the submit buttons. - $( '#doaction, #doaction2' ).click( function( event ) { - - /* - * Retrieves all select elements for bulk actions that have a name starting with `action` - * and handle its action based on its value. - */ - $( 'select[name^="action"]' ).each( function() { - var optionValue = $( this ).val(); - - if ( 'attach' === optionValue ) { - event.preventDefault(); - findPosts.open(); - } else if ( 'delete' === optionValue ) { - if ( ! showNotice.warn() ) { - event.preventDefault(); - } - } - }); - }); - - /** - * Enables clicking on the entire table row. - * - * @returns {void} - */ - $( '.find-box-inside' ).on( 'click', 'tr', function() { - $( this ).find( '.found-radio input' ).prop( 'checked', true ); - }); - }); -})( jQuery ); diff --git a/srcs/wordpress/wp-admin/js/media.min.js b/srcs/wordpress/wp-admin/js/media.min.js deleted file mode 100644 index 5a0513c..0000000 --- a/srcs/wordpress/wp-admin/js/media.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(s){window.findPosts={open:function(n,i){var e=s(".ui-find-overlay");return 0===e.length&&(s("body").append('<div class="ui-find-overlay"></div>'),findPosts.overlay()),e.show(),n&&i&&s("#affected").attr("name",n).val(i),s("#find-posts").show(),s("#find-posts-input").focus().keyup(function(n){27==n.which&&findPosts.close()}),findPosts.send(),!1},close:function(){s("#find-posts-response").empty(),s("#find-posts").hide(),s(".ui-find-overlay").hide()},overlay:function(){s(".ui-find-overlay").on("click",function(){findPosts.close()})},send:function(){var n={ps:s("#find-posts-input").val(),action:"find_posts",_ajax_nonce:s("#_ajax_nonce").val()},i=s(".find-box-search .spinner");i.addClass("is-active"),s.ajax(ajaxurl,{type:"POST",data:n,dataType:"json"}).always(function(){i.removeClass("is-active")}).done(function(n){n.success||s("#find-posts-response").text(attachMediaBoxL10n.error),s("#find-posts-response").html(n.data)}).fail(function(){s("#find-posts-response").text(attachMediaBoxL10n.error)})}},s(document).ready(function(){var n,i=s("#wp-media-grid");i.length&&window.wp&&window.wp.media&&(n=_wpMediaGridSettings,window.wp.media({frame:"manage",container:i,library:n.queryVars}).open()),s("#find-posts-submit").click(function(n){s('#find-posts-response input[type="radio"]:checked').length||n.preventDefault()}),s("#find-posts .find-box-search :input").keypress(function(n){if(13==n.which)return findPosts.send(),!1}),s("#find-posts-search").click(findPosts.send),s("#find-posts-close").click(findPosts.close),s("#doaction, #doaction2").click(function(i){s('select[name^="action"]').each(function(){var n=s(this).val();"attach"===n?(i.preventDefault(),findPosts.open()):"delete"===n&&(showNotice.warn()||i.preventDefault())})}),s(".find-box-inside").on("click","tr",function(){s(this).find(".found-radio input").prop("checked",!0)})})}(jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/nav-menu.js b/srcs/wordpress/wp-admin/js/nav-menu.js deleted file mode 100644 index 95b66c1..0000000 --- a/srcs/wordpress/wp-admin/js/nav-menu.js +++ /dev/null @@ -1,1321 +0,0 @@ -/** - * WordPress Administration Navigation Menu - * Interface JS functions - * - * @version 2.0.0 - * - * @package WordPress - * @subpackage Administration - * @output wp-admin/js/nav-menu.js - */ - -/* global menus, postboxes, columns, isRtl, navMenuL10n, ajaxurl, wpNavMenu */ - -(function($) { - - var api; - - /** - * Contains all the functions to handle WordPress navigation menus administration. - * - * @namespace wpNavMenu - */ - api = window.wpNavMenu = { - - options : { - menuItemDepthPerLevel : 30, // Do not use directly. Use depthToPx and pxToDepth instead. - globalMaxDepth: 11, - sortableItems: '> *', - targetTolerance: 0 - }, - - menuList : undefined, // Set in init. - targetList : undefined, // Set in init. - menusChanged : false, - isRTL: !! ( 'undefined' != typeof isRtl && isRtl ), - negateIfRTL: ( 'undefined' != typeof isRtl && isRtl ) ? -1 : 1, - lastSearch: '', - - // Functions that run on init. - init : function() { - api.menuList = $('#menu-to-edit'); - api.targetList = api.menuList; - - this.jQueryExtensions(); - - this.attachMenuEditListeners(); - - this.attachQuickSearchListeners(); - this.attachThemeLocationsListeners(); - this.attachMenuSaveSubmitListeners(); - - this.attachTabsPanelListeners(); - - this.attachUnsavedChangesListener(); - - if ( api.menuList.length ) - this.initSortables(); - - if ( menus.oneThemeLocationNoMenus ) - $( '#posttype-page' ).addSelectedToMenu( api.addMenuItemToBottom ); - - this.initManageLocations(); - - this.initAccessibility(); - - this.initToggles(); - - this.initPreviewing(); - }, - - jQueryExtensions : function() { - // jQuery extensions - $.fn.extend({ - menuItemDepth : function() { - var margin = api.isRTL ? this.eq(0).css('margin-right') : this.eq(0).css('margin-left'); - return api.pxToDepth( margin && -1 != margin.indexOf('px') ? margin.slice(0, -2) : 0 ); - }, - updateDepthClass : function(current, prev) { - return this.each(function(){ - var t = $(this); - prev = prev || t.menuItemDepth(); - $(this).removeClass('menu-item-depth-'+ prev ) - .addClass('menu-item-depth-'+ current ); - }); - }, - shiftDepthClass : function(change) { - return this.each(function(){ - var t = $(this), - depth = t.menuItemDepth(), - newDepth = depth + change; - - t.removeClass( 'menu-item-depth-'+ depth ) - .addClass( 'menu-item-depth-'+ ( newDepth ) ); - - if ( 0 === newDepth ) { - t.find( '.is-submenu' ).hide(); - } - }); - }, - childMenuItems : function() { - var result = $(); - this.each(function(){ - var t = $(this), depth = t.menuItemDepth(), next = t.next( '.menu-item' ); - while( next.length && next.menuItemDepth() > depth ) { - result = result.add( next ); - next = next.next( '.menu-item' ); - } - }); - return result; - }, - shiftHorizontally : function( dir ) { - return this.each(function(){ - var t = $(this), - depth = t.menuItemDepth(), - newDepth = depth + dir; - - // Change .menu-item-depth-n class - t.moveHorizontally( newDepth, depth ); - }); - }, - moveHorizontally : function( newDepth, depth ) { - return this.each(function(){ - var t = $(this), - children = t.childMenuItems(), - diff = newDepth - depth, - subItemText = t.find('.is-submenu'); - - // Change .menu-item-depth-n class - t.updateDepthClass( newDepth, depth ).updateParentMenuItemDBId(); - - // If it has children, move those too - if ( children ) { - children.each(function() { - var t = $(this), - thisDepth = t.menuItemDepth(), - newDepth = thisDepth + diff; - t.updateDepthClass(newDepth, thisDepth).updateParentMenuItemDBId(); - }); - } - - // Show "Sub item" helper text - if (0 === newDepth) - subItemText.hide(); - else - subItemText.show(); - }); - }, - updateParentMenuItemDBId : function() { - return this.each(function(){ - var item = $(this), - input = item.find( '.menu-item-data-parent-id' ), - depth = parseInt( item.menuItemDepth(), 10 ), - parentDepth = depth - 1, - parent = item.prevAll( '.menu-item-depth-' + parentDepth ).first(); - - if ( 0 === depth ) { // Item is on the top level, has no parent - input.val(0); - } else { // Find the parent item, and retrieve its object id. - input.val( parent.find( '.menu-item-data-db-id' ).val() ); - } - }); - }, - hideAdvancedMenuItemFields : function() { - return this.each(function(){ - var that = $(this); - $('.hide-column-tog').not(':checked').each(function(){ - that.find('.field-' + $(this).val() ).addClass('hidden-field'); - }); - }); - }, - /** - * Adds selected menu items to the menu. - * - * @ignore - * - * @param jQuery metabox The metabox jQuery object. - */ - addSelectedToMenu : function(processMethod) { - if ( 0 === $('#menu-to-edit').length ) { - return false; - } - - return this.each(function() { - var t = $(this), menuItems = {}, - checkboxes = ( menus.oneThemeLocationNoMenus && 0 === t.find( '.tabs-panel-active .categorychecklist li input:checked' ).length ) ? t.find( '#page-all li input[type="checkbox"]' ) : t.find( '.tabs-panel-active .categorychecklist li input:checked' ), - re = /menu-item\[([^\]]*)/; - - processMethod = processMethod || api.addMenuItemToBottom; - - // If no items are checked, bail. - if ( !checkboxes.length ) - return false; - - // Show the ajax spinner - t.find( '.button-controls .spinner' ).addClass( 'is-active' ); - - // Retrieve menu item data - $(checkboxes).each(function(){ - var t = $(this), - listItemDBIDMatch = re.exec( t.attr('name') ), - listItemDBID = 'undefined' == typeof listItemDBIDMatch[1] ? 0 : parseInt(listItemDBIDMatch[1], 10); - - if ( this.className && -1 != this.className.indexOf('add-to-top') ) - processMethod = api.addMenuItemToTop; - menuItems[listItemDBID] = t.closest('li').getItemData( 'add-menu-item', listItemDBID ); - }); - - // Add the items - api.addItemToMenu(menuItems, processMethod, function(){ - // Deselect the items and hide the ajax spinner - checkboxes.prop( 'checked', false ); - t.find( '.button-controls .select-all' ).prop( 'checked', false ); - t.find( '.button-controls .spinner' ).removeClass( 'is-active' ); - }); - }); - }, - getItemData : function( itemType, id ) { - itemType = itemType || 'menu-item'; - - var itemData = {}, i, - fields = [ - 'menu-item-db-id', - 'menu-item-object-id', - 'menu-item-object', - 'menu-item-parent-id', - 'menu-item-position', - 'menu-item-type', - 'menu-item-title', - 'menu-item-url', - 'menu-item-description', - 'menu-item-attr-title', - 'menu-item-target', - 'menu-item-classes', - 'menu-item-xfn' - ]; - - if( !id && itemType == 'menu-item' ) { - id = this.find('.menu-item-data-db-id').val(); - } - - if( !id ) return itemData; - - this.find('input').each(function() { - var field; - i = fields.length; - while ( i-- ) { - if( itemType == 'menu-item' ) - field = fields[i] + '[' + id + ']'; - else if( itemType == 'add-menu-item' ) - field = 'menu-item[' + id + '][' + fields[i] + ']'; - - if ( - this.name && - field == this.name - ) { - itemData[fields[i]] = this.value; - } - } - }); - - return itemData; - }, - setItemData : function( itemData, itemType, id ) { // Can take a type, such as 'menu-item', or an id. - itemType = itemType || 'menu-item'; - - if( !id && itemType == 'menu-item' ) { - id = $('.menu-item-data-db-id', this).val(); - } - - if( !id ) return this; - - this.find('input').each(function() { - var t = $(this), field; - $.each( itemData, function( attr, val ) { - if( itemType == 'menu-item' ) - field = attr + '[' + id + ']'; - else if( itemType == 'add-menu-item' ) - field = 'menu-item[' + id + '][' + attr + ']'; - - if ( field == t.attr('name') ) { - t.val( val ); - } - }); - }); - return this; - } - }); - }, - - countMenuItems : function( depth ) { - return $( '.menu-item-depth-' + depth ).length; - }, - - moveMenuItem : function( $this, dir ) { - - var items, newItemPosition, newDepth, - menuItems = $( '#menu-to-edit li' ), - menuItemsCount = menuItems.length, - thisItem = $this.parents( 'li.menu-item' ), - thisItemChildren = thisItem.childMenuItems(), - thisItemData = thisItem.getItemData(), - thisItemDepth = parseInt( thisItem.menuItemDepth(), 10 ), - thisItemPosition = parseInt( thisItem.index(), 10 ), - nextItem = thisItem.next(), - nextItemChildren = nextItem.childMenuItems(), - nextItemDepth = parseInt( nextItem.menuItemDepth(), 10 ) + 1, - prevItem = thisItem.prev(), - prevItemDepth = parseInt( prevItem.menuItemDepth(), 10 ), - prevItemId = prevItem.getItemData()['menu-item-db-id']; - - switch ( dir ) { - case 'up': - newItemPosition = thisItemPosition - 1; - - // Already at top - if ( 0 === thisItemPosition ) - break; - - // If a sub item is moved to top, shift it to 0 depth - if ( 0 === newItemPosition && 0 !== thisItemDepth ) - thisItem.moveHorizontally( 0, thisItemDepth ); - - // If prev item is sub item, shift to match depth - if ( 0 !== prevItemDepth ) - thisItem.moveHorizontally( prevItemDepth, thisItemDepth ); - - // Does this item have sub items? - if ( thisItemChildren ) { - items = thisItem.add( thisItemChildren ); - // Move the entire block - items.detach().insertBefore( menuItems.eq( newItemPosition ) ).updateParentMenuItemDBId(); - } else { - thisItem.detach().insertBefore( menuItems.eq( newItemPosition ) ).updateParentMenuItemDBId(); - } - break; - case 'down': - // Does this item have sub items? - if ( thisItemChildren ) { - items = thisItem.add( thisItemChildren ), - nextItem = menuItems.eq( items.length + thisItemPosition ), - nextItemChildren = 0 !== nextItem.childMenuItems().length; - - if ( nextItemChildren ) { - newDepth = parseInt( nextItem.menuItemDepth(), 10 ) + 1; - thisItem.moveHorizontally( newDepth, thisItemDepth ); - } - - // Have we reached the bottom? - if ( menuItemsCount === thisItemPosition + items.length ) - break; - - items.detach().insertAfter( menuItems.eq( thisItemPosition + items.length ) ).updateParentMenuItemDBId(); - } else { - // If next item has sub items, shift depth - if ( 0 !== nextItemChildren.length ) - thisItem.moveHorizontally( nextItemDepth, thisItemDepth ); - - // Have we reached the bottom - if ( menuItemsCount === thisItemPosition + 1 ) - break; - thisItem.detach().insertAfter( menuItems.eq( thisItemPosition + 1 ) ).updateParentMenuItemDBId(); - } - break; - case 'top': - // Already at top - if ( 0 === thisItemPosition ) - break; - // Does this item have sub items? - if ( thisItemChildren ) { - items = thisItem.add( thisItemChildren ); - // Move the entire block - items.detach().insertBefore( menuItems.eq( 0 ) ).updateParentMenuItemDBId(); - } else { - thisItem.detach().insertBefore( menuItems.eq( 0 ) ).updateParentMenuItemDBId(); - } - break; - case 'left': - // As far left as possible - if ( 0 === thisItemDepth ) - break; - thisItem.shiftHorizontally( -1 ); - break; - case 'right': - // Can't be sub item at top - if ( 0 === thisItemPosition ) - break; - // Already sub item of prevItem - if ( thisItemData['menu-item-parent-id'] === prevItemId ) - break; - thisItem.shiftHorizontally( 1 ); - break; - } - $this.focus(); - api.registerChange(); - api.refreshKeyboardAccessibility(); - api.refreshAdvancedAccessibility(); - }, - - initAccessibility : function() { - var menu = $( '#menu-to-edit' ); - - api.refreshKeyboardAccessibility(); - api.refreshAdvancedAccessibility(); - - // Refresh the accessibility when the user comes close to the item in any way - menu.on( 'mouseenter.refreshAccessibility focus.refreshAccessibility touchstart.refreshAccessibility' , '.menu-item' , function(){ - api.refreshAdvancedAccessibilityOfItem( $( this ).find( 'a.item-edit' ) ); - } ); - - // We have to update on click as well because we might hover first, change the item, and then click. - menu.on( 'click', 'a.item-edit', function() { - api.refreshAdvancedAccessibilityOfItem( $( this ) ); - } ); - - // Links for moving items - menu.on( 'click', '.menus-move', function () { - var $this = $( this ), - dir = $this.data( 'dir' ); - - if ( 'undefined' !== typeof dir ) { - api.moveMenuItem( $( this ).parents( 'li.menu-item' ).find( 'a.item-edit' ), dir ); - } - }); - }, - - /** - * refreshAdvancedAccessibilityOfItem( [itemToRefresh] ) - * - * Refreshes advanced accessibility buttons for one menu item. - * Shows or hides buttons based on the location of the menu item. - * - * @param {object} itemToRefresh The menu item that might need its advanced accessibility buttons refreshed - */ - refreshAdvancedAccessibilityOfItem : function( itemToRefresh ) { - - // Only refresh accessibility when necessary - if ( true !== $( itemToRefresh ).data( 'needs_accessibility_refresh' ) ) { - return; - } - - var thisLink, thisLinkText, primaryItems, itemPosition, title, - parentItem, parentItemId, parentItemName, subItems, - $this = $( itemToRefresh ), - menuItem = $this.closest( 'li.menu-item' ).first(), - depth = menuItem.menuItemDepth(), - isPrimaryMenuItem = ( 0 === depth ), - itemName = $this.closest( '.menu-item-handle' ).find( '.menu-item-title' ).text(), - position = parseInt( menuItem.index(), 10 ), - prevItemDepth = ( isPrimaryMenuItem ) ? depth : parseInt( depth - 1, 10 ), - prevItemNameLeft = menuItem.prevAll('.menu-item-depth-' + prevItemDepth).first().find( '.menu-item-title' ).text(), - prevItemNameRight = menuItem.prevAll('.menu-item-depth-' + depth).first().find( '.menu-item-title' ).text(), - totalMenuItems = $('#menu-to-edit li').length, - hasSameDepthSibling = menuItem.nextAll( '.menu-item-depth-' + depth ).length; - - menuItem.find( '.field-move' ).toggle( totalMenuItems > 1 ); - - // Where can they move this menu item? - if ( 0 !== position ) { - thisLink = menuItem.find( '.menus-move-up' ); - thisLink.attr( 'aria-label', menus.moveUp ).css( 'display', 'inline' ); - } - - if ( 0 !== position && isPrimaryMenuItem ) { - thisLink = menuItem.find( '.menus-move-top' ); - thisLink.attr( 'aria-label', menus.moveToTop ).css( 'display', 'inline' ); - } - - if ( position + 1 !== totalMenuItems && 0 !== position ) { - thisLink = menuItem.find( '.menus-move-down' ); - thisLink.attr( 'aria-label', menus.moveDown ).css( 'display', 'inline' ); - } - - if ( 0 === position && 0 !== hasSameDepthSibling ) { - thisLink = menuItem.find( '.menus-move-down' ); - thisLink.attr( 'aria-label', menus.moveDown ).css( 'display', 'inline' ); - } - - if ( ! isPrimaryMenuItem ) { - thisLink = menuItem.find( '.menus-move-left' ), - thisLinkText = menus.outFrom.replace( '%s', prevItemNameLeft ); - thisLink.attr( 'aria-label', menus.moveOutFrom.replace( '%s', prevItemNameLeft ) ).text( thisLinkText ).css( 'display', 'inline' ); - } - - if ( 0 !== position ) { - if ( menuItem.find( '.menu-item-data-parent-id' ).val() !== menuItem.prev().find( '.menu-item-data-db-id' ).val() ) { - thisLink = menuItem.find( '.menus-move-right' ), - thisLinkText = menus.under.replace( '%s', prevItemNameRight ); - thisLink.attr( 'aria-label', menus.moveUnder.replace( '%s', prevItemNameRight ) ).text( thisLinkText ).css( 'display', 'inline' ); - } - } - - if ( isPrimaryMenuItem ) { - primaryItems = $( '.menu-item-depth-0' ), - itemPosition = primaryItems.index( menuItem ) + 1, - totalMenuItems = primaryItems.length, - - // String together help text for primary menu items - title = menus.menuFocus.replace( '%1$s', itemName ).replace( '%2$d', itemPosition ).replace( '%3$d', totalMenuItems ); - } else { - parentItem = menuItem.prevAll( '.menu-item-depth-' + parseInt( depth - 1, 10 ) ).first(), - parentItemId = parentItem.find( '.menu-item-data-db-id' ).val(), - parentItemName = parentItem.find( '.menu-item-title' ).text(), - subItems = $( '.menu-item .menu-item-data-parent-id[value="' + parentItemId + '"]' ), - itemPosition = $( subItems.parents('.menu-item').get().reverse() ).index( menuItem ) + 1; - - // String together help text for sub menu items - title = menus.subMenuFocus.replace( '%1$s', itemName ).replace( '%2$d', itemPosition ).replace( '%3$s', parentItemName ); - } - - $this.attr( 'aria-label', title ); - - // Mark this item's accessibility as refreshed - $this.data( 'needs_accessibility_refresh', false ); - }, - - /** - * refreshAdvancedAccessibility - * - * Hides all advanced accessibility buttons and marks them for refreshing. - */ - refreshAdvancedAccessibility : function() { - - // Hide all the move buttons by default. - $( '.menu-item-settings .field-move .menus-move' ).hide(); - - // Mark all menu items as unprocessed - $( 'a.item-edit' ).data( 'needs_accessibility_refresh', true ); - - // All open items have to be refreshed or they will show no links - $( '.menu-item-edit-active a.item-edit' ).each( function() { - api.refreshAdvancedAccessibilityOfItem( this ); - } ); - }, - - refreshKeyboardAccessibility : function() { - $( 'a.item-edit' ).off( 'focus' ).on( 'focus', function(){ - $(this).off( 'keydown' ).on( 'keydown', function(e){ - - var arrows, - $this = $( this ), - thisItem = $this.parents( 'li.menu-item' ), - thisItemData = thisItem.getItemData(); - - // Bail if it's not an arrow key - if ( 37 != e.which && 38 != e.which && 39 != e.which && 40 != e.which ) - return; - - // Avoid multiple keydown events - $this.off('keydown'); - - // Bail if there is only one menu item - if ( 1 === $('#menu-to-edit li').length ) - return; - - // If RTL, swap left/right arrows - arrows = { '38': 'up', '40': 'down', '37': 'left', '39': 'right' }; - if ( $('body').hasClass('rtl') ) - arrows = { '38' : 'up', '40' : 'down', '39' : 'left', '37' : 'right' }; - - switch ( arrows[e.which] ) { - case 'up': - api.moveMenuItem( $this, 'up' ); - break; - case 'down': - api.moveMenuItem( $this, 'down' ); - break; - case 'left': - api.moveMenuItem( $this, 'left' ); - break; - case 'right': - api.moveMenuItem( $this, 'right' ); - break; - } - // Put focus back on same menu item - $( '#edit-' + thisItemData['menu-item-db-id'] ).focus(); - return false; - }); - }); - }, - - initPreviewing : function() { - // Update the item handle title when the navigation label is changed. - $( '#menu-to-edit' ).on( 'change input', '.edit-menu-item-title', function(e) { - var input = $( e.currentTarget ), title, titleEl; - title = input.val(); - titleEl = input.closest( '.menu-item' ).find( '.menu-item-title' ); - // Don't update to empty title. - if ( title ) { - titleEl.text( title ).removeClass( 'no-title' ); - } else { - titleEl.text( navMenuL10n.untitled ).addClass( 'no-title' ); - } - } ); - }, - - initToggles : function() { - // init postboxes - postboxes.add_postbox_toggles('nav-menus'); - - // adjust columns functions for menus UI - columns.useCheckboxesForHidden(); - columns.checked = function(field) { - $('.field-' + field).removeClass('hidden-field'); - }; - columns.unchecked = function(field) { - $('.field-' + field).addClass('hidden-field'); - }; - // hide fields - api.menuList.hideAdvancedMenuItemFields(); - - $('.hide-postbox-tog').click(function () { - var hidden = $( '.accordion-container li.accordion-section' ).filter(':hidden').map(function() { return this.id; }).get().join(','); - $.post(ajaxurl, { - action: 'closed-postboxes', - hidden: hidden, - closedpostboxesnonce: jQuery('#closedpostboxesnonce').val(), - page: 'nav-menus' - }); - }); - }, - - initSortables : function() { - var currentDepth = 0, originalDepth, minDepth, maxDepth, - prev, next, prevBottom, nextThreshold, helperHeight, transport, - menuEdge = api.menuList.offset().left, - body = $('body'), maxChildDepth, - menuMaxDepth = initialMenuMaxDepth(); - - if( 0 !== $( '#menu-to-edit li' ).length ) - $( '.drag-instructions' ).show(); - - // Use the right edge if RTL. - menuEdge += api.isRTL ? api.menuList.width() : 0; - - api.menuList.sortable({ - handle: '.menu-item-handle', - placeholder: 'sortable-placeholder', - items: api.options.sortableItems, - start: function(e, ui) { - var height, width, parent, children, tempHolder; - - // handle placement for rtl orientation - if ( api.isRTL ) - ui.item[0].style.right = 'auto'; - - transport = ui.item.children('.menu-item-transport'); - - // Set depths. currentDepth must be set before children are located. - originalDepth = ui.item.menuItemDepth(); - updateCurrentDepth(ui, originalDepth); - - // Attach child elements to parent - // Skip the placeholder - parent = ( ui.item.next()[0] == ui.placeholder[0] ) ? ui.item.next() : ui.item; - children = parent.childMenuItems(); - transport.append( children ); - - // Update the height of the placeholder to match the moving item. - height = transport.outerHeight(); - // If there are children, account for distance between top of children and parent - height += ( height > 0 ) ? (ui.placeholder.css('margin-top').slice(0, -2) * 1) : 0; - height += ui.helper.outerHeight(); - helperHeight = height; - height -= 2; // Subtract 2 for borders - ui.placeholder.height(height); - - // Update the width of the placeholder to match the moving item. - maxChildDepth = originalDepth; - children.each(function(){ - var depth = $(this).menuItemDepth(); - maxChildDepth = (depth > maxChildDepth) ? depth : maxChildDepth; - }); - width = ui.helper.find('.menu-item-handle').outerWidth(); // Get original width - width += api.depthToPx(maxChildDepth - originalDepth); // Account for children - width -= 2; // Subtract 2 for borders - ui.placeholder.width(width); - - // Update the list of menu items. - tempHolder = ui.placeholder.next( '.menu-item' ); - tempHolder.css( 'margin-top', helperHeight + 'px' ); // Set the margin to absorb the placeholder - ui.placeholder.detach(); // detach or jQuery UI will think the placeholder is a menu item - $(this).sortable( 'refresh' ); // The children aren't sortable. We should let jQ UI know. - ui.item.after( ui.placeholder ); // reattach the placeholder. - tempHolder.css('margin-top', 0); // reset the margin - - // Now that the element is complete, we can update... - updateSharedVars(ui); - }, - stop: function(e, ui) { - var children, subMenuTitle, - depthChange = currentDepth - originalDepth; - - // Return child elements to the list - children = transport.children().insertAfter(ui.item); - - // Add "sub menu" description - subMenuTitle = ui.item.find( '.item-title .is-submenu' ); - if ( 0 < currentDepth ) - subMenuTitle.show(); - else - subMenuTitle.hide(); - - // Update depth classes - if ( 0 !== depthChange ) { - ui.item.updateDepthClass( currentDepth ); - children.shiftDepthClass( depthChange ); - updateMenuMaxDepth( depthChange ); - } - // Register a change - api.registerChange(); - // Update the item data. - ui.item.updateParentMenuItemDBId(); - - // address sortable's incorrectly-calculated top in opera - ui.item[0].style.top = 0; - - // handle drop placement for rtl orientation - if ( api.isRTL ) { - ui.item[0].style.left = 'auto'; - ui.item[0].style.right = 0; - } - - api.refreshKeyboardAccessibility(); - api.refreshAdvancedAccessibility(); - }, - change: function(e, ui) { - // Make sure the placeholder is inside the menu. - // Otherwise fix it, or we're in trouble. - if( ! ui.placeholder.parent().hasClass('menu') ) - (prev.length) ? prev.after( ui.placeholder ) : api.menuList.prepend( ui.placeholder ); - - updateSharedVars(ui); - }, - sort: function(e, ui) { - var offset = ui.helper.offset(), - edge = api.isRTL ? offset.left + ui.helper.width() : offset.left, - depth = api.negateIfRTL * api.pxToDepth( edge - menuEdge ); - - // Check and correct if depth is not within range. - // Also, if the dragged element is dragged upwards over - // an item, shift the placeholder to a child position. - if ( depth > maxDepth || offset.top < ( prevBottom - api.options.targetTolerance ) ) { - depth = maxDepth; - } else if ( depth < minDepth ) { - depth = minDepth; - } - - if( depth != currentDepth ) - updateCurrentDepth(ui, depth); - - // If we overlap the next element, manually shift downwards - if( nextThreshold && offset.top + helperHeight > nextThreshold ) { - next.after( ui.placeholder ); - updateSharedVars( ui ); - $( this ).sortable( 'refreshPositions' ); - } - } - }); - - function updateSharedVars(ui) { - var depth; - - prev = ui.placeholder.prev( '.menu-item' ); - next = ui.placeholder.next( '.menu-item' ); - - // Make sure we don't select the moving item. - if( prev[0] == ui.item[0] ) prev = prev.prev( '.menu-item' ); - if( next[0] == ui.item[0] ) next = next.next( '.menu-item' ); - - prevBottom = (prev.length) ? prev.offset().top + prev.height() : 0; - nextThreshold = (next.length) ? next.offset().top + next.height() / 3 : 0; - minDepth = (next.length) ? next.menuItemDepth() : 0; - - if( prev.length ) - maxDepth = ( (depth = prev.menuItemDepth() + 1) > api.options.globalMaxDepth ) ? api.options.globalMaxDepth : depth; - else - maxDepth = 0; - } - - function updateCurrentDepth(ui, depth) { - ui.placeholder.updateDepthClass( depth, currentDepth ); - currentDepth = depth; - } - - function initialMenuMaxDepth() { - if( ! body[0].className ) return 0; - var match = body[0].className.match(/menu-max-depth-(\d+)/); - return match && match[1] ? parseInt( match[1], 10 ) : 0; - } - - function updateMenuMaxDepth( depthChange ) { - var depth, newDepth = menuMaxDepth; - if ( depthChange === 0 ) { - return; - } else if ( depthChange > 0 ) { - depth = maxChildDepth + depthChange; - if( depth > menuMaxDepth ) - newDepth = depth; - } else if ( depthChange < 0 && maxChildDepth == menuMaxDepth ) { - while( ! $('.menu-item-depth-' + newDepth, api.menuList).length && newDepth > 0 ) - newDepth--; - } - // Update the depth class. - body.removeClass( 'menu-max-depth-' + menuMaxDepth ).addClass( 'menu-max-depth-' + newDepth ); - menuMaxDepth = newDepth; - } - }, - - initManageLocations : function () { - $('#menu-locations-wrap form').submit(function(){ - window.onbeforeunload = null; - }); - $('.menu-location-menus select').on('change', function () { - var editLink = $(this).closest('tr').find('.locations-edit-menu-link'); - if ($(this).find('option:selected').data('orig')) - editLink.show(); - else - editLink.hide(); - }); - }, - - attachMenuEditListeners : function() { - var that = this; - $('#update-nav-menu').bind('click', function(e) { - if ( e.target && e.target.className ) { - if ( -1 != e.target.className.indexOf('item-edit') ) { - return that.eventOnClickEditLink(e.target); - } else if ( -1 != e.target.className.indexOf('menu-save') ) { - return that.eventOnClickMenuSave(e.target); - } else if ( -1 != e.target.className.indexOf('menu-delete') ) { - return that.eventOnClickMenuDelete(e.target); - } else if ( -1 != e.target.className.indexOf('item-delete') ) { - return that.eventOnClickMenuItemDelete(e.target); - } else if ( -1 != e.target.className.indexOf('item-cancel') ) { - return that.eventOnClickCancelLink(e.target); - } - } - }); - - $( '#menu-name' ).on( 'input', _.debounce( function () { - var menuName = $( document.getElementById( 'menu-name' ) ), - menuNameVal = menuName.val(); - - if ( ! menuNameVal || ! menuNameVal.replace( /\s+/, '' ) ) { - // Add warning for invalid menu name. - menuName.parent().addClass( 'form-invalid' ); - } else { - // Remove warning for valid menu name. - menuName.parent().removeClass( 'form-invalid' ); - } - }, 500 ) ); - - $('#add-custom-links input[type="text"]').keypress(function(e){ - $('#customlinkdiv').removeClass('form-invalid'); - - if ( e.keyCode === 13 ) { - e.preventDefault(); - $( '#submit-customlinkdiv' ).click(); - } - }); - }, - - attachMenuSaveSubmitListeners : function() { - /* - * When a navigation menu is saved, store a JSON representation of all form data - * in a single input to avoid PHP `max_input_vars` limitations. See #14134. - */ - $( '#update-nav-menu' ).submit( function() { - var navMenuData = $( '#update-nav-menu' ).serializeArray(); - $( '[name="nav-menu-data"]' ).val( JSON.stringify( navMenuData ) ); - }); - }, - - attachThemeLocationsListeners : function() { - var loc = $('#nav-menu-theme-locations'), params = {}; - params.action = 'menu-locations-save'; - params['menu-settings-column-nonce'] = $('#menu-settings-column-nonce').val(); - loc.find('input[type="submit"]').click(function() { - loc.find('select').each(function() { - params[this.name] = $(this).val(); - }); - loc.find( '.spinner' ).addClass( 'is-active' ); - $.post( ajaxurl, params, function() { - loc.find( '.spinner' ).removeClass( 'is-active' ); - }); - return false; - }); - }, - - attachQuickSearchListeners : function() { - var searchTimer; - - // Prevent form submission. - $( '#nav-menu-meta' ).on( 'submit', function( event ) { - event.preventDefault(); - }); - - $( '#nav-menu-meta' ).on( 'input', '.quick-search', function() { - var $this = $( this ); - - $this.attr( 'autocomplete', 'off' ); - - if ( searchTimer ) { - clearTimeout( searchTimer ); - } - - searchTimer = setTimeout( function() { - api.updateQuickSearchResults( $this ); - }, 500 ); - }).on( 'blur', '.quick-search', function() { - api.lastSearch = ''; - }); - }, - - updateQuickSearchResults : function(input) { - var panel, params, - minSearchLength = 2, - q = input.val(); - - /* - * Minimum characters for a search. Also avoid a new AJAX search when - * the pressed key (e.g. arrows) doesn't change the searched term. - */ - if ( q.length < minSearchLength || api.lastSearch == q ) { - return; - } - - api.lastSearch = q; - - panel = input.parents('.tabs-panel'); - params = { - 'action': 'menu-quick-search', - 'response-format': 'markup', - 'menu': $('#menu').val(), - 'menu-settings-column-nonce': $('#menu-settings-column-nonce').val(), - 'q': q, - 'type': input.attr('name') - }; - - $( '.spinner', panel ).addClass( 'is-active' ); - - $.post( ajaxurl, params, function(menuMarkup) { - api.processQuickSearchQueryResponse(menuMarkup, params, panel); - }); - }, - - addCustomLink : function( processMethod ) { - var url = $('#custom-menu-item-url').val().trim(), - label = $('#custom-menu-item-name').val(); - - processMethod = processMethod || api.addMenuItemToBottom; - - if ( '' === url || 'https://' == url || 'http://' == url ) { - $('#customlinkdiv').addClass('form-invalid'); - return false; - } - - // Show the ajax spinner - $( '.customlinkdiv .spinner' ).addClass( 'is-active' ); - this.addLinkToMenu( url, label, processMethod, function() { - // Remove the ajax spinner - $( '.customlinkdiv .spinner' ).removeClass( 'is-active' ); - // Set custom link form back to defaults - $('#custom-menu-item-name').val('').blur(); - $( '#custom-menu-item-url' ).val( '' ).attr( 'placeholder', 'https://' ); - }); - }, - - addLinkToMenu : function(url, label, processMethod, callback) { - processMethod = processMethod || api.addMenuItemToBottom; - callback = callback || function(){}; - - api.addItemToMenu({ - '-1': { - 'menu-item-type': 'custom', - 'menu-item-url': url, - 'menu-item-title': label - } - }, processMethod, callback); - }, - - addItemToMenu : function(menuItem, processMethod, callback) { - var menu = $('#menu').val(), - nonce = $('#menu-settings-column-nonce').val(), - params; - - processMethod = processMethod || function(){}; - callback = callback || function(){}; - - params = { - 'action': 'add-menu-item', - 'menu': menu, - 'menu-settings-column-nonce': nonce, - 'menu-item': menuItem - }; - - $.post( ajaxurl, params, function(menuMarkup) { - var ins = $('#menu-instructions'); - - menuMarkup = $.trim( menuMarkup ); // Trim leading whitespaces - processMethod(menuMarkup, params); - - // Make it stand out a bit more visually, by adding a fadeIn - $( 'li.pending' ).hide().fadeIn('slow'); - $( '.drag-instructions' ).show(); - if( ! ins.hasClass( 'menu-instructions-inactive' ) && ins.siblings().length ) - ins.addClass( 'menu-instructions-inactive' ); - - callback(); - }); - }, - - /** - * Process the add menu item request response into menu list item. Appends to menu. - * - * @param {string} menuMarkup The text server response of menu item markup. - * - * @fires document#menu-item-added Passes menuMarkup as a jQuery object. - */ - addMenuItemToBottom : function( menuMarkup ) { - var $menuMarkup = $( menuMarkup ); - $menuMarkup.hideAdvancedMenuItemFields().appendTo( api.targetList ); - api.refreshKeyboardAccessibility(); - api.refreshAdvancedAccessibility(); - $( document ).trigger( 'menu-item-added', [ $menuMarkup ] ); - }, - - /** - * Process the add menu item request response into menu list item. Prepends to menu. - * - * @param {string} menuMarkup The text server response of menu item markup. - * - * @fires document#menu-item-added Passes menuMarkup as a jQuery object. - */ - addMenuItemToTop : function( menuMarkup ) { - var $menuMarkup = $( menuMarkup ); - $menuMarkup.hideAdvancedMenuItemFields().prependTo( api.targetList ); - api.refreshKeyboardAccessibility(); - api.refreshAdvancedAccessibility(); - $( document ).trigger( 'menu-item-added', [ $menuMarkup ] ); - }, - - attachUnsavedChangesListener : function() { - $('#menu-management input, #menu-management select, #menu-management, #menu-management textarea, .menu-location-menus select').change(function(){ - api.registerChange(); - }); - - if ( 0 !== $('#menu-to-edit').length || 0 !== $('.menu-location-menus select').length ) { - window.onbeforeunload = function(){ - if ( api.menusChanged ) - return navMenuL10n.saveAlert; - }; - } else { - // Make the post boxes read-only, as they can't be used yet - $( '#menu-settings-column' ).find( 'input,select' ).end().find( 'a' ).attr( 'href', '#' ).unbind( 'click' ); - } - }, - - registerChange : function() { - api.menusChanged = true; - }, - - attachTabsPanelListeners : function() { - $('#menu-settings-column').bind('click', function(e) { - var selectAreaMatch, selectAll, panelId, wrapper, items, - target = $(e.target); - - if ( target.hasClass('nav-tab-link') ) { - - panelId = target.data( 'type' ); - - wrapper = target.parents('.accordion-section-content').first(); - - // upon changing tabs, we want to uncheck all checkboxes - $( 'input', wrapper ).prop( 'checked', false ); - - $('.tabs-panel-active', wrapper).removeClass('tabs-panel-active').addClass('tabs-panel-inactive'); - $('#' + panelId, wrapper).removeClass('tabs-panel-inactive').addClass('tabs-panel-active'); - - $('.tabs', wrapper).removeClass('tabs'); - target.parent().addClass('tabs'); - - // select the search bar - $('.quick-search', wrapper).focus(); - - // Hide controls in the search tab if no items found. - if ( ! wrapper.find( '.tabs-panel-active .menu-item-title' ).length ) { - wrapper.addClass( 'has-no-menu-item' ); - } else { - wrapper.removeClass( 'has-no-menu-item' ); - } - - e.preventDefault(); - } else if ( target.hasClass( 'select-all' ) ) { - selectAreaMatch = target.closest( '.button-controls' ).data( 'items-type' ); - if ( selectAreaMatch ) { - items = $( '#' + selectAreaMatch + ' .tabs-panel-active .menu-item-title input' ); - - if ( items.length === items.filter( ':checked' ).length && ! target.is( ':checked' ) ) { - items.prop( 'checked', false ); - } else if ( target.is( ':checked' ) ) { - items.prop( 'checked', true ); - } - } - } else if ( target.hasClass( 'menu-item-checkbox' ) ) { - selectAreaMatch = target.closest( '.tabs-panel-active' ).parent().attr( 'id' ); - if ( selectAreaMatch ) { - items = $( '#' + selectAreaMatch + ' .tabs-panel-active .menu-item-title input' ); - selectAll = $( '.button-controls[data-items-type="' + selectAreaMatch + '"] .select-all' ); - - if ( items.length === items.filter( ':checked' ).length && ! selectAll.is( ':checked' ) ) { - selectAll.prop( 'checked', true ); - } else if ( selectAll.is( ':checked' ) ) { - selectAll.prop( 'checked', false ); - } - } - } else if ( target.hasClass('submit-add-to-menu') ) { - api.registerChange(); - - if ( e.target.id && 'submit-customlinkdiv' == e.target.id ) - api.addCustomLink( api.addMenuItemToBottom ); - else if ( e.target.id && -1 != e.target.id.indexOf('submit-') ) - $('#' + e.target.id.replace(/submit-/, '')).addSelectedToMenu( api.addMenuItemToBottom ); - return false; - } - }); - - /* - * Delegate the `click` event and attach it just to the pagination - * links thus excluding the current page `<span>`. See ticket #35577. - */ - $( '#nav-menu-meta' ).on( 'click', 'a.page-numbers', function() { - var $container = $( this ).closest( '.inside' ); - - $.post( ajaxurl, this.href.replace( /.*\?/, '' ).replace( /action=([^&]*)/, '' ) + '&action=menu-get-metabox', - function( resp ) { - var metaBoxData = $.parseJSON( resp ), - toReplace; - - if ( -1 === resp.indexOf( 'replace-id' ) ) { - return; - } - - // Get the post type menu meta box to update. - toReplace = document.getElementById( metaBoxData['replace-id'] ); - - if ( ! metaBoxData.markup || ! toReplace ) { - return; - } - - // Update the post type menu meta box with new content from the response. - $container.html( metaBoxData.markup ); - } - ); - - return false; - }); - }, - - eventOnClickEditLink : function(clickedEl) { - var settings, item, - matchedSection = /#(.*)$/.exec(clickedEl.href); - if ( matchedSection && matchedSection[1] ) { - settings = $('#'+matchedSection[1]); - item = settings.parent(); - if( 0 !== item.length ) { - if( item.hasClass('menu-item-edit-inactive') ) { - if( ! settings.data('menu-item-data') ) { - settings.data( 'menu-item-data', settings.getItemData() ); - } - settings.slideDown('fast'); - item.removeClass('menu-item-edit-inactive') - .addClass('menu-item-edit-active'); - } else { - settings.slideUp('fast'); - item.removeClass('menu-item-edit-active') - .addClass('menu-item-edit-inactive'); - } - return false; - } - } - }, - - eventOnClickCancelLink : function(clickedEl) { - var settings = $( clickedEl ).closest( '.menu-item-settings' ), - thisMenuItem = $( clickedEl ).closest( '.menu-item' ); - thisMenuItem.removeClass('menu-item-edit-active').addClass('menu-item-edit-inactive'); - settings.setItemData( settings.data('menu-item-data') ).hide(); - return false; - }, - - eventOnClickMenuSave : function() { - var locs = '', - menuName = $('#menu-name'), - menuNameVal = menuName.val(); - // Cancel and warn if invalid menu name - if ( ! menuNameVal || ! menuNameVal.replace( /\s+/, '' ) ) { - menuName.parent().addClass( 'form-invalid' ); - return false; - } - // Copy menu theme locations - $('#nav-menu-theme-locations select').each(function() { - locs += '<input type="hidden" name="' + this.name + '" value="' + $(this).val() + '" />'; - }); - $('#update-nav-menu').append( locs ); - // Update menu item position data - api.menuList.find('.menu-item-data-position').val( function(index) { return index + 1; } ); - window.onbeforeunload = null; - - return true; - }, - - eventOnClickMenuDelete : function() { - // Delete warning AYS - if ( window.confirm( navMenuL10n.warnDeleteMenu ) ) { - window.onbeforeunload = null; - return true; - } - return false; - }, - - eventOnClickMenuItemDelete : function(clickedEl) { - var itemID = parseInt(clickedEl.id.replace('delete-', ''), 10); - api.removeMenuItem( $('#menu-item-' + itemID) ); - api.registerChange(); - return false; - }, - - /** - * Process the quick search response into a search result - * - * @param string resp The server response to the query. - * @param object req The request arguments. - * @param jQuery panel The tabs panel we're searching in. - */ - processQuickSearchQueryResponse : function(resp, req, panel) { - var matched, newID, - takenIDs = {}, - form = document.getElementById('nav-menu-meta'), - pattern = /menu-item[(\[^]\]*/, - $items = $('<div>').html(resp).find('li'), - wrapper = panel.closest( '.accordion-section-content' ), - selectAll = wrapper.find( '.button-controls .select-all' ), - $item; - - if( ! $items.length ) { - $('.categorychecklist', panel).html( '<li><p>' + navMenuL10n.noResultsFound + '</p></li>' ); - $( '.spinner', panel ).removeClass( 'is-active' ); - wrapper.addClass( 'has-no-menu-item' ); - return; - } - - $items.each(function(){ - $item = $(this); - - // make a unique DB ID number - matched = pattern.exec($item.html()); - - if ( matched && matched[1] ) { - newID = matched[1]; - while( form.elements['menu-item[' + newID + '][menu-item-type]'] || takenIDs[ newID ] ) { - newID--; - } - - takenIDs[newID] = true; - if ( newID != matched[1] ) { - $item.html( $item.html().replace(new RegExp( - 'menu-item\\[' + matched[1] + '\\]', 'g'), - 'menu-item[' + newID + ']' - ) ); - } - } - }); - - $('.categorychecklist', panel).html( $items ); - $( '.spinner', panel ).removeClass( 'is-active' ); - wrapper.removeClass( 'has-no-menu-item' ); - - if ( selectAll.is( ':checked' ) ) { - selectAll.prop( 'checked', false ); - } - }, - - /** - * Remove a menu item. - * @param {object} el The element to be removed as a jQuery object. - * - * @fires document#menu-removing-item Passes the element to be removed. - */ - removeMenuItem : function(el) { - var children = el.childMenuItems(); - - $( document ).trigger( 'menu-removing-item', [ el ] ); - el.addClass('deleting').animate({ - opacity : 0, - height: 0 - }, 350, function() { - var ins = $('#menu-instructions'); - el.remove(); - children.shiftDepthClass( -1 ).updateParentMenuItemDBId(); - if ( 0 === $( '#menu-to-edit li' ).length ) { - $( '.drag-instructions' ).hide(); - ins.removeClass( 'menu-instructions-inactive' ); - } - api.refreshAdvancedAccessibility(); - }); - }, - - depthToPx : function(depth) { - return depth * api.options.menuItemDepthPerLevel; - }, - - pxToDepth : function(px) { - return Math.floor(px / api.options.menuItemDepthPerLevel); - } - - }; - - $(document).ready(function(){ wpNavMenu.init(); }); - -})(jQuery); diff --git a/srcs/wordpress/wp-admin/js/nav-menu.min.js b/srcs/wordpress/wp-admin/js/nav-menu.min.js deleted file mode 100644 index fbbe89b..0000000 --- a/srcs/wordpress/wp-admin/js/nav-menu.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(y){var k;k=window.wpNavMenu={options:{menuItemDepthPerLevel:30,globalMaxDepth:11,sortableItems:"> *",targetTolerance:0},menuList:void 0,targetList:void 0,menusChanged:!1,isRTL:!("undefined"==typeof isRtl||!isRtl),negateIfRTL:"undefined"!=typeof isRtl&&isRtl?-1:1,lastSearch:"",init:function(){k.menuList=y("#menu-to-edit"),k.targetList=k.menuList,this.jQueryExtensions(),this.attachMenuEditListeners(),this.attachQuickSearchListeners(),this.attachThemeLocationsListeners(),this.attachMenuSaveSubmitListeners(),this.attachTabsPanelListeners(),this.attachUnsavedChangesListener(),k.menuList.length&&this.initSortables(),menus.oneThemeLocationNoMenus&&y("#posttype-page").addSelectedToMenu(k.addMenuItemToBottom),this.initManageLocations(),this.initAccessibility(),this.initToggles(),this.initPreviewing()},jQueryExtensions:function(){y.fn.extend({menuItemDepth:function(){var e=k.isRTL?this.eq(0).css("margin-right"):this.eq(0).css("margin-left");return k.pxToDepth(e&&-1!=e.indexOf("px")?e.slice(0,-2):0)},updateDepthClass:function(t,n){return this.each(function(){var e=y(this);n=n||e.menuItemDepth(),y(this).removeClass("menu-item-depth-"+n).addClass("menu-item-depth-"+t)})},shiftDepthClass:function(i){return this.each(function(){var e=y(this),t=e.menuItemDepth(),n=t+i;e.removeClass("menu-item-depth-"+t).addClass("menu-item-depth-"+n),0===n&&e.find(".is-submenu").hide()})},childMenuItems:function(){var i=y();return this.each(function(){for(var e=y(this),t=e.menuItemDepth(),n=e.next(".menu-item");n.length&&n.menuItemDepth()>t;)i=i.add(n),n=n.next(".menu-item")}),i},shiftHorizontally:function(i){return this.each(function(){var e=y(this),t=e.menuItemDepth(),n=t+i;e.moveHorizontally(n,t)})},moveHorizontally:function(a,s){return this.each(function(){var e=y(this),t=e.childMenuItems(),i=a-s,n=e.find(".is-submenu");e.updateDepthClass(a,s).updateParentMenuItemDBId(),t&&t.each(function(){var e=y(this),t=e.menuItemDepth(),n=t+i;e.updateDepthClass(n,t).updateParentMenuItemDBId()}),0===a?n.hide():n.show()})},updateParentMenuItemDBId:function(){return this.each(function(){var e=y(this),t=e.find(".menu-item-data-parent-id"),n=parseInt(e.menuItemDepth(),10),i=n-1,a=e.prevAll(".menu-item-depth-"+i).first();0===n?t.val(0):t.val(a.find(".menu-item-data-db-id").val())})},hideAdvancedMenuItemFields:function(){return this.each(function(){var e=y(this);y(".hide-column-tog").not(":checked").each(function(){e.find(".field-"+y(this).val()).addClass("hidden-field")})})},addSelectedToMenu:function(s){return 0!==y("#menu-to-edit").length&&this.each(function(){var e=y(this),i={},t=menus.oneThemeLocationNoMenus&&0===e.find(".tabs-panel-active .categorychecklist li input:checked").length?e.find('#page-all li input[type="checkbox"]'):e.find(".tabs-panel-active .categorychecklist li input:checked"),a=/menu-item\[([^\]]*)/;if(s=s||k.addMenuItemToBottom,!t.length)return!1;e.find(".button-controls .spinner").addClass("is-active"),y(t).each(function(){var e=y(this),t=a.exec(e.attr("name")),n=void 0===t[1]?0:parseInt(t[1],10);this.className&&-1!=this.className.indexOf("add-to-top")&&(s=k.addMenuItemToTop),i[n]=e.closest("li").getItemData("add-menu-item",n)}),k.addItemToMenu(i,s,function(){t.prop("checked",!1),e.find(".button-controls .select-all").prop("checked",!1),e.find(".button-controls .spinner").removeClass("is-active")})})},getItemData:function(t,n){t=t||"menu-item";var i,a={},s=["menu-item-db-id","menu-item-object-id","menu-item-object","menu-item-parent-id","menu-item-position","menu-item-type","menu-item-title","menu-item-url","menu-item-description","menu-item-attr-title","menu-item-target","menu-item-classes","menu-item-xfn"];return n||"menu-item"!=t||(n=this.find(".menu-item-data-db-id").val()),n&&this.find("input").each(function(){var e;for(i=s.length;i--;)"menu-item"==t?e=s[i]+"["+n+"]":"add-menu-item"==t&&(e="menu-item["+n+"]["+s[i]+"]"),this.name&&e==this.name&&(a[s[i]]=this.value)}),a},setItemData:function(e,a,s){return a=a||"menu-item",s||"menu-item"!=a||(s=y(".menu-item-data-db-id",this).val()),s&&this.find("input").each(function(){var n,i=y(this);y.each(e,function(e,t){"menu-item"==a?n=e+"["+s+"]":"add-menu-item"==a&&(n="menu-item["+s+"]["+e+"]"),n==i.attr("name")&&i.val(t)})}),this}})},countMenuItems:function(e){return y(".menu-item-depth-"+e).length},moveMenuItem:function(e,t){var n,i,a,s=y("#menu-to-edit li"),m=s.length,u=e.parents("li.menu-item"),o=u.childMenuItems(),r=u.getItemData(),c=parseInt(u.menuItemDepth(),10),l=parseInt(u.index(),10),d=u.next(),h=d.childMenuItems(),f=parseInt(d.menuItemDepth(),10)+1,p=u.prev(),v=parseInt(p.menuItemDepth(),10),g=p.getItemData()["menu-item-db-id"];switch(t){case"up":if(i=l-1,0===l)break;0==i&&0!==c&&u.moveHorizontally(0,c),0!==v&&u.moveHorizontally(v,c),o?(n=u.add(o)).detach().insertBefore(s.eq(i)).updateParentMenuItemDBId():u.detach().insertBefore(s.eq(i)).updateParentMenuItemDBId();break;case"down":if(o){if(n=u.add(o),(h=0!==(d=s.eq(n.length+l)).childMenuItems().length)&&(a=parseInt(d.menuItemDepth(),10)+1,u.moveHorizontally(a,c)),m===l+n.length)break;n.detach().insertAfter(s.eq(l+n.length)).updateParentMenuItemDBId()}else{if(0!==h.length&&u.moveHorizontally(f,c),m===l+1)break;u.detach().insertAfter(s.eq(l+1)).updateParentMenuItemDBId()}break;case"top":if(0===l)break;o?(n=u.add(o)).detach().insertBefore(s.eq(0)).updateParentMenuItemDBId():u.detach().insertBefore(s.eq(0)).updateParentMenuItemDBId();break;case"left":if(0===c)break;u.shiftHorizontally(-1);break;case"right":if(0===l)break;if(r["menu-item-parent-id"]===g)break;u.shiftHorizontally(1)}e.focus(),k.registerChange(),k.refreshKeyboardAccessibility(),k.refreshAdvancedAccessibility()},initAccessibility:function(){var e=y("#menu-to-edit");k.refreshKeyboardAccessibility(),k.refreshAdvancedAccessibility(),e.on("mouseenter.refreshAccessibility focus.refreshAccessibility touchstart.refreshAccessibility",".menu-item",function(){k.refreshAdvancedAccessibilityOfItem(y(this).find("a.item-edit"))}),e.on("click","a.item-edit",function(){k.refreshAdvancedAccessibilityOfItem(y(this))}),e.on("click",".menus-move",function(){var e=y(this).data("dir");void 0!==e&&k.moveMenuItem(y(this).parents("li.menu-item").find("a.item-edit"),e)})},refreshAdvancedAccessibilityOfItem:function(e){if(!0===y(e).data("needs_accessibility_refresh")){var t,n,i,a,s,m,u,o,r,c=y(e),l=c.closest("li.menu-item").first(),d=l.menuItemDepth(),h=0===d,f=c.closest(".menu-item-handle").find(".menu-item-title").text(),p=parseInt(l.index(),10),v=h?d:parseInt(d-1,10),g=l.prevAll(".menu-item-depth-"+v).first().find(".menu-item-title").text(),b=l.prevAll(".menu-item-depth-"+d).first().find(".menu-item-title").text(),I=y("#menu-to-edit li").length,k=l.nextAll(".menu-item-depth-"+d).length;l.find(".field-move").toggle(1<I),0!==p&&(t=l.find(".menus-move-up")).attr("aria-label",menus.moveUp).css("display","inline"),0!==p&&h&&(t=l.find(".menus-move-top")).attr("aria-label",menus.moveToTop).css("display","inline"),p+1!==I&&0!==p&&(t=l.find(".menus-move-down")).attr("aria-label",menus.moveDown).css("display","inline"),0===p&&0!==k&&(t=l.find(".menus-move-down")).attr("aria-label",menus.moveDown).css("display","inline"),h||(t=l.find(".menus-move-left"),n=menus.outFrom.replace("%s",g),t.attr("aria-label",menus.moveOutFrom.replace("%s",g)).text(n).css("display","inline")),0!==p&&l.find(".menu-item-data-parent-id").val()!==l.prev().find(".menu-item-data-db-id").val()&&(t=l.find(".menus-move-right"),n=menus.under.replace("%s",b),t.attr("aria-label",menus.moveUnder.replace("%s",b)).text(n).css("display","inline")),s=h?(a=(i=y(".menu-item-depth-0")).index(l)+1,I=i.length,menus.menuFocus.replace("%1$s",f).replace("%2$d",a).replace("%3$d",I)):(u=(m=l.prevAll(".menu-item-depth-"+parseInt(d-1,10)).first()).find(".menu-item-data-db-id").val(),o=m.find(".menu-item-title").text(),r=y('.menu-item .menu-item-data-parent-id[value="'+u+'"]'),a=y(r.parents(".menu-item").get().reverse()).index(l)+1,menus.subMenuFocus.replace("%1$s",f).replace("%2$d",a).replace("%3$s",o)),c.attr("aria-label",s),c.data("needs_accessibility_refresh",!1)}},refreshAdvancedAccessibility:function(){y(".menu-item-settings .field-move .menus-move").hide(),y("a.item-edit").data("needs_accessibility_refresh",!0),y(".menu-item-edit-active a.item-edit").each(function(){k.refreshAdvancedAccessibilityOfItem(this)})},refreshKeyboardAccessibility:function(){y("a.item-edit").off("focus").on("focus",function(){y(this).off("keydown").on("keydown",function(e){var t,n=y(this),i=n.parents("li.menu-item").getItemData();if((37==e.which||38==e.which||39==e.which||40==e.which)&&(n.off("keydown"),1!==y("#menu-to-edit li").length)){switch(t={38:"up",40:"down",37:"left",39:"right"},y("body").hasClass("rtl")&&(t={38:"up",40:"down",39:"left",37:"right"}),t[e.which]){case"up":k.moveMenuItem(n,"up");break;case"down":k.moveMenuItem(n,"down");break;case"left":k.moveMenuItem(n,"left");break;case"right":k.moveMenuItem(n,"right")}return y("#edit-"+i["menu-item-db-id"]).focus(),!1}})})},initPreviewing:function(){y("#menu-to-edit").on("change input",".edit-menu-item-title",function(e){var t,n,i=y(e.currentTarget);t=i.val(),n=i.closest(".menu-item").find(".menu-item-title"),t?n.text(t).removeClass("no-title"):n.text(navMenuL10n.untitled).addClass("no-title")})},initToggles:function(){postboxes.add_postbox_toggles("nav-menus"),columns.useCheckboxesForHidden(),columns.checked=function(e){y(".field-"+e).removeClass("hidden-field")},columns.unchecked=function(e){y(".field-"+e).addClass("hidden-field")},k.menuList.hideAdvancedMenuItemFields(),y(".hide-postbox-tog").click(function(){var e=y(".accordion-container li.accordion-section").filter(":hidden").map(function(){return this.id}).get().join(",");y.post(ajaxurl,{action:"closed-postboxes",hidden:e,closedpostboxesnonce:jQuery("#closedpostboxesnonce").val(),page:"nav-menus"})})},initSortables:function(){var m,s,u,n,o,r,c,l,d,h,f=0,p=k.menuList.offset().left,v=y("body"),g=function(){if(!v[0].className)return 0;var e=v[0].className.match(/menu-max-depth-(\d+)/);return e&&e[1]?parseInt(e[1],10):0}();function b(e){var t;n=e.placeholder.prev(".menu-item"),o=e.placeholder.next(".menu-item"),n[0]==e.item[0]&&(n=n.prev(".menu-item")),o[0]==e.item[0]&&(o=o.next(".menu-item")),r=n.length?n.offset().top+n.height():0,c=o.length?o.offset().top+o.height()/3:0,s=o.length?o.menuItemDepth():0,u=n.length?(t=n.menuItemDepth()+1)>k.options.globalMaxDepth?k.options.globalMaxDepth:t:0}function I(e,t){e.placeholder.updateDepthClass(t,f),f=t}0!==y("#menu-to-edit li").length&&y(".drag-instructions").show(),p+=k.isRTL?k.menuList.width():0,k.menuList.sortable({handle:".menu-item-handle",placeholder:"sortable-placeholder",items:k.options.sortableItems,start:function(e,t){var n,i,a,s;k.isRTL&&(t.item[0].style.right="auto"),d=t.item.children(".menu-item-transport"),m=t.item.menuItemDepth(),I(t,m),a=(t.item.next()[0]==t.placeholder[0]?t.item.next():t.item).childMenuItems(),d.append(a),n=d.outerHeight(),n+=0<n?1*t.placeholder.css("margin-top").slice(0,-2):0,n+=t.helper.outerHeight(),l=n,n-=2,t.placeholder.height(n),h=m,a.each(function(){var e=y(this).menuItemDepth();h=h<e?e:h}),i=t.helper.find(".menu-item-handle").outerWidth(),i+=k.depthToPx(h-m),i-=2,t.placeholder.width(i),(s=t.placeholder.next(".menu-item")).css("margin-top",l+"px"),t.placeholder.detach(),y(this).sortable("refresh"),t.item.after(t.placeholder),s.css("margin-top",0),b(t)},stop:function(e,t){var n,i,a=f-m;n=d.children().insertAfter(t.item),i=t.item.find(".item-title .is-submenu"),0<f?i.show():i.hide(),0!=a&&(t.item.updateDepthClass(f),n.shiftDepthClass(a),function(e){var t,n=g;{if(0===e)return;if(0<e)g<(t=h+e)&&(n=t);else if(e<0&&h==g)for(;!y(".menu-item-depth-"+n,k.menuList).length&&0<n;)n--}v.removeClass("menu-max-depth-"+g).addClass("menu-max-depth-"+n),g=n}(a)),k.registerChange(),t.item.updateParentMenuItemDBId(),t.item[0].style.top=0,k.isRTL&&(t.item[0].style.left="auto",t.item[0].style.right=0),k.refreshKeyboardAccessibility(),k.refreshAdvancedAccessibility()},change:function(e,t){t.placeholder.parent().hasClass("menu")||(n.length?n.after(t.placeholder):k.menuList.prepend(t.placeholder)),b(t)},sort:function(e,t){var n=t.helper.offset(),i=k.isRTL?n.left+t.helper.width():n.left,a=k.negateIfRTL*k.pxToDepth(i-p);u<a||n.top<r-k.options.targetTolerance?a=u:a<s&&(a=s),a!=f&&I(t,a),c&&n.top+l>c&&(o.after(t.placeholder),b(t),y(this).sortable("refreshPositions"))}})},initManageLocations:function(){y("#menu-locations-wrap form").submit(function(){window.onbeforeunload=null}),y(".menu-location-menus select").on("change",function(){var e=y(this).closest("tr").find(".locations-edit-menu-link");y(this).find("option:selected").data("orig")?e.show():e.hide()})},attachMenuEditListeners:function(){var t=this;y("#update-nav-menu").bind("click",function(e){if(e.target&&e.target.className){if(-1!=e.target.className.indexOf("item-edit"))return t.eventOnClickEditLink(e.target);if(-1!=e.target.className.indexOf("menu-save"))return t.eventOnClickMenuSave(e.target);if(-1!=e.target.className.indexOf("menu-delete"))return t.eventOnClickMenuDelete(e.target);if(-1!=e.target.className.indexOf("item-delete"))return t.eventOnClickMenuItemDelete(e.target);if(-1!=e.target.className.indexOf("item-cancel"))return t.eventOnClickCancelLink(e.target)}}),y("#menu-name").on("input",_.debounce(function(){var e=y(document.getElementById("menu-name")),t=e.val();t&&t.replace(/\s+/,"")?e.parent().removeClass("form-invalid"):e.parent().addClass("form-invalid")},500)),y('#add-custom-links input[type="text"]').keypress(function(e){y("#customlinkdiv").removeClass("form-invalid"),13===e.keyCode&&(e.preventDefault(),y("#submit-customlinkdiv").click())})},attachMenuSaveSubmitListeners:function(){y("#update-nav-menu").submit(function(){var e=y("#update-nav-menu").serializeArray();y('[name="nav-menu-data"]').val(JSON.stringify(e))})},attachThemeLocationsListeners:function(){var e=y("#nav-menu-theme-locations"),t={action:"menu-locations-save"};t["menu-settings-column-nonce"]=y("#menu-settings-column-nonce").val(),e.find('input[type="submit"]').click(function(){return e.find("select").each(function(){t[this.name]=y(this).val()}),e.find(".spinner").addClass("is-active"),y.post(ajaxurl,t,function(){e.find(".spinner").removeClass("is-active")}),!1})},attachQuickSearchListeners:function(){var t;y("#nav-menu-meta").on("submit",function(e){e.preventDefault()}),y("#nav-menu-meta").on("input",".quick-search",function(){var e=y(this);e.attr("autocomplete","off"),t&&clearTimeout(t),t=setTimeout(function(){k.updateQuickSearchResults(e)},500)}).on("blur",".quick-search",function(){k.lastSearch=""})},updateQuickSearchResults:function(e){var t,n,i=e.val();i.length<2||k.lastSearch==i||(k.lastSearch=i,t=e.parents(".tabs-panel"),n={action:"menu-quick-search","response-format":"markup",menu:y("#menu").val(),"menu-settings-column-nonce":y("#menu-settings-column-nonce").val(),q:i,type:e.attr("name")},y(".spinner",t).addClass("is-active"),y.post(ajaxurl,n,function(e){k.processQuickSearchQueryResponse(e,n,t)}))},addCustomLink:function(e){var t=y("#custom-menu-item-url").val().trim(),n=y("#custom-menu-item-name").val();if(e=e||k.addMenuItemToBottom,""===t||"https://"==t||"http://"==t)return y("#customlinkdiv").addClass("form-invalid"),!1;y(".customlinkdiv .spinner").addClass("is-active"),this.addLinkToMenu(t,n,e,function(){y(".customlinkdiv .spinner").removeClass("is-active"),y("#custom-menu-item-name").val("").blur(),y("#custom-menu-item-url").val("").attr("placeholder","https://")})},addLinkToMenu:function(e,t,n,i){n=n||k.addMenuItemToBottom,i=i||function(){},k.addItemToMenu({"-1":{"menu-item-type":"custom","menu-item-url":e,"menu-item-title":t}},n,i)},addItemToMenu:function(e,n,i){var a,t=y("#menu").val(),s=y("#menu-settings-column-nonce").val();n=n||function(){},i=i||function(){},a={action:"add-menu-item",menu:t,"menu-settings-column-nonce":s,"menu-item":e},y.post(ajaxurl,a,function(e){var t=y("#menu-instructions");e=y.trim(e),n(e,a),y("li.pending").hide().fadeIn("slow"),y(".drag-instructions").show(),!t.hasClass("menu-instructions-inactive")&&t.siblings().length&&t.addClass("menu-instructions-inactive"),i()})},addMenuItemToBottom:function(e){var t=y(e);t.hideAdvancedMenuItemFields().appendTo(k.targetList),k.refreshKeyboardAccessibility(),k.refreshAdvancedAccessibility(),y(document).trigger("menu-item-added",[t])},addMenuItemToTop:function(e){var t=y(e);t.hideAdvancedMenuItemFields().prependTo(k.targetList),k.refreshKeyboardAccessibility(),k.refreshAdvancedAccessibility(),y(document).trigger("menu-item-added",[t])},attachUnsavedChangesListener:function(){y("#menu-management input, #menu-management select, #menu-management, #menu-management textarea, .menu-location-menus select").change(function(){k.registerChange()}),0!==y("#menu-to-edit").length||0!==y(".menu-location-menus select").length?window.onbeforeunload=function(){if(k.menusChanged)return navMenuL10n.saveAlert}:y("#menu-settings-column").find("input,select").end().find("a").attr("href","#").unbind("click")},registerChange:function(){k.menusChanged=!0},attachTabsPanelListeners:function(){y("#menu-settings-column").bind("click",function(e){var t,n,i,a,s,m=y(e.target);if(m.hasClass("nav-tab-link"))i=m.data("type"),a=m.parents(".accordion-section-content").first(),y("input",a).prop("checked",!1),y(".tabs-panel-active",a).removeClass("tabs-panel-active").addClass("tabs-panel-inactive"),y("#"+i,a).removeClass("tabs-panel-inactive").addClass("tabs-panel-active"),y(".tabs",a).removeClass("tabs"),m.parent().addClass("tabs"),y(".quick-search",a).focus(),a.find(".tabs-panel-active .menu-item-title").length?a.removeClass("has-no-menu-item"):a.addClass("has-no-menu-item"),e.preventDefault();else if(m.hasClass("select-all"))(t=m.closest(".button-controls").data("items-type"))&&((s=y("#"+t+" .tabs-panel-active .menu-item-title input")).length!==s.filter(":checked").length||m.is(":checked")?m.is(":checked")&&s.prop("checked",!0):s.prop("checked",!1));else if(m.hasClass("menu-item-checkbox"))(t=m.closest(".tabs-panel-active").parent().attr("id"))&&(s=y("#"+t+" .tabs-panel-active .menu-item-title input"),n=y('.button-controls[data-items-type="'+t+'"] .select-all'),s.length!==s.filter(":checked").length||n.is(":checked")?n.is(":checked")&&n.prop("checked",!1):n.prop("checked",!0));else if(m.hasClass("submit-add-to-menu"))return k.registerChange(),e.target.id&&"submit-customlinkdiv"==e.target.id?k.addCustomLink(k.addMenuItemToBottom):e.target.id&&-1!=e.target.id.indexOf("submit-")&&y("#"+e.target.id.replace(/submit-/,"")).addSelectedToMenu(k.addMenuItemToBottom),!1}),y("#nav-menu-meta").on("click","a.page-numbers",function(){var i=y(this).closest(".inside");return y.post(ajaxurl,this.href.replace(/.*\?/,"").replace(/action=([^&]*)/,"")+"&action=menu-get-metabox",function(e){var t,n=y.parseJSON(e);-1!==e.indexOf("replace-id")&&(t=document.getElementById(n["replace-id"]),n.markup&&t&&i.html(n.markup))}),!1})},eventOnClickEditLink:function(e){var t,n,i=/#(.*)$/.exec(e.href);if(i&&i[1]&&0!==(n=(t=y("#"+i[1])).parent()).length)return n.hasClass("menu-item-edit-inactive")?(t.data("menu-item-data")||t.data("menu-item-data",t.getItemData()),t.slideDown("fast"),n.removeClass("menu-item-edit-inactive").addClass("menu-item-edit-active")):(t.slideUp("fast"),n.removeClass("menu-item-edit-active").addClass("menu-item-edit-inactive")),!1},eventOnClickCancelLink:function(e){var t=y(e).closest(".menu-item-settings");return y(e).closest(".menu-item").removeClass("menu-item-edit-active").addClass("menu-item-edit-inactive"),t.setItemData(t.data("menu-item-data")).hide(),!1},eventOnClickMenuSave:function(){var e="",t=y("#menu-name"),n=t.val();return n&&n.replace(/\s+/,"")?(y("#nav-menu-theme-locations select").each(function(){e+='<input type="hidden" name="'+this.name+'" value="'+y(this).val()+'" />'}),y("#update-nav-menu").append(e),k.menuList.find(".menu-item-data-position").val(function(e){return e+1}),!(window.onbeforeunload=null)):(t.parent().addClass("form-invalid"),!1)},eventOnClickMenuDelete:function(){return!!window.confirm(navMenuL10n.warnDeleteMenu)&&!(window.onbeforeunload=null)},eventOnClickMenuItemDelete:function(e){var t=parseInt(e.id.replace("delete-",""),10);return k.removeMenuItem(y("#menu-item-"+t)),k.registerChange(),!1},processQuickSearchQueryResponse:function(e,t,n){var i,a,s,m={},u=document.getElementById("nav-menu-meta"),o=/menu-item[(\[^]\]*/,r=y("<div>").html(e).find("li"),c=n.closest(".accordion-section-content"),l=c.find(".button-controls .select-all");if(!r.length)return y(".categorychecklist",n).html("<li><p>"+navMenuL10n.noResultsFound+"</p></li>"),y(".spinner",n).removeClass("is-active"),void c.addClass("has-no-menu-item");r.each(function(){if(s=y(this),(i=o.exec(s.html()))&&i[1]){for(a=i[1];u.elements["menu-item["+a+"][menu-item-type]"]||m[a];)a--;m[a]=!0,a!=i[1]&&s.html(s.html().replace(new RegExp("menu-item\\["+i[1]+"\\]","g"),"menu-item["+a+"]"))}}),y(".categorychecklist",n).html(r),y(".spinner",n).removeClass("is-active"),c.removeClass("has-no-menu-item"),l.is(":checked")&&l.prop("checked",!1)},removeMenuItem:function(t){var n=t.childMenuItems();y(document).trigger("menu-removing-item",[t]),t.addClass("deleting").animate({opacity:0,height:0},350,function(){var e=y("#menu-instructions");t.remove(),n.shiftDepthClass(-1).updateParentMenuItemDBId(),0===y("#menu-to-edit li").length&&(y(".drag-instructions").hide(),e.removeClass("menu-instructions-inactive")),k.refreshAdvancedAccessibility()})},depthToPx:function(e){return e*k.options.menuItemDepthPerLevel},pxToDepth:function(e){return Math.floor(e/k.options.menuItemDepthPerLevel)}},y(document).ready(function(){wpNavMenu.init()})}(jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/password-strength-meter.js b/srcs/wordpress/wp-admin/js/password-strength-meter.js deleted file mode 100644 index 753f697..0000000 --- a/srcs/wordpress/wp-admin/js/password-strength-meter.js +++ /dev/null @@ -1,121 +0,0 @@ -/** - * @output wp-admin/js/password-strength-meter.js - */ - -/* global zxcvbn */ -window.wp = window.wp || {}; - -(function($){ - - /** - * Contains functions to determine the password strength. - * - * @since 3.7.0 - * - * @namespace - */ - wp.passwordStrength = { - /** - * Determines the strength of a given password. - * - * Compares first password to the password confirmation. - * - * @since 3.7.0 - * - * @param {string} password1 The subject password. - * @param {Array} blacklist An array of words that will lower the entropy of - * the password. - * @param {string} password2 The password confirmation. - * - * @returns {number} The password strength score. - */ - meter : function( password1, blacklist, password2 ) { - if ( ! $.isArray( blacklist ) ) - blacklist = [ blacklist.toString() ]; - - if (password1 != password2 && password2 && password2.length > 0) - return 5; - - if ( 'undefined' === typeof window.zxcvbn ) { - // Password strength unknown. - return -1; - } - - var result = zxcvbn( password1, blacklist ); - return result.score; - }, - - /** - * Builds an array of words that should be penalized. - * - * Certain words need to be penalized because it would lower the entropy of a - * password if they were used. The blacklist is based on user input fields such - * as username, first name, email etc. - * - * @since 3.7.0 - * - * @returns {string[]} The array of words to be blacklisted. - */ - userInputBlacklist : function() { - var i, userInputFieldsLength, rawValuesLength, currentField, - rawValues = [], - blacklist = [], - userInputFields = [ 'user_login', 'first_name', 'last_name', 'nickname', 'display_name', 'email', 'url', 'description', 'weblog_title', 'admin_email' ]; - - // Collect all the strings we want to blacklist. - rawValues.push( document.title ); - rawValues.push( document.URL ); - - userInputFieldsLength = userInputFields.length; - for ( i = 0; i < userInputFieldsLength; i++ ) { - currentField = $( '#' + userInputFields[ i ] ); - - if ( 0 === currentField.length ) { - continue; - } - - rawValues.push( currentField[0].defaultValue ); - rawValues.push( currentField.val() ); - } - - /* - * Strip out non-alphanumeric characters and convert each word to an - * individual entry. - */ - rawValuesLength = rawValues.length; - for ( i = 0; i < rawValuesLength; i++ ) { - if ( rawValues[ i ] ) { - blacklist = blacklist.concat( rawValues[ i ].replace( /\W/g, ' ' ).split( ' ' ) ); - } - } - - /* - * Remove empty values, short words and duplicates. Short words are likely to - * cause many false positives. - */ - blacklist = $.grep( blacklist, function( value, key ) { - if ( '' === value || 4 > value.length ) { - return false; - } - - return $.inArray( value, blacklist ) === key; - }); - - return blacklist; - } - }; - - // Backward compatibility. - - /** - * Password strength meter function. - * - * @since 2.5.0 - * @deprecated 3.7.0 Use wp.passwordStrength.meter instead. - * - * @global - * - * @type {wp.passwordStrength.meter} - */ - window.passwordStrength = wp.passwordStrength.meter; -})(jQuery); diff --git a/srcs/wordpress/wp-admin/js/password-strength-meter.min.js b/srcs/wordpress/wp-admin/js/password-strength-meter.min.js deleted file mode 100644 index 4b8c77f..0000000 --- a/srcs/wordpress/wp-admin/js/password-strength-meter.min.js +++ /dev/null @@ -1 +0,0 @@ -window.wp=window.wp||{},function(l){wp.passwordStrength={meter:function(n,e,t){return l.isArray(e)||(e=[e.toString()]),n!=t&&t&&0<t.length?5:void 0===window.zxcvbn?-1:zxcvbn(n,e).score},userInputBlacklist:function(){var n,e,t,r,i=[],o=[],a=["user_login","first_name","last_name","nickname","display_name","email","url","description","weblog_title","admin_email"];for(i.push(document.title),i.push(document.URL),e=a.length,n=0;n<e;n++)0!==(r=l("#"+a[n])).length&&(i.push(r[0].defaultValue),i.push(r.val()));for(t=i.length,n=0;n<t;n++)i[n]&&(o=o.concat(i[n].replace(/\W/g," ").split(" ")));return o=l.grep(o,function(n,e){return!(""===n||n.length<4)&&l.inArray(n,o)===e})}},window.passwordStrength=wp.passwordStrength.meter}(jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/plugin-install.js b/srcs/wordpress/wp-admin/js/plugin-install.js deleted file mode 100644 index b6cd1d7..0000000 --- a/srcs/wordpress/wp-admin/js/plugin-install.js +++ /dev/null @@ -1,222 +0,0 @@ -/** - * @file Functionality for the plugin install screens. - * - * @output wp-admin/js/plugin-install.js - */ - -/* global plugininstallL10n, tb_click, tb_remove, tb_position */ - -jQuery( document ).ready( function( $ ) { - - var tbWindow, - $iframeBody, - $tabbables, - $firstTabbable, - $lastTabbable, - $focusedBefore = $(), - $uploadViewToggle = $( '.upload-view-toggle' ), - $wrap = $ ( '.wrap' ), - $body = $( document.body ); - - window.tb_position = function() { - var width = $( window ).width(), - H = $( window ).height() - ( ( 792 < width ) ? 60 : 20 ), - W = ( 792 < width ) ? 772 : width - 20; - - tbWindow = $( '#TB_window' ); - - if ( tbWindow.length ) { - tbWindow.width( W ).height( H ); - $( '#TB_iframeContent' ).width( W ).height( H ); - tbWindow.css({ - 'margin-left': '-' + parseInt( ( W / 2 ), 10 ) + 'px' - }); - if ( typeof document.body.style.maxWidth !== 'undefined' ) { - tbWindow.css({ - 'top': '30px', - 'margin-top': '0' - }); - } - } - - return $( 'a.thickbox' ).each( function() { - var href = $( this ).attr( 'href' ); - if ( ! href ) { - return; - } - href = href.replace( /&width=[0-9]+/g, '' ); - href = href.replace( /&height=[0-9]+/g, '' ); - $(this).attr( 'href', href + '&width=' + W + '&height=' + ( H ) ); - }); - }; - - $( window ).resize( function() { - tb_position(); - }); - - /* - * Custom events: when a Thickbox iframe has loaded and when the Thickbox - * modal gets removed from the DOM. - */ - $body - .on( 'thickbox:iframe:loaded', tbWindow, function() { - /* - * Return if it's not the modal with the plugin details iframe. Other - * thickbox instances might want to load an iframe with content from - * an external domain. Avoid to access the iframe contents when we're - * not sure the iframe loads from the same domain. - */ - if ( ! tbWindow.hasClass( 'plugin-details-modal' ) ) { - return; - } - - iframeLoaded(); - }) - .on( 'thickbox:removed', function() { - // Set focus back to the element that opened the modal dialog. - // Note: IE 8 would need this wrapped in a fake setTimeout `0`. - $focusedBefore.focus(); - }); - - function iframeLoaded() { - var $iframe = tbWindow.find( '#TB_iframeContent' ); - - // Get the iframe body. - $iframeBody = $iframe.contents().find( 'body' ); - - // Get the tabbable elements and handle the keydown event on first load. - handleTabbables(); - - // Set initial focus on the "Close" button. - $firstTabbable.focus(); - - /* - * When the "Install" button is disabled (e.g. the Plugin is already installed) - * then we can't predict where the last focusable element is. We need to get - * the tabbable elements and handle the keydown event again and again, - * each time the active tab panel changes. - */ - $( '#plugin-information-tabs a', $iframeBody ).on( 'click', function() { - handleTabbables(); - }); - - // Close the modal when pressing Escape. - $iframeBody.on( 'keydown', function( event ) { - if ( 27 !== event.which ) { - return; - } - tb_remove(); - }); - } - - /* - * Get the tabbable elements and detach/attach the keydown event. - * Called after the iframe has fully loaded so we have all the elements we need. - * Called again each time a Tab gets clicked. - * @todo Consider to implement a WordPress general utility for this and don't use jQuery UI. - */ - function handleTabbables() { - var $firstAndLast; - // Get all the tabbable elements. - $tabbables = $( ':tabbable', $iframeBody ); - // Our first tabbable element is always the "Close" button. - $firstTabbable = tbWindow.find( '#TB_closeWindowButton' ); - // Get the last tabbable element. - $lastTabbable = $tabbables.last(); - // Make a jQuery collection. - $firstAndLast = $firstTabbable.add( $lastTabbable ); - // Detach any previously attached keydown event. - $firstAndLast.off( 'keydown.wp-plugin-details' ); - // Attach again the keydown event on the first and last focusable elements. - $firstAndLast.on( 'keydown.wp-plugin-details', function( event ) { - constrainTabbing( event ); - }); - } - - // Constrain tabbing within the plugin modal dialog. - function constrainTabbing( event ) { - if ( 9 !== event.which ) { - return; - } - - if ( $lastTabbable[0] === event.target && ! event.shiftKey ) { - event.preventDefault(); - $firstTabbable.focus(); - } else if ( $firstTabbable[0] === event.target && event.shiftKey ) { - event.preventDefault(); - $lastTabbable.focus(); - } - } - - /* - * Open the Plugin details modal. The event is delegated to get also the links - * in the plugins search tab, after the AJAX search rebuilds the HTML. It's - * delegated on the closest ancestor and not on the body to avoid conflicts - * with other handlers, see Trac ticket #43082. - */ - $( '.wrap' ).on( 'click', '.thickbox.open-plugin-details-modal', function( e ) { - // The `data-title` attribute is used only in the Plugin screens. - var title = $( this ).data( 'title' ) ? plugininstallL10n.plugin_information + ' ' + $( this ).data( 'title' ) : plugininstallL10n.plugin_modal_label; - - e.preventDefault(); - e.stopPropagation(); - - // Store the element that has focus before opening the modal dialog, i.e. the control which opens it. - $focusedBefore = $( this ); - - tb_click.call(this); - - // Set ARIA role, ARIA label, and add a CSS class. - tbWindow - .attr({ - 'role': 'dialog', - 'aria-label': plugininstallL10n.plugin_modal_label - }) - .addClass( 'plugin-details-modal' ); - - // Set title attribute on the iframe. - tbWindow.find( '#TB_iframeContent' ).attr( 'title', title ); - }); - - /* Plugin install related JS */ - $( '#plugin-information-tabs a' ).click( function( event ) { - var tab = $( this ).attr( 'name' ); - event.preventDefault(); - - // Flip the tab - $( '#plugin-information-tabs a.current' ).removeClass( 'current' ); - $( this ).addClass( 'current' ); - - // Only show the fyi box in the description section, on smaller screen, where it's otherwise always displayed at the top. - if ( 'description' !== tab && $( window ).width() < 772 ) { - $( '#plugin-information-content' ).find( '.fyi' ).hide(); - } else { - $( '#plugin-information-content' ).find( '.fyi' ).show(); - } - - // Flip the content. - $( '#section-holder div.section' ).hide(); // Hide 'em all. - $( '#section-' + tab ).show(); - }); - - /* - * When a user presses the "Upload Plugin" button, show the upload form in place - * rather than sending them to the devoted upload plugin page. - * The `?tab=upload` page still exists for no-js support and for plugins that - * might access it directly. When we're in this page, let the link behave - * like a link. Otherwise we're in the normal plugin installer pages and the - * link should behave like a toggle button. - */ - if ( ! $wrap.hasClass( 'plugin-install-tab-upload' ) ) { - $uploadViewToggle - .attr({ - role: 'button', - 'aria-expanded': 'false' - }) - .on( 'click', function( event ) { - event.preventDefault(); - $body.toggleClass( 'show-upload-view' ); - $uploadViewToggle.attr( 'aria-expanded', $body.hasClass( 'show-upload-view' ) ); - }); - } -}); diff --git a/srcs/wordpress/wp-admin/js/plugin-install.min.js b/srcs/wordpress/wp-admin/js/plugin-install.min.js deleted file mode 100644 index 8915ac6..0000000 --- a/srcs/wordpress/wp-admin/js/plugin-install.min.js +++ /dev/null @@ -1 +0,0 @@ -jQuery(document).ready(function(o){var a,i,n,e,l,d=o(),s=o(".upload-view-toggle"),t=o(".wrap"),r=o(document.body);function u(){var t;n=o(":tabbable",i),e=a.find("#TB_closeWindowButton"),l=n.last(),(t=e.add(l)).off("keydown.wp-plugin-details"),t.on("keydown.wp-plugin-details",function(t){!function(t){if(9!==t.which)return;l[0]!==t.target||t.shiftKey?e[0]===t.target&&t.shiftKey&&(t.preventDefault(),l.focus()):(t.preventDefault(),e.focus())}(t)})}window.tb_position=function(){var t=o(window).width(),i=o(window).height()-(792<t?60:20),n=792<t?772:t-20;return(a=o("#TB_window")).length&&(a.width(n).height(i),o("#TB_iframeContent").width(n).height(i),a.css({"margin-left":"-"+parseInt(n/2,10)+"px"}),void 0!==document.body.style.maxWidth&&a.css({top:"30px","margin-top":"0"})),o("a.thickbox").each(function(){var t=o(this).attr("href");t&&(t=(t=t.replace(/&width=[0-9]+/g,"")).replace(/&height=[0-9]+/g,""),o(this).attr("href",t+"&width="+n+"&height="+i))})},o(window).resize(function(){tb_position()}),r.on("thickbox:iframe:loaded",a,function(){a.hasClass("plugin-details-modal")&&function(){var t=a.find("#TB_iframeContent");i=t.contents().find("body"),u(),e.focus(),o("#plugin-information-tabs a",i).on("click",function(){u()}),i.on("keydown",function(t){27===t.which&&tb_remove()})}()}).on("thickbox:removed",function(){d.focus()}),o(".wrap").on("click",".thickbox.open-plugin-details-modal",function(t){var i=o(this).data("title")?plugininstallL10n.plugin_information+" "+o(this).data("title"):plugininstallL10n.plugin_modal_label;t.preventDefault(),t.stopPropagation(),d=o(this),tb_click.call(this),a.attr({role:"dialog","aria-label":plugininstallL10n.plugin_modal_label}).addClass("plugin-details-modal"),a.find("#TB_iframeContent").attr("title",i)}),o("#plugin-information-tabs a").click(function(t){var i=o(this).attr("name");t.preventDefault(),o("#plugin-information-tabs a.current").removeClass("current"),o(this).addClass("current"),"description"!==i&&o(window).width()<772?o("#plugin-information-content").find(".fyi").hide():o("#plugin-information-content").find(".fyi").show(),o("#section-holder div.section").hide(),o("#section-"+i).show()}),t.hasClass("plugin-install-tab-upload")||s.attr({role:"button","aria-expanded":"false"}).on("click",function(t){t.preventDefault(),r.toggleClass("show-upload-view"),s.attr("aria-expanded",r.hasClass("show-upload-view"))})});
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/post.js b/srcs/wordpress/wp-admin/js/post.js deleted file mode 100644 index ec1a0d7..0000000 --- a/srcs/wordpress/wp-admin/js/post.js +++ /dev/null @@ -1,1273 +0,0 @@ -/** - * @file Contains all dynamic functionality needed on post and term pages. - * - * @output wp-admin/js/post.js - */ - - /* global postL10n, ajaxurl, wpAjax, setPostThumbnailL10n, postboxes, pagenow, tinymce, alert, deleteUserSetting */ - /* global theList:true, theExtraList:true, getUserSetting, setUserSetting, commentReply, commentsBox */ - /* global WPSetThumbnailHTML, wptitlehint */ - -// Backwards compatibility: prevent fatal errors. -window.makeSlugeditClickable = window.editPermalink = function(){}; - -// Make sure the wp object exists. -window.wp = window.wp || {}; - -( function( $ ) { - var titleHasFocus = false; - - /** - * Control loading of comments on the post and term edit pages. - * - * @type {{st: number, get: commentsBox.get, load: commentsBox.load}} - * - * @namespace commentsBox - */ - window.commentsBox = { - // Comment offset to use when fetching new comments. - st : 0, - - /** - * Fetch comments using AJAX and display them in the box. - * - * @memberof commentsBox - * - * @param {int} total Total number of comments for this post. - * @param {int} num Optional. Number of comments to fetch, defaults to 20. - * @returns {boolean} Always returns false. - */ - get : function(total, num) { - var st = this.st, data; - if ( ! num ) - num = 20; - - this.st += num; - this.total = total; - $( '#commentsdiv .spinner' ).addClass( 'is-active' ); - - data = { - 'action' : 'get-comments', - 'mode' : 'single', - '_ajax_nonce' : $('#add_comment_nonce').val(), - 'p' : $('#post_ID').val(), - 'start' : st, - 'number' : num - }; - - $.post( - ajaxurl, - data, - function(r) { - r = wpAjax.parseAjaxResponse(r); - $('#commentsdiv .widefat').show(); - $( '#commentsdiv .spinner' ).removeClass( 'is-active' ); - - if ( 'object' == typeof r && r.responses[0] ) { - $('#the-comment-list').append( r.responses[0].data ); - - theList = theExtraList = null; - $( 'a[className*=\':\']' ).unbind(); - - // If the offset is over the total number of comments we cannot fetch any more, so hide the button. - if ( commentsBox.st > commentsBox.total ) - $('#show-comments').hide(); - else - $('#show-comments').show().children('a').html(postL10n.showcomm); - - return; - } else if ( 1 == r ) { - $('#show-comments').html(postL10n.endcomm); - return; - } - - $('#the-comment-list').append('<tr><td colspan="2">'+wpAjax.broken+'</td></tr>'); - } - ); - - return false; - }, - - /** - * Load the next batch of comments. - * - * @param {int} total Total number of comments to load. - * - * @memberof commentsBox - */ - load: function(total){ - this.st = jQuery('#the-comment-list tr.comment:visible').length; - this.get(total); - } - }; - - /** - * Overwrite the content of the Featured Image postbox - * - * @param {string} html New HTML to be displayed in the content area of the postbox. - * - * @global - */ - window.WPSetThumbnailHTML = function(html){ - $('.inside', '#postimagediv').html(html); - }; - - /** - * Set the Image ID of the Featured Image - * - * @param {int} id The post_id of the image to use as Featured Image. - * - * @global - */ - window.WPSetThumbnailID = function(id){ - var field = $('input[value="_thumbnail_id"]', '#list-table'); - if ( field.length > 0 ) { - $('#meta\\[' + field.attr('id').match(/[0-9]+/) + '\\]\\[value\\]').text(id); - } - }; - - /** - * Remove the Featured Image - * - * @param {string} nonce Nonce to use in the request. - * - * @global - */ - window.WPRemoveThumbnail = function(nonce){ - $.post(ajaxurl, { - action: 'set-post-thumbnail', post_id: $( '#post_ID' ).val(), thumbnail_id: -1, _ajax_nonce: nonce, cookie: encodeURIComponent( document.cookie ) - }, - /** - * Handle server response - * - * @param {string} str Response, will be '0' when an error occurred otherwise contains link to add Featured Image. - */ - function(str){ - if ( str == '0' ) { - alert( setPostThumbnailL10n.error ); - } else { - WPSetThumbnailHTML(str); - } - } - ); - }; - - /** - * Heartbeat locks. - * - * Used to lock editing of an object by only one user at a time. - * - * When the user does not send a heartbeat in a heartbeat-time - * the user is no longer editing and another user can start editing. - */ - $(document).on( 'heartbeat-send.refresh-lock', function( e, data ) { - var lock = $('#active_post_lock').val(), - post_id = $('#post_ID').val(), - send = {}; - - if ( ! post_id || ! $('#post-lock-dialog').length ) - return; - - send.post_id = post_id; - - if ( lock ) - send.lock = lock; - - data['wp-refresh-post-lock'] = send; - - }).on( 'heartbeat-tick.refresh-lock', function( e, data ) { - // Post locks: update the lock string or show the dialog if somebody has taken over editing. - var received, wrap, avatar; - - if ( data['wp-refresh-post-lock'] ) { - received = data['wp-refresh-post-lock']; - - if ( received.lock_error ) { - // Show "editing taken over" message. - wrap = $('#post-lock-dialog'); - - if ( wrap.length && ! wrap.is(':visible') ) { - if ( wp.autosave ) { - // Save the latest changes and disable. - $(document).one( 'heartbeat-tick', function() { - wp.autosave.server.suspend(); - wrap.removeClass('saving').addClass('saved'); - $(window).off( 'beforeunload.edit-post' ); - }); - - wrap.addClass('saving'); - wp.autosave.server.triggerSave(); - } - - if ( received.lock_error.avatar_src ) { - avatar = $( '<img class="avatar avatar-64 photo" width="64" height="64" alt="" />' ).attr( 'src', received.lock_error.avatar_src.replace( /&/g, '&' ) ); - wrap.find('div.post-locked-avatar').empty().append( avatar ); - } - - wrap.show().find('.currently-editing').text( received.lock_error.text ); - wrap.find('.wp-tab-first').focus(); - } - } else if ( received.new_lock ) { - $('#active_post_lock').val( received.new_lock ); - } - } - }).on( 'before-autosave.update-post-slug', function() { - titleHasFocus = document.activeElement && document.activeElement.id === 'title'; - }).on( 'after-autosave.update-post-slug', function() { - - /* - * Create slug area only if not already there - * and the title field was not focused (user was not typing a title) when autosave ran. - */ - if ( ! $('#edit-slug-box > *').length && ! titleHasFocus ) { - $.post( ajaxurl, { - action: 'sample-permalink', - post_id: $('#post_ID').val(), - new_title: $('#title').val(), - samplepermalinknonce: $('#samplepermalinknonce').val() - }, - function( data ) { - if ( data != '-1' ) { - $('#edit-slug-box').html(data); - } - } - ); - } - }); - -}(jQuery)); - -/** - * Heartbeat refresh nonces. - */ -(function($) { - var check, timeout; - - /** - * Only allow to check for nonce refresh every 30 seconds. - */ - function schedule() { - check = false; - window.clearTimeout( timeout ); - timeout = window.setTimeout( function(){ check = true; }, 300000 ); - } - - $(document).on( 'heartbeat-send.wp-refresh-nonces', function( e, data ) { - var post_id, - $authCheck = $('#wp-auth-check-wrap'); - - if ( check || ( $authCheck.length && ! $authCheck.hasClass( 'hidden' ) ) ) { - if ( ( post_id = $('#post_ID').val() ) && $('#_wpnonce').val() ) { - data['wp-refresh-post-nonces'] = { - post_id: post_id - }; - } - } - }).on( 'heartbeat-tick.wp-refresh-nonces', function( e, data ) { - var nonces = data['wp-refresh-post-nonces']; - - if ( nonces ) { - schedule(); - - if ( nonces.replace ) { - $.each( nonces.replace, function( selector, value ) { - $( '#' + selector ).val( value ); - }); - } - - if ( nonces.heartbeatNonce ) - window.heartbeatSettings.nonce = nonces.heartbeatNonce; - } - }).ready( function() { - schedule(); - }); -}(jQuery)); - -/** - * All post and postbox controls and functionality. - */ -jQuery(document).ready( function($) { - var stamp, visibility, $submitButtons, updateVisibility, updateText, - sticky = '', - $textarea = $('#content'), - $document = $(document), - postId = $('#post_ID').val() || 0, - $submitpost = $('#submitpost'), - releaseLock = true, - $postVisibilitySelect = $('#post-visibility-select'), - $timestampdiv = $('#timestampdiv'), - $postStatusSelect = $('#post-status-select'), - isMac = window.navigator.platform ? window.navigator.platform.indexOf( 'Mac' ) !== -1 : false; - - postboxes.add_postbox_toggles(pagenow); - - /* - * Clear the window name. Otherwise if this is a former preview window where the user navigated to edit another post, - * and the first post is still being edited, clicking Preview there will use this window to show the preview. - */ - window.name = ''; - - // Post locks: contain focus inside the dialog. If the dialog is shown, focus the first item. - $('#post-lock-dialog .notification-dialog').on( 'keydown', function(e) { - // Don't do anything when [tab] is pressed. - if ( e.which != 9 ) - return; - - var target = $(e.target); - - // [shift] + [tab] on first tab cycles back to last tab. - if ( target.hasClass('wp-tab-first') && e.shiftKey ) { - $(this).find('.wp-tab-last').focus(); - e.preventDefault(); - // [tab] on last tab cycles back to first tab. - } else if ( target.hasClass('wp-tab-last') && ! e.shiftKey ) { - $(this).find('.wp-tab-first').focus(); - e.preventDefault(); - } - }).filter(':visible').find('.wp-tab-first').focus(); - - // Set the heartbeat interval to 15 sec. if post lock dialogs are enabled. - if ( wp.heartbeat && $('#post-lock-dialog').length ) { - wp.heartbeat.interval( 15 ); - } - - // The form is being submitted by the user. - $submitButtons = $submitpost.find( ':submit, a.submitdelete, #post-preview' ).on( 'click.edit-post', function( event ) { - var $button = $(this); - - if ( $button.hasClass('disabled') ) { - event.preventDefault(); - return; - } - - if ( $button.hasClass('submitdelete') || $button.is( '#post-preview' ) ) { - return; - } - - // The form submission can be blocked from JS or by using HTML 5.0 validation on some fields. - // Run this only on an actual 'submit'. - $('form#post').off( 'submit.edit-post' ).on( 'submit.edit-post', function( event ) { - if ( event.isDefaultPrevented() ) { - return; - } - - // Stop auto save. - if ( wp.autosave ) { - wp.autosave.server.suspend(); - } - - if ( typeof commentReply !== 'undefined' ) { - /* - * Warn the user they have an unsaved comment before submitting - * the post data for update. - */ - if ( ! commentReply.discardCommentChanges() ) { - return false; - } - - /* - * Close the comment edit/reply form if open to stop the form - * action from interfering with the post's form action. - */ - commentReply.close(); - } - - releaseLock = false; - $(window).off( 'beforeunload.edit-post' ); - - $submitButtons.addClass( 'disabled' ); - - if ( $button.attr('id') === 'publish' ) { - $submitpost.find( '#major-publishing-actions .spinner' ).addClass( 'is-active' ); - } else { - $submitpost.find( '#minor-publishing .spinner' ).addClass( 'is-active' ); - } - }); - }); - - // Submit the form saving a draft or an autosave, and show a preview in a new tab - $('#post-preview').on( 'click.post-preview', function( event ) { - var $this = $(this), - $form = $('form#post'), - $previewField = $('input#wp-preview'), - target = $this.attr('target') || 'wp-preview', - ua = navigator.userAgent.toLowerCase(); - - event.preventDefault(); - - if ( $this.hasClass('disabled') ) { - return; - } - - if ( wp.autosave ) { - wp.autosave.server.tempBlockSave(); - } - - $previewField.val('dopreview'); - $form.attr( 'target', target ).submit().attr( 'target', '' ); - - // Workaround for WebKit bug preventing a form submitting twice to the same action. - // https://bugs.webkit.org/show_bug.cgi?id=28633 - if ( ua.indexOf('safari') !== -1 && ua.indexOf('chrome') === -1 ) { - $form.attr( 'action', function( index, value ) { - return value + '?t=' + ( new Date() ).getTime(); - }); - } - - $previewField.val(''); - }); - - // This code is meant to allow tabbing from Title to Post content. - $('#title').on( 'keydown.editor-focus', function( event ) { - var editor; - - if ( event.keyCode === 9 && ! event.ctrlKey && ! event.altKey && ! event.shiftKey ) { - editor = typeof tinymce != 'undefined' && tinymce.get('content'); - - if ( editor && ! editor.isHidden() ) { - editor.focus(); - } else if ( $textarea.length ) { - $textarea.focus(); - } else { - return; - } - - event.preventDefault(); - } - }); - - // Auto save new posts after a title is typed. - if ( $( '#auto_draft' ).val() ) { - $( '#title' ).blur( function() { - var cancel; - - if ( ! this.value || $('#edit-slug-box > *').length ) { - return; - } - - // Cancel the auto save when the blur was triggered by the user submitting the form. - $('form#post').one( 'submit', function() { - cancel = true; - }); - - window.setTimeout( function() { - if ( ! cancel && wp.autosave ) { - wp.autosave.server.triggerSave(); - } - }, 200 ); - }); - } - - $document.on( 'autosave-disable-buttons.edit-post', function() { - $submitButtons.addClass( 'disabled' ); - }).on( 'autosave-enable-buttons.edit-post', function() { - if ( ! wp.heartbeat || ! wp.heartbeat.hasConnectionError() ) { - $submitButtons.removeClass( 'disabled' ); - } - }).on( 'before-autosave.edit-post', function() { - $( '.autosave-message' ).text( postL10n.savingText ); - }).on( 'after-autosave.edit-post', function( event, data ) { - $( '.autosave-message' ).text( data.message ); - - if ( $( document.body ).hasClass( 'post-new-php' ) ) { - $( '.submitbox .submitdelete' ).show(); - } - }); - - /* - * When the user is trying to load another page, or reloads current page - * show a confirmation dialog when there are unsaved changes. - */ - $(window).on( 'beforeunload.edit-post', function() { - var editor = typeof tinymce !== 'undefined' && tinymce.get('content'); - - if ( ( editor && ! editor.isHidden() && editor.isDirty() ) || - ( wp.autosave && wp.autosave.server.postChanged() ) ) { - - return postL10n.saveAlert; - } - }).on( 'unload.edit-post', function( event ) { - if ( ! releaseLock ) { - return; - } - - /* - * Unload is triggered (by hand) on removing the Thickbox iframe. - * Make sure we process only the main document unload. - */ - if ( event.target && event.target.nodeName != '#document' ) { - return; - } - - var postID = $('#post_ID').val(); - var postLock = $('#active_post_lock').val(); - - if ( ! postID || ! postLock ) { - return; - } - - var data = { - action: 'wp-remove-post-lock', - _wpnonce: $('#_wpnonce').val(), - post_ID: postID, - active_post_lock: postLock - }; - - if ( window.FormData && window.navigator.sendBeacon ) { - var formData = new window.FormData(); - - $.each( data, function( key, value ) { - formData.append( key, value ); - }); - - if ( window.navigator.sendBeacon( ajaxurl, formData ) ) { - return; - } - } - - // Fall back to a synchronous POST request. - // See https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon - $.post({ - async: false, - data: data, - url: ajaxurl - }); - }); - - // Multiple Taxonomies. - if ( $('#tagsdiv-post_tag').length ) { - window.tagBox && window.tagBox.init(); - } else { - $('.meta-box-sortables').children('div.postbox').each(function(){ - if ( this.id.indexOf('tagsdiv-') === 0 ) { - window.tagBox && window.tagBox.init(); - return false; - } - }); - } - - // Handle categories. - $('.categorydiv').each( function(){ - var this_id = $(this).attr('id'), catAddBefore, catAddAfter, taxonomyParts, taxonomy, settingName; - - taxonomyParts = this_id.split('-'); - taxonomyParts.shift(); - taxonomy = taxonomyParts.join('-'); - settingName = taxonomy + '_tab'; - - if ( taxonomy == 'category' ) { - settingName = 'cats'; - } - - // TODO: move to jQuery 1.3+, support for multiple hierarchical taxonomies, see wp-lists.js - $('a', '#' + taxonomy + '-tabs').click( function( e ) { - e.preventDefault(); - var t = $(this).attr('href'); - $(this).parent().addClass('tabs').siblings('li').removeClass('tabs'); - $('#' + taxonomy + '-tabs').siblings('.tabs-panel').hide(); - $(t).show(); - if ( '#' + taxonomy + '-all' == t ) { - deleteUserSetting( settingName ); - } else { - setUserSetting( settingName, 'pop' ); - } - }); - - if ( getUserSetting( settingName ) ) - $('a[href="#' + taxonomy + '-pop"]', '#' + taxonomy + '-tabs').click(); - - // Add category button controls. - $('#new' + taxonomy).one( 'focus', function() { - $( this ).val( '' ).removeClass( 'form-input-tip' ); - }); - - // On [enter] submit the taxonomy. - $('#new' + taxonomy).keypress( function(event){ - if( 13 === event.keyCode ) { - event.preventDefault(); - $('#' + taxonomy + '-add-submit').click(); - } - }); - - // After submitting a new taxonomy, re-focus the input field. - $('#' + taxonomy + '-add-submit').click( function() { - $('#new' + taxonomy).focus(); - }); - - /** - * Before adding a new taxonomy, disable submit button. - * - * @param {Object} s Taxonomy object which will be added. - * - * @returns {Object} - */ - catAddBefore = function( s ) { - if ( !$('#new'+taxonomy).val() ) { - return false; - } - - s.data += '&' + $( ':checked', '#'+taxonomy+'checklist' ).serialize(); - $( '#' + taxonomy + '-add-submit' ).prop( 'disabled', true ); - return s; - }; - - /** - * Re-enable submit button after a taxonomy has been added. - * - * Re-enable submit button. - * If the taxonomy has a parent place the taxonomy underneath the parent. - * - * @param {Object} r Response. - * @param {Object} s Taxonomy data. - * - * @returns void - */ - catAddAfter = function( r, s ) { - var sup, drop = $('#new'+taxonomy+'_parent'); - - $( '#' + taxonomy + '-add-submit' ).prop( 'disabled', false ); - if ( 'undefined' != s.parsed.responses[0] && (sup = s.parsed.responses[0].supplemental.newcat_parent) ) { - drop.before(sup); - drop.remove(); - } - }; - - $('#' + taxonomy + 'checklist').wpList({ - alt: '', - response: taxonomy + '-ajax-response', - addBefore: catAddBefore, - addAfter: catAddAfter - }); - - // Add new taxonomy button toggles input form visibility. - $('#' + taxonomy + '-add-toggle').click( function( e ) { - e.preventDefault(); - $('#' + taxonomy + '-adder').toggleClass( 'wp-hidden-children' ); - $('a[href="#' + taxonomy + '-all"]', '#' + taxonomy + '-tabs').click(); - $('#new'+taxonomy).focus(); - }); - - // Sync checked items between "All {taxonomy}" and "Most used" lists. - $('#' + taxonomy + 'checklist, #' + taxonomy + 'checklist-pop').on( 'click', 'li.popular-category > label input[type="checkbox"]', function() { - var t = $(this), c = t.is(':checked'), id = t.val(); - if ( id && t.parents('#taxonomy-'+taxonomy).length ) - $('#in-' + taxonomy + '-' + id + ', #in-popular-' + taxonomy + '-' + id).prop( 'checked', c ); - }); - - }); // end cats - - // Custom Fields postbox. - if ( $('#postcustom').length ) { - $( '#the-list' ).wpList( { - /** - * Add current post_ID to request to fetch custom fields - * - * @ignore - * - * @param {Object} s Request object. - * - * @returns {Object} Data modified with post_ID attached. - */ - addBefore: function( s ) { - s.data += '&post_id=' + $('#post_ID').val(); - return s; - }, - /** - * Show the listing of custom fields after fetching. - * - * @ignore - */ - addAfter: function() { - $('table#list-table').show(); - } - }); - } - - /* - * Publish Post box (#submitdiv) - */ - if ( $('#submitdiv').length ) { - stamp = $('#timestamp').html(); - visibility = $('#post-visibility-display').html(); - - /** - * When the visibility of a post changes sub-options should be shown or hidden. - * - * @ignore - * - * @returns void - */ - updateVisibility = function() { - // Show sticky for public posts. - if ( $postVisibilitySelect.find('input:radio:checked').val() != 'public' ) { - $('#sticky').prop('checked', false); - $('#sticky-span').hide(); - } else { - $('#sticky-span').show(); - } - - // Show password input field for password protected post. - if ( $postVisibilitySelect.find('input:radio:checked').val() != 'password' ) { - $('#password-span').hide(); - } else { - $('#password-span').show(); - } - }; - - /** - * Make sure all labels represent the current settings. - * - * @ignore - * - * @returns {boolean} False when an invalid timestamp has been selected, otherwise True. - */ - updateText = function() { - - if ( ! $timestampdiv.length ) - return true; - - var attemptedDate, originalDate, currentDate, publishOn, postStatus = $('#post_status'), - optPublish = $('option[value="publish"]', postStatus), aa = $('#aa').val(), - mm = $('#mm').val(), jj = $('#jj').val(), hh = $('#hh').val(), mn = $('#mn').val(); - - attemptedDate = new Date( aa, mm - 1, jj, hh, mn ); - originalDate = new Date( $('#hidden_aa').val(), $('#hidden_mm').val() -1, $('#hidden_jj').val(), $('#hidden_hh').val(), $('#hidden_mn').val() ); - currentDate = new Date( $('#cur_aa').val(), $('#cur_mm').val() -1, $('#cur_jj').val(), $('#cur_hh').val(), $('#cur_mn').val() ); - - // Catch unexpected date problems. - if ( attemptedDate.getFullYear() != aa || (1 + attemptedDate.getMonth()) != mm || attemptedDate.getDate() != jj || attemptedDate.getMinutes() != mn ) { - $timestampdiv.find('.timestamp-wrap').addClass('form-invalid'); - return false; - } else { - $timestampdiv.find('.timestamp-wrap').removeClass('form-invalid'); - } - - // Determine what the publish should be depending on the date and post status. - if ( attemptedDate > currentDate && $('#original_post_status').val() != 'future' ) { - publishOn = postL10n.publishOnFuture; - $('#publish').val( postL10n.schedule ); - } else if ( attemptedDate <= currentDate && $('#original_post_status').val() != 'publish' ) { - publishOn = postL10n.publishOn; - $('#publish').val( postL10n.publish ); - } else { - publishOn = postL10n.publishOnPast; - $('#publish').val( postL10n.update ); - } - - // If the date is the same, set it to trigger update events. - if ( originalDate.toUTCString() == attemptedDate.toUTCString() ) { - // Re-set to the current value. - $('#timestamp').html(stamp); - } else { - $('#timestamp').html( - '\n' + publishOn + ' <b>' + - postL10n.dateFormat - .replace( '%1$s', $( 'option[value="' + mm + '"]', '#mm' ).attr( 'data-text' ) ) - .replace( '%2$s', parseInt( jj, 10 ) ) - .replace( '%3$s', aa ) - .replace( '%4$s', ( '00' + hh ).slice( -2 ) ) - .replace( '%5$s', ( '00' + mn ).slice( -2 ) ) + - '</b> ' - ); - } - - // Add "privately published" to post status when applies. - if ( $postVisibilitySelect.find('input:radio:checked').val() == 'private' ) { - $('#publish').val( postL10n.update ); - if ( 0 === optPublish.length ) { - postStatus.append('<option value="publish">' + postL10n.privatelyPublished + '</option>'); - } else { - optPublish.html( postL10n.privatelyPublished ); - } - $('option[value="publish"]', postStatus).prop('selected', true); - $('#misc-publishing-actions .edit-post-status').hide(); - } else { - if ( $('#original_post_status').val() == 'future' || $('#original_post_status').val() == 'draft' ) { - if ( optPublish.length ) { - optPublish.remove(); - postStatus.val($('#hidden_post_status').val()); - } - } else { - optPublish.html( postL10n.published ); - } - if ( postStatus.is(':hidden') ) - $('#misc-publishing-actions .edit-post-status').show(); - } - - // Update "Status:" to currently selected status. - $('#post-status-display').text( - wp.sanitize.stripTagsAndEncodeText( $('option:selected', postStatus).text() ) // Remove any potential tags from post status text. - ); - - // Show or hide the "Save Draft" button. - if ( $('option:selected', postStatus).val() == 'private' || $('option:selected', postStatus).val() == 'publish' ) { - $('#save-post').hide(); - } else { - $('#save-post').show(); - if ( $('option:selected', postStatus).val() == 'pending' ) { - $('#save-post').show().val( postL10n.savePending ); - } else { - $('#save-post').show().val( postL10n.saveDraft ); - } - } - return true; - }; - - // Show the visibility options and hide the toggle button when opened. - $( '#visibility .edit-visibility').click( function( e ) { - e.preventDefault(); - if ( $postVisibilitySelect.is(':hidden') ) { - updateVisibility(); - $postVisibilitySelect.slideDown( 'fast', function() { - $postVisibilitySelect.find( 'input[type="radio"]' ).first().focus(); - } ); - $(this).hide(); - } - }); - - // Cancel visibility selection area and hide it from view. - $postVisibilitySelect.find('.cancel-post-visibility').click( function( event ) { - $postVisibilitySelect.slideUp('fast'); - $('#visibility-radio-' + $('#hidden-post-visibility').val()).prop('checked', true); - $('#post_password').val($('#hidden-post-password').val()); - $('#sticky').prop('checked', $('#hidden-post-sticky').prop('checked')); - $('#post-visibility-display').html(visibility); - $('#visibility .edit-visibility').show().focus(); - updateText(); - event.preventDefault(); - }); - - // Set the selected visibility as current. - $postVisibilitySelect.find('.save-post-visibility').click( function( event ) { // crazyhorse - multiple ok cancels - $postVisibilitySelect.slideUp('fast'); - $('#visibility .edit-visibility').show().focus(); - updateText(); - - if ( $postVisibilitySelect.find('input:radio:checked').val() != 'public' ) { - $('#sticky').prop('checked', false); - } - - if ( $('#sticky').prop('checked') ) { - sticky = 'Sticky'; - } else { - sticky = ''; - } - - $('#post-visibility-display').html( postL10n[ $postVisibilitySelect.find('input:radio:checked').val() + sticky ] ); - event.preventDefault(); - }); - - // When the selection changes, update labels. - $postVisibilitySelect.find('input:radio').change( function() { - updateVisibility(); - }); - - // Edit publish time click. - $timestampdiv.siblings('a.edit-timestamp').click( function( event ) { - if ( $timestampdiv.is( ':hidden' ) ) { - $timestampdiv.slideDown( 'fast', function() { - $( 'input, select', $timestampdiv.find( '.timestamp-wrap' ) ).first().focus(); - } ); - $(this).hide(); - } - event.preventDefault(); - }); - - // Cancel editing the publish time and hide the settings. - $timestampdiv.find('.cancel-timestamp').click( function( event ) { - $timestampdiv.slideUp('fast').siblings('a.edit-timestamp').show().focus(); - $('#mm').val($('#hidden_mm').val()); - $('#jj').val($('#hidden_jj').val()); - $('#aa').val($('#hidden_aa').val()); - $('#hh').val($('#hidden_hh').val()); - $('#mn').val($('#hidden_mn').val()); - updateText(); - event.preventDefault(); - }); - - // Save the changed timestamp. - $timestampdiv.find('.save-timestamp').click( function( event ) { // crazyhorse - multiple ok cancels - if ( updateText() ) { - $timestampdiv.slideUp('fast'); - $timestampdiv.siblings('a.edit-timestamp').show().focus(); - } - event.preventDefault(); - }); - - // Cancel submit when an invalid timestamp has been selected. - $('#post').on( 'submit', function( event ) { - if ( ! updateText() ) { - event.preventDefault(); - $timestampdiv.show(); - - if ( wp.autosave ) { - wp.autosave.enableButtons(); - } - - $( '#publishing-action .spinner' ).removeClass( 'is-active' ); - } - }); - - // Post Status edit click. - $postStatusSelect.siblings('a.edit-post-status').click( function( event ) { - if ( $postStatusSelect.is( ':hidden' ) ) { - $postStatusSelect.slideDown( 'fast', function() { - $postStatusSelect.find('select').focus(); - } ); - $(this).hide(); - } - event.preventDefault(); - }); - - // Save the Post Status changes and hide the options. - $postStatusSelect.find('.save-post-status').click( function( event ) { - $postStatusSelect.slideUp( 'fast' ).siblings( 'a.edit-post-status' ).show().focus(); - updateText(); - event.preventDefault(); - }); - - // Cancel Post Status editing and hide the options. - $postStatusSelect.find('.cancel-post-status').click( function( event ) { - $postStatusSelect.slideUp( 'fast' ).siblings( 'a.edit-post-status' ).show().focus(); - $('#post_status').val( $('#hidden_post_status').val() ); - updateText(); - event.preventDefault(); - }); - } - - /** - * Handle the editing of the post_name. Create the required HTML elements and - * update the changes via AJAX. - * - * @global - * - * @returns void - */ - function editPermalink() { - var i, slug_value, - $el, revert_e, - c = 0, - real_slug = $('#post_name'), - revert_slug = real_slug.val(), - permalink = $( '#sample-permalink' ), - permalinkOrig = permalink.html(), - permalinkInner = $( '#sample-permalink a' ).html(), - buttons = $('#edit-slug-buttons'), - buttonsOrig = buttons.html(), - full = $('#editable-post-name-full'); - - // Deal with Twemoji in the post-name. - full.find( 'img' ).replaceWith( function() { return this.alt; } ); - full = full.html(); - - permalink.html( permalinkInner ); - - // Save current content to revert to when cancelling. - $el = $( '#editable-post-name' ); - revert_e = $el.html(); - - buttons.html( '<button type="button" class="save button button-small">' + postL10n.ok + '</button> <button type="button" class="cancel button-link">' + postL10n.cancel + '</button>' ); - - // Save permalink changes. - buttons.children( '.save' ).click( function() { - var new_slug = $el.children( 'input' ).val(); - - if ( new_slug == $('#editable-post-name-full').text() ) { - buttons.children('.cancel').click(); - return; - } - - $.post( - ajaxurl, - { - action: 'sample-permalink', - post_id: postId, - new_slug: new_slug, - new_title: $('#title').val(), - samplepermalinknonce: $('#samplepermalinknonce').val() - }, - function(data) { - var box = $('#edit-slug-box'); - box.html(data); - if (box.hasClass('hidden')) { - box.fadeIn('fast', function () { - box.removeClass('hidden'); - }); - } - - buttons.html(buttonsOrig); - permalink.html(permalinkOrig); - real_slug.val(new_slug); - $( '.edit-slug' ).focus(); - wp.a11y.speak( postL10n.permalinkSaved ); - } - ); - }); - - // Cancel editing of permalink. - buttons.children( '.cancel' ).click( function() { - $('#view-post-btn').show(); - $el.html(revert_e); - buttons.html(buttonsOrig); - permalink.html(permalinkOrig); - real_slug.val(revert_slug); - $( '.edit-slug' ).focus(); - }); - - // If more than 1/4th of 'full' is '%', make it empty. - for ( i = 0; i < full.length; ++i ) { - if ( '%' == full.charAt(i) ) - c++; - } - slug_value = ( c > full.length / 4 ) ? '' : full; - - $el.html( '<input type="text" id="new-post-slug" value="' + slug_value + '" autocomplete="off" />' ).children( 'input' ).keydown( function( e ) { - var key = e.which; - // On [enter], just save the new slug, don't save the post. - if ( 13 === key ) { - e.preventDefault(); - buttons.children( '.save' ).click(); - } - // On [esc] cancel the editing. - if ( 27 === key ) { - buttons.children( '.cancel' ).click(); - } - } ).keyup( function() { - real_slug.val( this.value ); - }).focus(); - } - - $( '#titlediv' ).on( 'click', '.edit-slug', function() { - editPermalink(); - }); - - /** - * Adds screen reader text to the title label when needed. - * - * Use the 'screen-reader-text' class to emulate a placeholder attribute - * and hide the label when entering a value. - * - * @param {string} id Optional. HTML ID to add the screen reader helper text to. - * - * @global - * - * @returns void - */ - window.wptitlehint = function( id ) { - id = id || 'title'; - - var title = $( '#' + id ), titleprompt = $( '#' + id + '-prompt-text' ); - - if ( '' === title.val() ) { - titleprompt.removeClass( 'screen-reader-text' ); - } - - title.on( 'input', function() { - if ( '' === this.value ) { - titleprompt.removeClass( 'screen-reader-text' ); - return; - } - - titleprompt.addClass( 'screen-reader-text' ); - } ); - }; - - wptitlehint(); - - // Resize the WYSIWYG and plain text editors. - ( function() { - var editor, offset, mce, - $handle = $('#post-status-info'), - $postdivrich = $('#postdivrich'); - - // If there are no textareas or we are on a touch device, we can't do anything. - if ( ! $textarea.length || 'ontouchstart' in window ) { - // Hide the resize handle. - $('#content-resize-handle').hide(); - return; - } - - /** - * Handle drag event. - * - * @param {Object} event Event containing details about the drag. - */ - function dragging( event ) { - if ( $postdivrich.hasClass( 'wp-editor-expand' ) ) { - return; - } - - if ( mce ) { - editor.theme.resizeTo( null, offset + event.pageY ); - } else { - $textarea.height( Math.max( 50, offset + event.pageY ) ); - } - - event.preventDefault(); - } - - /** - * When the dragging stopped make sure we return focus and do a sanity check on the height. - */ - function endDrag() { - var height, toolbarHeight; - - if ( $postdivrich.hasClass( 'wp-editor-expand' ) ) { - return; - } - - if ( mce ) { - editor.focus(); - toolbarHeight = parseInt( $( '#wp-content-editor-container .mce-toolbar-grp' ).height(), 10 ); - - if ( toolbarHeight < 10 || toolbarHeight > 200 ) { - toolbarHeight = 30; - } - - height = parseInt( $('#content_ifr').css('height'), 10 ) + toolbarHeight - 28; - } else { - $textarea.focus(); - height = parseInt( $textarea.css('height'), 10 ); - } - - $document.off( '.wp-editor-resize' ); - - // Sanity check: normalize height to stay within acceptable ranges. - if ( height && height > 50 && height < 5000 ) { - setUserSetting( 'ed_size', height ); - } - } - - $handle.on( 'mousedown.wp-editor-resize', function( event ) { - if ( typeof tinymce !== 'undefined' ) { - editor = tinymce.get('content'); - } - - if ( editor && ! editor.isHidden() ) { - mce = true; - offset = $('#content_ifr').height() - event.pageY; - } else { - mce = false; - offset = $textarea.height() - event.pageY; - $textarea.blur(); - } - - $document.on( 'mousemove.wp-editor-resize', dragging ) - .on( 'mouseup.wp-editor-resize mouseleave.wp-editor-resize', endDrag ); - - event.preventDefault(); - }).on( 'mouseup.wp-editor-resize', endDrag ); - })(); - - // TinyMCE specific handling of Post Format changes to reflect in the editor. - if ( typeof tinymce !== 'undefined' ) { - // When changing post formats, change the editor body class. - $( '#post-formats-select input.post-format' ).on( 'change.set-editor-class', function() { - var editor, body, format = this.id; - - if ( format && $( this ).prop( 'checked' ) && ( editor = tinymce.get( 'content' ) ) ) { - body = editor.getBody(); - body.className = body.className.replace( /\bpost-format-[^ ]+/, '' ); - editor.dom.addClass( body, format == 'post-format-0' ? 'post-format-standard' : format ); - $( document ).trigger( 'editor-classchange' ); - } - }); - - // When changing page template, change the editor body class - $( '#page_template' ).on( 'change.set-editor-class', function() { - var editor, body, pageTemplate = $( this ).val() || ''; - - pageTemplate = pageTemplate.substr( pageTemplate.lastIndexOf( '/' ) + 1, pageTemplate.length ) - .replace( /\.php$/, '' ) - .replace( /\./g, '-' ); - - if ( pageTemplate && ( editor = tinymce.get( 'content' ) ) ) { - body = editor.getBody(); - body.className = body.className.replace( /\bpage-template-[^ ]+/, '' ); - editor.dom.addClass( body, 'page-template-' + pageTemplate ); - $( document ).trigger( 'editor-classchange' ); - } - }); - - } - - // Save on pressing [ctrl]/[command] + [s] in the Text editor. - $textarea.on( 'keydown.wp-autosave', function( event ) { - // Key [s] has code 83. - if ( event.which === 83 ) { - if ( event.shiftKey || event.altKey || ( isMac && ( ! event.metaKey || event.ctrlKey ) ) || ( ! isMac && ! event.ctrlKey ) ) { - return; - } - - wp.autosave && wp.autosave.server.triggerSave(); - event.preventDefault(); - } - }); - - // If the last status was auto-draft and the save is triggered, edit the current URL. - if ( $( '#original_post_status' ).val() === 'auto-draft' && window.history.replaceState ) { - var location; - - $( '#publish' ).on( 'click', function() { - location = window.location.href; - location += ( location.indexOf( '?' ) !== -1 ) ? '&' : '?'; - location += 'wp-post-new-reload=true'; - - window.history.replaceState( null, null, location ); - }); - } -}); - -/** - * TinyMCE word count display - */ -( function( $, counter ) { - $( function() { - var $content = $( '#content' ), - $count = $( '#wp-word-count' ).find( '.word-count' ), - prevCount = 0, - contentEditor; - - /** - * Get the word count from TinyMCE and display it - */ - function update() { - var text, count; - - if ( ! contentEditor || contentEditor.isHidden() ) { - text = $content.val(); - } else { - text = contentEditor.getContent( { format: 'raw' } ); - } - - count = counter.count( text ); - - if ( count !== prevCount ) { - $count.text( count ); - } - - prevCount = count; - } - - /** - * Bind the word count update triggers. - * - * When a node change in the main TinyMCE editor has been triggered. - * When a key has been released in the plain text content editor. - */ - $( document ).on( 'tinymce-editor-init', function( event, editor ) { - if ( editor.id !== 'content' ) { - return; - } - - contentEditor = editor; - - editor.on( 'nodechange keyup', _.debounce( update, 1000 ) ); - } ); - - $content.on( 'input keyup', _.debounce( update, 1000 ) ); - - update(); - } ); - -} )( jQuery, new wp.utils.WordCounter() ); diff --git a/srcs/wordpress/wp-admin/js/post.min.js b/srcs/wordpress/wp-admin/js/post.min.js deleted file mode 100644 index 13fb87a..0000000 --- a/srcs/wordpress/wp-admin/js/post.min.js +++ /dev/null @@ -1 +0,0 @@ -window.makeSlugeditClickable=window.editPermalink=function(){},window.wp=window.wp||{},function(a){var t=!1;window.commentsBox={st:0,get:function(t,e){var i,n=this.st;return e=e||20,this.st+=e,this.total=t,a("#commentsdiv .spinner").addClass("is-active"),i={action:"get-comments",mode:"single",_ajax_nonce:a("#add_comment_nonce").val(),p:a("#post_ID").val(),start:n,number:e},a.post(ajaxurl,i,function(t){if(t=wpAjax.parseAjaxResponse(t),a("#commentsdiv .widefat").show(),a("#commentsdiv .spinner").removeClass("is-active"),"object"==typeof t&&t.responses[0])return a("#the-comment-list").append(t.responses[0].data),theList=theExtraList=null,a("a[className*=':']").unbind(),void(commentsBox.st>commentsBox.total?a("#show-comments").hide():a("#show-comments").show().children("a").html(postL10n.showcomm));1!=t?a("#the-comment-list").append('<tr><td colspan="2">'+wpAjax.broken+"</td></tr>"):a("#show-comments").html(postL10n.endcomm)}),!1},load:function(t){this.st=jQuery("#the-comment-list tr.comment:visible").length,this.get(t)}},window.WPSetThumbnailHTML=function(t){a(".inside","#postimagediv").html(t)},window.WPSetThumbnailID=function(t){var e=a('input[value="_thumbnail_id"]',"#list-table");0<e.length&&a("#meta\\["+e.attr("id").match(/[0-9]+/)+"\\]\\[value\\]").text(t)},window.WPRemoveThumbnail=function(t){a.post(ajaxurl,{action:"set-post-thumbnail",post_id:a("#post_ID").val(),thumbnail_id:-1,_ajax_nonce:t,cookie:encodeURIComponent(document.cookie)},function(t){"0"==t?alert(setPostThumbnailL10n.error):WPSetThumbnailHTML(t)})},a(document).on("heartbeat-send.refresh-lock",function(t,e){var i=a("#active_post_lock").val(),n=a("#post_ID").val(),s={};n&&a("#post-lock-dialog").length&&(s.post_id=n,i&&(s.lock=i),e["wp-refresh-post-lock"]=s)}).on("heartbeat-tick.refresh-lock",function(t,e){var i,n,s;e["wp-refresh-post-lock"]&&((i=e["wp-refresh-post-lock"]).lock_error?(n=a("#post-lock-dialog")).length&&!n.is(":visible")&&(wp.autosave&&(a(document).one("heartbeat-tick",function(){wp.autosave.server.suspend(),n.removeClass("saving").addClass("saved"),a(window).off("beforeunload.edit-post")}),n.addClass("saving"),wp.autosave.server.triggerSave()),i.lock_error.avatar_src&&(s=a('<img class="avatar avatar-64 photo" width="64" height="64" alt="" />').attr("src",i.lock_error.avatar_src.replace(/&/g,"&")),n.find("div.post-locked-avatar").empty().append(s)),n.show().find(".currently-editing").text(i.lock_error.text),n.find(".wp-tab-first").focus()):i.new_lock&&a("#active_post_lock").val(i.new_lock))}).on("before-autosave.update-post-slug",function(){t=document.activeElement&&"title"===document.activeElement.id}).on("after-autosave.update-post-slug",function(){a("#edit-slug-box > *").length||t||a.post(ajaxurl,{action:"sample-permalink",post_id:a("#post_ID").val(),new_title:a("#title").val(),samplepermalinknonce:a("#samplepermalinknonce").val()},function(t){"-1"!=t&&a("#edit-slug-box").html(t)})})}(jQuery),function(s){var a,t;function n(){a=!1,window.clearTimeout(t),t=window.setTimeout(function(){a=!0},3e5)}s(document).on("heartbeat-send.wp-refresh-nonces",function(t,e){var i,n=s("#wp-auth-check-wrap");(a||n.length&&!n.hasClass("hidden"))&&(i=s("#post_ID").val())&&s("#_wpnonce").val()&&(e["wp-refresh-post-nonces"]={post_id:i})}).on("heartbeat-tick.wp-refresh-nonces",function(t,e){var i=e["wp-refresh-post-nonces"];i&&(n(),i.replace&&s.each(i.replace,function(t,e){s("#"+t).val(e)}),i.heartbeatNonce&&(window.heartbeatSettings.nonce=i.heartbeatNonce))}).ready(function(){n()})}(jQuery),jQuery(document).ready(function(h){var d,e,i,n,s,a,o,l,t,p,c,r="",u=h("#content"),f=h(document),v=h("#post_ID").val()||0,m=h("#submitpost"),w=!0,b=h("#post-visibility-select"),g=h("#timestampdiv"),k=h("#post-status-select"),y=!!window.navigator.platform&&-1!==window.navigator.platform.indexOf("Mac");function _(t){p.hasClass("wp-editor-expand")||(l?a.theme.resizeTo(null,o+t.pageY):u.height(Math.max(50,o+t.pageY)),t.preventDefault())}function x(){var t,e;p.hasClass("wp-editor-expand")||(t=l?(a.focus(),((e=parseInt(h("#wp-content-editor-container .mce-toolbar-grp").height(),10))<10||200<e)&&(e=30),parseInt(h("#content_ifr").css("height"),10)+e-28):(u.focus(),parseInt(u.css("height"),10)),f.off(".wp-editor-resize"),t&&50<t&&t<5e3&&setUserSetting("ed_size",t))}postboxes.add_postbox_toggles(pagenow),window.name="",h("#post-lock-dialog .notification-dialog").on("keydown",function(t){if(9==t.which){var e=h(t.target);e.hasClass("wp-tab-first")&&t.shiftKey?(h(this).find(".wp-tab-last").focus(),t.preventDefault()):e.hasClass("wp-tab-last")&&!t.shiftKey&&(h(this).find(".wp-tab-first").focus(),t.preventDefault())}}).filter(":visible").find(".wp-tab-first").focus(),wp.heartbeat&&h("#post-lock-dialog").length&&wp.heartbeat.interval(15),i=m.find(":submit, a.submitdelete, #post-preview").on("click.edit-post",function(t){var e=h(this);e.hasClass("disabled")?t.preventDefault():e.hasClass("submitdelete")||e.is("#post-preview")||h("form#post").off("submit.edit-post").on("submit.edit-post",function(t){if(!t.isDefaultPrevented()){if(wp.autosave&&wp.autosave.server.suspend(),"undefined"!=typeof commentReply){if(!commentReply.discardCommentChanges())return!1;commentReply.close()}w=!1,h(window).off("beforeunload.edit-post"),i.addClass("disabled"),"publish"===e.attr("id")?m.find("#major-publishing-actions .spinner").addClass("is-active"):m.find("#minor-publishing .spinner").addClass("is-active")}})}),h("#post-preview").on("click.post-preview",function(t){var e=h(this),i=h("form#post"),n=h("input#wp-preview"),s=e.attr("target")||"wp-preview",a=navigator.userAgent.toLowerCase();t.preventDefault(),e.hasClass("disabled")||(wp.autosave&&wp.autosave.server.tempBlockSave(),n.val("dopreview"),i.attr("target",s).submit().attr("target",""),-1!==a.indexOf("safari")&&-1===a.indexOf("chrome")&&i.attr("action",function(t,e){return e+"?t="+(new Date).getTime()}),n.val(""))}),h("#title").on("keydown.editor-focus",function(t){var e;if(9===t.keyCode&&!t.ctrlKey&&!t.altKey&&!t.shiftKey){if((e="undefined"!=typeof tinymce&&tinymce.get("content"))&&!e.isHidden())e.focus();else{if(!u.length)return;u.focus()}t.preventDefault()}}),h("#auto_draft").val()&&h("#title").blur(function(){var t;this.value&&!h("#edit-slug-box > *").length&&(h("form#post").one("submit",function(){t=!0}),window.setTimeout(function(){!t&&wp.autosave&&wp.autosave.server.triggerSave()},200))}),f.on("autosave-disable-buttons.edit-post",function(){i.addClass("disabled")}).on("autosave-enable-buttons.edit-post",function(){wp.heartbeat&&wp.heartbeat.hasConnectionError()||i.removeClass("disabled")}).on("before-autosave.edit-post",function(){h(".autosave-message").text(postL10n.savingText)}).on("after-autosave.edit-post",function(t,e){h(".autosave-message").text(e.message),h(document.body).hasClass("post-new-php")&&h(".submitbox .submitdelete").show()}),h(window).on("beforeunload.edit-post",function(){var t="undefined"!=typeof tinymce&&tinymce.get("content");if(t&&!t.isHidden()&&t.isDirty()||wp.autosave&&wp.autosave.server.postChanged())return postL10n.saveAlert}).on("unload.edit-post",function(t){if(w&&(!t.target||"#document"==t.target.nodeName)){var e=h("#post_ID").val(),i=h("#active_post_lock").val();if(e&&i){var n={action:"wp-remove-post-lock",_wpnonce:h("#_wpnonce").val(),post_ID:e,active_post_lock:i};if(window.FormData&&window.navigator.sendBeacon){var s=new window.FormData;if(h.each(n,function(t,e){s.append(t,e)}),window.navigator.sendBeacon(ajaxurl,s))return}h.post({async:!1,data:n,url:ajaxurl})}}}),h("#tagsdiv-post_tag").length?window.tagBox&&window.tagBox.init():h(".meta-box-sortables").children("div.postbox").each(function(){if(0===this.id.indexOf("tagsdiv-"))return window.tagBox&&window.tagBox.init(),!1}),h(".categorydiv").each(function(){var t,e,i,s,n;(i=h(this).attr("id").split("-")).shift(),s=i.join("-"),n=s+"_tab","category"==s&&(n="cats"),h("a","#"+s+"-tabs").click(function(t){t.preventDefault();var e=h(this).attr("href");h(this).parent().addClass("tabs").siblings("li").removeClass("tabs"),h("#"+s+"-tabs").siblings(".tabs-panel").hide(),h(e).show(),"#"+s+"-all"==e?deleteUserSetting(n):setUserSetting(n,"pop")}),getUserSetting(n)&&h('a[href="#'+s+'-pop"]',"#"+s+"-tabs").click(),h("#new"+s).one("focus",function(){h(this).val("").removeClass("form-input-tip")}),h("#new"+s).keypress(function(t){13===t.keyCode&&(t.preventDefault(),h("#"+s+"-add-submit").click())}),h("#"+s+"-add-submit").click(function(){h("#new"+s).focus()}),t=function(t){return!!h("#new"+s).val()&&(t.data+="&"+h(":checked","#"+s+"checklist").serialize(),h("#"+s+"-add-submit").prop("disabled",!0),t)},e=function(t,e){var i,n=h("#new"+s+"_parent");h("#"+s+"-add-submit").prop("disabled",!1),"undefined"!=e.parsed.responses[0]&&(i=e.parsed.responses[0].supplemental.newcat_parent)&&(n.before(i),n.remove())},h("#"+s+"checklist").wpList({alt:"",response:s+"-ajax-response",addBefore:t,addAfter:e}),h("#"+s+"-add-toggle").click(function(t){t.preventDefault(),h("#"+s+"-adder").toggleClass("wp-hidden-children"),h('a[href="#'+s+'-all"]',"#"+s+"-tabs").click(),h("#new"+s).focus()}),h("#"+s+"checklist, #"+s+"checklist-pop").on("click",'li.popular-category > label input[type="checkbox"]',function(){var t=h(this),e=t.is(":checked"),i=t.val();i&&t.parents("#taxonomy-"+s).length&&h("#in-"+s+"-"+i+", #in-popular-"+s+"-"+i).prop("checked",e)})}),h("#postcustom").length&&h("#the-list").wpList({addBefore:function(t){return t.data+="&post_id="+h("#post_ID").val(),t},addAfter:function(){h("table#list-table").show()}}),h("#submitdiv").length&&(d=h("#timestamp").html(),e=h("#post-visibility-display").html(),n=function(){"public"!=b.find("input:radio:checked").val()?(h("#sticky").prop("checked",!1),h("#sticky-span").hide()):h("#sticky-span").show(),"password"!=b.find("input:radio:checked").val()?h("#password-span").hide():h("#password-span").show()},s=function(){if(!g.length)return!0;var t,e,i,n,s=h("#post_status"),a=h('option[value="publish"]',s),o=h("#aa").val(),l=h("#mm").val(),p=h("#jj").val(),c=h("#hh").val(),r=h("#mn").val();return t=new Date(o,l-1,p,c,r),e=new Date(h("#hidden_aa").val(),h("#hidden_mm").val()-1,h("#hidden_jj").val(),h("#hidden_hh").val(),h("#hidden_mn").val()),i=new Date(h("#cur_aa").val(),h("#cur_mm").val()-1,h("#cur_jj").val(),h("#cur_hh").val(),h("#cur_mn").val()),t.getFullYear()!=o||1+t.getMonth()!=l||t.getDate()!=p||t.getMinutes()!=r?(g.find(".timestamp-wrap").addClass("form-invalid"),!1):(g.find(".timestamp-wrap").removeClass("form-invalid"),i<t&&"future"!=h("#original_post_status").val()?(n=postL10n.publishOnFuture,h("#publish").val(postL10n.schedule)):t<=i&&"publish"!=h("#original_post_status").val()?(n=postL10n.publishOn,h("#publish").val(postL10n.publish)):(n=postL10n.publishOnPast,h("#publish").val(postL10n.update)),e.toUTCString()==t.toUTCString()?h("#timestamp").html(d):h("#timestamp").html("\n"+n+" <b>"+postL10n.dateFormat.replace("%1$s",h('option[value="'+l+'"]',"#mm").attr("data-text")).replace("%2$s",parseInt(p,10)).replace("%3$s",o).replace("%4$s",("00"+c).slice(-2)).replace("%5$s",("00"+r).slice(-2))+"</b> "),"private"==b.find("input:radio:checked").val()?(h("#publish").val(postL10n.update),0===a.length?s.append('<option value="publish">'+postL10n.privatelyPublished+"</option>"):a.html(postL10n.privatelyPublished),h('option[value="publish"]',s).prop("selected",!0),h("#misc-publishing-actions .edit-post-status").hide()):("future"==h("#original_post_status").val()||"draft"==h("#original_post_status").val()?a.length&&(a.remove(),s.val(h("#hidden_post_status").val())):a.html(postL10n.published),s.is(":hidden")&&h("#misc-publishing-actions .edit-post-status").show()),h("#post-status-display").text(wp.sanitize.stripTagsAndEncodeText(h("option:selected",s).text())),"private"==h("option:selected",s).val()||"publish"==h("option:selected",s).val()?h("#save-post").hide():(h("#save-post").show(),"pending"==h("option:selected",s).val()?h("#save-post").show().val(postL10n.savePending):h("#save-post").show().val(postL10n.saveDraft)),!0)},h("#visibility .edit-visibility").click(function(t){t.preventDefault(),b.is(":hidden")&&(n(),b.slideDown("fast",function(){b.find('input[type="radio"]').first().focus()}),h(this).hide())}),b.find(".cancel-post-visibility").click(function(t){b.slideUp("fast"),h("#visibility-radio-"+h("#hidden-post-visibility").val()).prop("checked",!0),h("#post_password").val(h("#hidden-post-password").val()),h("#sticky").prop("checked",h("#hidden-post-sticky").prop("checked")),h("#post-visibility-display").html(e),h("#visibility .edit-visibility").show().focus(),s(),t.preventDefault()}),b.find(".save-post-visibility").click(function(t){b.slideUp("fast"),h("#visibility .edit-visibility").show().focus(),s(),"public"!=b.find("input:radio:checked").val()&&h("#sticky").prop("checked",!1),r=h("#sticky").prop("checked")?"Sticky":"",h("#post-visibility-display").html(postL10n[b.find("input:radio:checked").val()+r]),t.preventDefault()}),b.find("input:radio").change(function(){n()}),g.siblings("a.edit-timestamp").click(function(t){g.is(":hidden")&&(g.slideDown("fast",function(){h("input, select",g.find(".timestamp-wrap")).first().focus()}),h(this).hide()),t.preventDefault()}),g.find(".cancel-timestamp").click(function(t){g.slideUp("fast").siblings("a.edit-timestamp").show().focus(),h("#mm").val(h("#hidden_mm").val()),h("#jj").val(h("#hidden_jj").val()),h("#aa").val(h("#hidden_aa").val()),h("#hh").val(h("#hidden_hh").val()),h("#mn").val(h("#hidden_mn").val()),s(),t.preventDefault()}),g.find(".save-timestamp").click(function(t){s()&&(g.slideUp("fast"),g.siblings("a.edit-timestamp").show().focus()),t.preventDefault()}),h("#post").on("submit",function(t){s()||(t.preventDefault(),g.show(),wp.autosave&&wp.autosave.enableButtons(),h("#publishing-action .spinner").removeClass("is-active"))}),k.siblings("a.edit-post-status").click(function(t){k.is(":hidden")&&(k.slideDown("fast",function(){k.find("select").focus()}),h(this).hide()),t.preventDefault()}),k.find(".save-post-status").click(function(t){k.slideUp("fast").siblings("a.edit-post-status").show().focus(),s(),t.preventDefault()}),k.find(".cancel-post-status").click(function(t){k.slideUp("fast").siblings("a.edit-post-status").show().focus(),h("#post_status").val(h("#hidden_post_status").val()),s(),t.preventDefault()})),h("#titlediv").on("click",".edit-slug",function(){!function(){var t,e,n,i,s=0,a=h("#post_name"),o=a.val(),l=h("#sample-permalink"),p=l.html(),c=h("#sample-permalink a").html(),r=h("#edit-slug-buttons"),d=r.html(),u=h("#editable-post-name-full");for(u.find("img").replaceWith(function(){return this.alt}),u=u.html(),l.html(c),n=h("#editable-post-name"),i=n.html(),r.html('<button type="button" class="save button button-small">'+postL10n.ok+'</button> <button type="button" class="cancel button-link">'+postL10n.cancel+"</button>"),r.children(".save").click(function(){var i=n.children("input").val();i!=h("#editable-post-name-full").text()?h.post(ajaxurl,{action:"sample-permalink",post_id:v,new_slug:i,new_title:h("#title").val(),samplepermalinknonce:h("#samplepermalinknonce").val()},function(t){var e=h("#edit-slug-box");e.html(t),e.hasClass("hidden")&&e.fadeIn("fast",function(){e.removeClass("hidden")}),r.html(d),l.html(p),a.val(i),h(".edit-slug").focus(),wp.a11y.speak(postL10n.permalinkSaved)}):r.children(".cancel").click()}),r.children(".cancel").click(function(){h("#view-post-btn").show(),n.html(i),r.html(d),l.html(p),a.val(o),h(".edit-slug").focus()}),t=0;t<u.length;++t)"%"==u.charAt(t)&&s++;e=s>u.length/4?"":u,n.html('<input type="text" id="new-post-slug" value="'+e+'" autocomplete="off" />').children("input").keydown(function(t){var e=t.which;13===e&&(t.preventDefault(),r.children(".save").click()),27===e&&r.children(".cancel").click()}).keyup(function(){a.val(this.value)}).focus()}()}),window.wptitlehint=function(t){var e=h("#"+(t=t||"title")),i=h("#"+t+"-prompt-text");""===e.val()&&i.removeClass("screen-reader-text"),e.on("input",function(){""!==this.value?i.addClass("screen-reader-text"):i.removeClass("screen-reader-text")})},wptitlehint(),t=h("#post-status-info"),p=h("#postdivrich"),!u.length||"ontouchstart"in window?h("#content-resize-handle").hide():t.on("mousedown.wp-editor-resize",function(t){"undefined"!=typeof tinymce&&(a=tinymce.get("content")),a&&!a.isHidden()?(l=!0,o=h("#content_ifr").height()-t.pageY):(l=!1,o=u.height()-t.pageY,u.blur()),f.on("mousemove.wp-editor-resize",_).on("mouseup.wp-editor-resize mouseleave.wp-editor-resize",x),t.preventDefault()}).on("mouseup.wp-editor-resize",x),"undefined"!=typeof tinymce&&(h("#post-formats-select input.post-format").on("change.set-editor-class",function(){var t,e,i=this.id;i&&h(this).prop("checked")&&(t=tinymce.get("content"))&&((e=t.getBody()).className=e.className.replace(/\bpost-format-[^ ]+/,""),t.dom.addClass(e,"post-format-0"==i?"post-format-standard":i),h(document).trigger("editor-classchange"))}),h("#page_template").on("change.set-editor-class",function(){var t,e,i=h(this).val()||"";(i=i.substr(i.lastIndexOf("/")+1,i.length).replace(/\.php$/,"").replace(/\./g,"-"))&&(t=tinymce.get("content"))&&((e=t.getBody()).className=e.className.replace(/\bpage-template-[^ ]+/,""),t.dom.addClass(e,"page-template-"+i),h(document).trigger("editor-classchange"))})),u.on("keydown.wp-autosave",function(t){if(83===t.which){if(t.shiftKey||t.altKey||y&&(!t.metaKey||t.ctrlKey)||!y&&!t.ctrlKey)return;wp.autosave&&wp.autosave.server.triggerSave(),t.preventDefault()}}),"auto-draft"===h("#original_post_status").val()&&window.history.replaceState&&h("#publish").on("click",function(){c=window.location.href,c+=-1!==c.indexOf("?")?"&":"?",c+="wp-post-new-reload=true",window.history.replaceState(null,null,c)})}),function(t,l){t(function(){var i,n=t("#content"),s=t("#wp-word-count").find(".word-count"),a=0;function o(){var t,e;t=!i||i.isHidden()?n.val():i.getContent({format:"raw"}),(e=l.count(t))!==a&&s.text(e),a=e}t(document).on("tinymce-editor-init",function(t,e){"content"===e.id&&(i=e).on("nodechange keyup",_.debounce(o,1e3))}),n.on("input keyup",_.debounce(o,1e3)),o()})}(jQuery,new wp.utils.WordCounter);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/postbox.js b/srcs/wordpress/wp-admin/js/postbox.js deleted file mode 100644 index 88facb1..0000000 --- a/srcs/wordpress/wp-admin/js/postbox.js +++ /dev/null @@ -1,445 +0,0 @@ -/** - * Contains the postboxes logic, opening and closing postboxes, reordering and saving - * the state and ordering to the database. - * - * @since 2.5.0 - * @requires jQuery - * @output wp-admin/js/postbox.js - */ - -/* global ajaxurl, postBoxL10n, postboxes */ - -(function($) { - var $document = $( document ); - - /** - * This object contains all function to handle the behaviour of the post boxes. The post boxes are the boxes you see - * around the content on the edit page. - * - * @since 2.7.0 - * - * @namespace postboxes - * - * @type {Object} - */ - window.postboxes = { - - /** - * Handles a click on either the postbox heading or the postbox open/close icon. - * - * Opens or closes the postbox. Expects `this` to equal the clicked element. - * Calls postboxes.pbshow if the postbox has been opened, calls postboxes.pbhide - * if the postbox has been closed. - * - * @since 4.4.0 - * @memberof postboxes - * @fires postboxes#postbox-toggled - * - * @returns {void} - */ - handle_click : function () { - var $el = $( this ), - p = $el.parent( '.postbox' ), - id = p.attr( 'id' ), - ariaExpandedValue; - - if ( 'dashboard_browser_nag' === id ) { - return; - } - - p.toggleClass( 'closed' ); - - ariaExpandedValue = ! p.hasClass( 'closed' ); - - if ( $el.hasClass( 'handlediv' ) ) { - // The handle button was clicked. - $el.attr( 'aria-expanded', ariaExpandedValue ); - } else { - // The handle heading was clicked. - $el.closest( '.postbox' ).find( 'button.handlediv' ) - .attr( 'aria-expanded', ariaExpandedValue ); - } - - if ( postboxes.page !== 'press-this' ) { - postboxes.save_state( postboxes.page ); - } - - if ( id ) { - if ( !p.hasClass('closed') && $.isFunction( postboxes.pbshow ) ) { - postboxes.pbshow( id ); - } else if ( p.hasClass('closed') && $.isFunction( postboxes.pbhide ) ) { - postboxes.pbhide( id ); - } - } - - /** - * Fires when a postbox has been opened or closed. - * - * Contains a jQuery object with the relevant postbox element. - * - * @since 4.0.0 - * @ignore - * - * @event postboxes#postbox-toggled - * @type {Object} - */ - $document.trigger( 'postbox-toggled', p ); - }, - - /** - * Adds event handlers to all postboxes and screen option on the current page. - * - * @since 2.7.0 - * @memberof postboxes - * - * @param {string} page The page we are currently on. - * @param {Object} [args] - * @param {Function} args.pbshow A callback that is called when a postbox opens. - * @param {Function} args.pbhide A callback that is called when a postbox closes. - * @returns {void} - */ - add_postbox_toggles : function (page, args) { - var $handles = $( '.postbox .hndle, .postbox .handlediv' ); - - this.page = page; - this.init( page, args ); - - $handles.on( 'click.postboxes', this.handle_click ); - - /** - * @since 2.7.0 - */ - $('.postbox .hndle a').click( function(e) { - e.stopPropagation(); - }); - - /** - * Hides a postbox. - * - * Event handler for the postbox dismiss button. After clicking the button - * the postbox will be hidden. - * - * @since 3.2.0 - * - * @returns {void} - */ - $( '.postbox a.dismiss' ).on( 'click.postboxes', function( e ) { - var hide_id = $(this).parents('.postbox').attr('id') + '-hide'; - e.preventDefault(); - $( '#' + hide_id ).prop('checked', false).triggerHandler('click'); - }); - - /** - * Hides the postbox element - * - * Event handler for the screen options checkboxes. When a checkbox is - * clicked this function will hide or show the relevant postboxes. - * - * @since 2.7.0 - * @ignore - * - * @fires postboxes#postbox-toggled - * - * @returns {void} - */ - $('.hide-postbox-tog').bind('click.postboxes', function() { - var $el = $(this), - boxId = $el.val(), - $postbox = $( '#' + boxId ); - - if ( $el.prop( 'checked' ) ) { - $postbox.show(); - if ( $.isFunction( postboxes.pbshow ) ) { - postboxes.pbshow( boxId ); - } - } else { - $postbox.hide(); - if ( $.isFunction( postboxes.pbhide ) ) { - postboxes.pbhide( boxId ); - } - } - - postboxes.save_state( page ); - postboxes._mark_area(); - - /** - * @since 4.0.0 - * @see postboxes.handle_click - */ - $document.trigger( 'postbox-toggled', $postbox ); - }); - - /** - * Changes the amount of columns based on the layout preferences. - * - * @since 2.8.0 - * - * @returns {void} - */ - $('.columns-prefs input[type="radio"]').bind('click.postboxes', function(){ - var n = parseInt($(this).val(), 10); - - if ( n ) { - postboxes._pb_edit(n); - postboxes.save_order( page ); - } - }); - }, - - /** - * Initializes all the postboxes, mainly their sortable behaviour. - * - * @since 2.7.0 - * @memberof postboxes - * - * @param {string} page The page we are currently on. - * @param {Object} [args={}] The arguments for the postbox initializer. - * @param {Function} args.pbshow A callback that is called when a postbox opens. - * @param {Function} args.pbhide A callback that is called when a postbox - * closes. - * - * @returns {void} - */ - init : function(page, args) { - var isMobile = $( document.body ).hasClass( 'mobile' ), - $handleButtons = $( '.postbox .handlediv' ); - - $.extend( this, args || {} ); - $('#wpbody-content').css('overflow','hidden'); - $('.meta-box-sortables').sortable({ - placeholder: 'sortable-placeholder', - connectWith: '.meta-box-sortables', - items: '.postbox', - handle: '.hndle', - cursor: 'move', - delay: ( isMobile ? 200 : 0 ), - distance: 2, - tolerance: 'pointer', - forcePlaceholderSize: true, - helper: function( event, element ) { - /* `helper: 'clone'` is equivalent to `return element.clone();` - * Cloning a checked radio and then inserting that clone next to the original - * radio unchecks the original radio (since only one of the two can be checked). - * We get around this by renaming the helper's inputs' name attributes so that, - * when the helper is inserted into the DOM for the sortable, no radios are - * duplicated, and no original radio gets unchecked. - */ - return element.clone() - .find( ':input' ) - .attr( 'name', function( i, currentName ) { - return 'sort_' + parseInt( Math.random() * 100000, 10 ).toString() + '_' + currentName; - } ) - .end(); - }, - opacity: 0.65, - stop: function() { - var $el = $( this ); - - if ( $el.find( '#dashboard_browser_nag' ).is( ':visible' ) && 'dashboard_browser_nag' != this.firstChild.id ) { - $el.sortable('cancel'); - return; - } - - postboxes.save_order(page); - }, - receive: function(e,ui) { - if ( 'dashboard_browser_nag' == ui.item[0].id ) - $(ui.sender).sortable('cancel'); - - postboxes._mark_area(); - $document.trigger( 'postbox-moved', ui.item ); - } - }); - - if ( isMobile ) { - $(document.body).bind('orientationchange.postboxes', function(){ postboxes._pb_change(); }); - this._pb_change(); - } - - this._mark_area(); - - // Set the handle buttons `aria-expanded` attribute initial value on page load. - $handleButtons.each( function () { - var $el = $( this ); - $el.attr( 'aria-expanded', ! $el.parent( '.postbox' ).hasClass( 'closed' ) ); - }); - }, - - /** - * Saves the state of the postboxes to the server. - * - * It sends two lists, one with all the closed postboxes, one with all the - * hidden postboxes. - * - * @since 2.7.0 - * @memberof postboxes - * - * @param {string} page The page we are currently on. - * @returns {void} - */ - save_state : function(page) { - var closed, hidden; - - // Return on the nav-menus.php screen, see #35112. - if ( 'nav-menus' === page ) { - return; - } - - closed = $( '.postbox' ).filter( '.closed' ).map( function() { return this.id; } ).get().join( ',' ); - hidden = $( '.postbox' ).filter( ':hidden' ).map( function() { return this.id; } ).get().join( ',' ); - - $.post(ajaxurl, { - action: 'closed-postboxes', - closed: closed, - hidden: hidden, - closedpostboxesnonce: jQuery('#closedpostboxesnonce').val(), - page: page - }); - }, - - /** - * Saves the order of the postboxes to the server. - * - * Sends a list of all postboxes inside a sortable area to the server. - * - * @since 2.8.0 - * @memberof postboxes - * - * @param {string} page The page we are currently on. - * @returns {void} - */ - save_order : function(page) { - var postVars, page_columns = $('.columns-prefs input:checked').val() || 0; - - postVars = { - action: 'meta-box-order', - _ajax_nonce: $('#meta-box-order-nonce').val(), - page_columns: page_columns, - page: page - }; - - $('.meta-box-sortables').each( function() { - postVars[ 'order[' + this.id.split( '-' )[0] + ']' ] = $( this ).sortable( 'toArray' ).join( ',' ); - } ); - - $.post( ajaxurl, postVars ); - }, - - /** - * Marks empty postbox areas. - * - * Adds a message to empty sortable areas on the dashboard page. Also adds a - * border around the side area on the post edit screen if there are no postboxes - * present. - * - * @since 3.3.0 - * @memberof postboxes - * @access private - * - * @returns {void} - */ - _mark_area : function() { - var visible = $('div.postbox:visible').length, side = $('#post-body #side-sortables'); - - $( '#dashboard-widgets .meta-box-sortables:visible' ).each( function() { - var t = $(this); - - if ( visible == 1 || t.children('.postbox:visible').length ) { - t.removeClass('empty-container'); - } - else { - t.addClass('empty-container'); - t.attr('data-emptyString', postBoxL10n.postBoxEmptyString); - } - }); - - if ( side.length ) { - if ( side.children('.postbox:visible').length ) - side.removeClass('empty-container'); - else if ( $('#postbox-container-1').css('width') == '280px' ) - side.addClass('empty-container'); - } - }, - - /** - * Changes the amount of columns on the post edit page. - * - * @since 3.3.0 - * @memberof postboxes - * @fires postboxes#postboxes-columnchange - * @access private - * - * @param {number} n The amount of columns to divide the post edit page in. - * @returns {void} - */ - _pb_edit : function(n) { - var el = $('.metabox-holder').get(0); - - if ( el ) { - el.className = el.className.replace(/columns-\d+/, 'columns-' + n); - } - - /** - * Fires when the amount of columns on the post edit page has been changed. - * - * @since 4.0.0 - * @ignore - * - * @event postboxes#postboxes-columnchange - */ - $( document ).trigger( 'postboxes-columnchange' ); - }, - - /** - * Changes the amount of columns the postboxes are in based on the current - * orientation of the browser. - * - * @since 3.3.0 - * @memberof postboxes - * @access private - * - * @returns {void} - */ - _pb_change : function() { - var check = $( 'label.columns-prefs-1 input[type="radio"]' ); - - switch ( window.orientation ) { - case 90: - case -90: - if ( !check.length || !check.is(':checked') ) - this._pb_edit(2); - break; - case 0: - case 180: - if ( $('#poststuff').length ) { - this._pb_edit(1); - } else { - if ( !check.length || !check.is(':checked') ) - this._pb_edit(2); - } - break; - } - }, - - /* Callbacks */ - - /** - * @since 2.7.0 - * @memberof postboxes - * @access public - * @property {Function|boolean} pbshow A callback that is called when a postbox - * is opened. - */ - pbshow : false, - - /** - * @since 2.7.0 - * @memberof postboxes - * @access public - * @property {Function|boolean} pbhide A callback that is called when a postbox - * is closed. - */ - pbhide : false - }; - -}(jQuery)); diff --git a/srcs/wordpress/wp-admin/js/postbox.min.js b/srcs/wordpress/wp-admin/js/postbox.min.js deleted file mode 100644 index 3bce933..0000000 --- a/srcs/wordpress/wp-admin/js/postbox.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(a){var n=a(document);window.postboxes={handle_click:function(){var e,o=a(this),s=o.parent(".postbox"),t=s.attr("id");"dashboard_browser_nag"!==t&&(s.toggleClass("closed"),e=!s.hasClass("closed"),o.hasClass("handlediv")?o.attr("aria-expanded",e):o.closest(".postbox").find("button.handlediv").attr("aria-expanded",e),"press-this"!==postboxes.page&&postboxes.save_state(postboxes.page),t&&(!s.hasClass("closed")&&a.isFunction(postboxes.pbshow)?postboxes.pbshow(t):s.hasClass("closed")&&a.isFunction(postboxes.pbhide)&&postboxes.pbhide(t)),n.trigger("postbox-toggled",s))},add_postbox_toggles:function(t,e){var o=a(".postbox .hndle, .postbox .handlediv");this.page=t,this.init(t,e),o.on("click.postboxes",this.handle_click),a(".postbox .hndle a").click(function(e){e.stopPropagation()}),a(".postbox a.dismiss").on("click.postboxes",function(e){var o=a(this).parents(".postbox").attr("id")+"-hide";e.preventDefault(),a("#"+o).prop("checked",!1).triggerHandler("click")}),a(".hide-postbox-tog").bind("click.postboxes",function(){var e=a(this),o=e.val(),s=a("#"+o);e.prop("checked")?(s.show(),a.isFunction(postboxes.pbshow)&&postboxes.pbshow(o)):(s.hide(),a.isFunction(postboxes.pbhide)&&postboxes.pbhide(o)),postboxes.save_state(t),postboxes._mark_area(),n.trigger("postbox-toggled",s)}),a('.columns-prefs input[type="radio"]').bind("click.postboxes",function(){var e=parseInt(a(this).val(),10);e&&(postboxes._pb_edit(e),postboxes.save_order(t))})},init:function(o,e){var s=a(document.body).hasClass("mobile"),t=a(".postbox .handlediv");a.extend(this,e||{}),a("#wpbody-content").css("overflow","hidden"),a(".meta-box-sortables").sortable({placeholder:"sortable-placeholder",connectWith:".meta-box-sortables",items:".postbox",handle:".hndle",cursor:"move",delay:s?200:0,distance:2,tolerance:"pointer",forcePlaceholderSize:!0,helper:function(e,o){return o.clone().find(":input").attr("name",function(e,o){return"sort_"+parseInt(1e5*Math.random(),10).toString()+"_"+o}).end()},opacity:.65,stop:function(){var e=a(this);e.find("#dashboard_browser_nag").is(":visible")&&"dashboard_browser_nag"!=this.firstChild.id?e.sortable("cancel"):postboxes.save_order(o)},receive:function(e,o){"dashboard_browser_nag"==o.item[0].id&&a(o.sender).sortable("cancel"),postboxes._mark_area(),n.trigger("postbox-moved",o.item)}}),s&&(a(document.body).bind("orientationchange.postboxes",function(){postboxes._pb_change()}),this._pb_change()),this._mark_area(),t.each(function(){var e=a(this);e.attr("aria-expanded",!e.parent(".postbox").hasClass("closed"))})},save_state:function(e){var o,s;"nav-menus"!==e&&(o=a(".postbox").filter(".closed").map(function(){return this.id}).get().join(","),s=a(".postbox").filter(":hidden").map(function(){return this.id}).get().join(","),a.post(ajaxurl,{action:"closed-postboxes",closed:o,hidden:s,closedpostboxesnonce:jQuery("#closedpostboxesnonce").val(),page:e}))},save_order:function(e){var o,s=a(".columns-prefs input:checked").val()||0;o={action:"meta-box-order",_ajax_nonce:a("#meta-box-order-nonce").val(),page_columns:s,page:e},a(".meta-box-sortables").each(function(){o["order["+this.id.split("-")[0]+"]"]=a(this).sortable("toArray").join(",")}),a.post(ajaxurl,o)},_mark_area:function(){var o=a("div.postbox:visible").length,e=a("#post-body #side-sortables");a("#dashboard-widgets .meta-box-sortables:visible").each(function(){var e=a(this);1==o||e.children(".postbox:visible").length?e.removeClass("empty-container"):(e.addClass("empty-container"),e.attr("data-emptyString",postBoxL10n.postBoxEmptyString))}),e.length&&(e.children(".postbox:visible").length?e.removeClass("empty-container"):"280px"==a("#postbox-container-1").css("width")&&e.addClass("empty-container"))},_pb_edit:function(e){var o=a(".metabox-holder").get(0);o&&(o.className=o.className.replace(/columns-\d+/,"columns-"+e)),a(document).trigger("postboxes-columnchange")},_pb_change:function(){var e=a('label.columns-prefs-1 input[type="radio"]');switch(window.orientation){case 90:case-90:e.length&&e.is(":checked")||this._pb_edit(2);break;case 0:case 180:a("#poststuff").length?this._pb_edit(1):e.length&&e.is(":checked")||this._pb_edit(2)}},pbshow:!1,pbhide:!1}}(jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/privacy-tools.js b/srcs/wordpress/wp-admin/js/privacy-tools.js deleted file mode 100644 index 802ec88..0000000 --- a/srcs/wordpress/wp-admin/js/privacy-tools.js +++ /dev/null @@ -1,263 +0,0 @@ -/** - * Interactions used by the User Privacy tools in WordPress. - * - * @output wp-admin/js/privacy-tools.js - */ - -// Privacy request action handling -jQuery( document ).ready( function( $ ) { - var strings = window.privacyToolsL10n || {}; - - function setActionState( $action, state ) { - $action.children().addClass( 'hidden' ); - $action.children( '.' + state ).removeClass( 'hidden' ); - } - - function clearResultsAfterRow( $requestRow ) { - $requestRow.removeClass( 'has-request-results' ); - - if ( $requestRow.next().hasClass( 'request-results' ) ) { - $requestRow.next().remove(); - } - } - - function appendResultsAfterRow( $requestRow, classes, summaryMessage, additionalMessages ) { - var itemList = '', - resultRowClasses = 'request-results'; - - clearResultsAfterRow( $requestRow ); - - if ( additionalMessages.length ) { - $.each( additionalMessages, function( index, value ) { - itemList = itemList + '<li>' + value + '</li>'; - }); - itemList = '<ul>' + itemList + '</ul>'; - } - - $requestRow.addClass( 'has-request-results' ); - - if ( $requestRow.hasClass( 'status-request-confirmed' ) ) { - resultRowClasses = resultRowClasses + ' status-request-confirmed'; - } - - if ( $requestRow.hasClass( 'status-request-failed' ) ) { - resultRowClasses = resultRowClasses + ' status-request-failed'; - } - - $requestRow.after( function() { - return '<tr class="' + resultRowClasses + '"><th colspan="5">' + - '<div class="notice inline notice-alt ' + classes + '">' + - '<p>' + summaryMessage + '</p>' + - itemList + - '</div>' + - '</td>' + - '</tr>'; - }); - } - - $( '.export-personal-data-handle' ).click( function( event ) { - var $this = $( this ), - $action = $this.parents( '.export-personal-data' ), - $requestRow = $this.parents( 'tr' ), - requestID = $action.data( 'request-id' ), - nonce = $action.data( 'nonce' ), - exportersCount = $action.data( 'exporters-count' ), - sendAsEmail = $action.data( 'send-as-email' ) ? true : false; - - event.preventDefault(); - event.stopPropagation(); - - $action.blur(); - clearResultsAfterRow( $requestRow ); - - function onExportDoneSuccess( zipUrl ) { - var summaryMessage = strings.emailSent; - - setActionState( $action, 'export-personal-data-success' ); - - appendResultsAfterRow( $requestRow, 'notice-success', summaryMessage, [] ); - $this.hide(); - - if ( 'undefined' !== typeof zipUrl ) { - window.location = zipUrl; - } else if ( ! sendAsEmail ) { - onExportFailure( strings.noExportFile ); - } - } - - function onExportFailure( errorMessage ) { - setActionState( $action, 'export-personal-data-failed' ); - if ( errorMessage ) { - appendResultsAfterRow( $requestRow, 'notice-error', strings.exportError, [ errorMessage ] ); - } - } - - function doNextExport( exporterIndex, pageIndex ) { - $.ajax( - { - url: window.ajaxurl, - data: { - action: 'wp-privacy-export-personal-data', - exporter: exporterIndex, - id: requestID, - page: pageIndex, - security: nonce, - sendAsEmail: sendAsEmail - }, - method: 'post' - } - ).done( function( response ) { - var responseData = response.data; - - if ( ! response.success ) { - - // e.g. invalid request ID - onExportFailure( response.data ); - return; - } - - if ( ! responseData.done ) { - setTimeout( doNextExport( exporterIndex, pageIndex + 1 ) ); - } else { - if ( exporterIndex < exportersCount ) { - setTimeout( doNextExport( exporterIndex + 1, 1 ) ); - } else { - onExportDoneSuccess( responseData.url ); - } - } - }).fail( function( jqxhr, textStatus, error ) { - - // e.g. Nonce failure - onExportFailure( error ); - }); - } - - // And now, let's begin - setActionState( $action, 'export-personal-data-processing' ); - doNextExport( 1, 1 ); - }); - - $( '.remove-personal-data-handle' ).click( function( event ) { - var $this = $( this ), - $action = $this.parents( '.remove-personal-data' ), - $requestRow = $this.parents( 'tr' ), - requestID = $action.data( 'request-id' ), - nonce = $action.data( 'nonce' ), - erasersCount = $action.data( 'erasers-count' ), - hasRemoved = false, - hasRetained = false, - messages = []; - - event.stopPropagation(); - - $action.blur(); - clearResultsAfterRow( $requestRow ); - - function onErasureDoneSuccess() { - var summaryMessage = strings.noDataFound; - var classes = 'notice-success'; - - setActionState( $action, 'remove-personal-data-success' ); - - if ( false === hasRemoved ) { - if ( false === hasRetained ) { - summaryMessage = strings.noDataFound; - } else { - summaryMessage = strings.noneRemoved; - classes = 'notice-warning'; - } - } else { - if ( false === hasRetained ) { - summaryMessage = strings.foundAndRemoved; - } else { - summaryMessage = strings.someNotRemoved; - classes = 'notice-warning'; - } - } - appendResultsAfterRow( $requestRow, classes, summaryMessage, messages ); - $this.hide(); - } - - function onErasureFailure() { - setActionState( $action, 'remove-personal-data-failed' ); - appendResultsAfterRow( $requestRow, 'notice-error', strings.removalError, [] ); - } - - function doNextErasure( eraserIndex, pageIndex ) { - $.ajax({ - url: window.ajaxurl, - data: { - action: 'wp-privacy-erase-personal-data', - eraser: eraserIndex, - id: requestID, - page: pageIndex, - security: nonce - }, - method: 'post' - }).done( function( response ) { - var responseData = response.data; - - if ( ! response.success ) { - onErasureFailure(); - return; - } - if ( responseData.items_removed ) { - hasRemoved = hasRemoved || responseData.items_removed; - } - if ( responseData.items_retained ) { - hasRetained = hasRetained || responseData.items_retained; - } - if ( responseData.messages ) { - messages = messages.concat( responseData.messages ); - } - if ( ! responseData.done ) { - setTimeout( doNextErasure( eraserIndex, pageIndex + 1 ) ); - } else { - if ( eraserIndex < erasersCount ) { - setTimeout( doNextErasure( eraserIndex + 1, 1 ) ); - } else { - onErasureDoneSuccess(); - } - } - }).fail( function() { - onErasureFailure(); - }); - } - - // And now, let's begin - setActionState( $action, 'remove-personal-data-processing' ); - - doNextErasure( 1, 1 ); - }); - - // Privacy policy page, copy button. - $( document ).on( 'click', function( event ) { - var $target = $( event.target ); - var $parent, $container, range; - - if ( $target.is( 'button.privacy-text-copy' ) ) { - $parent = $target.parent().parent(); - $container = $parent.find( 'div.wp-suggested-text' ); - - if ( ! $container.length ) { - $container = $parent.find( 'div.policy-text' ); - } - - if ( $container.length ) { - try { - window.getSelection().removeAllRanges(); - range = document.createRange(); - $container.addClass( 'hide-privacy-policy-tutorial' ); - - range.selectNodeContents( $container[0] ); - window.getSelection().addRange( range ); - document.execCommand( 'copy' ); - - $container.removeClass( 'hide-privacy-policy-tutorial' ); - window.getSelection().removeAllRanges(); - } catch ( er ) {} - } - } - }); -}); - diff --git a/srcs/wordpress/wp-admin/js/privacy-tools.min.js b/srcs/wordpress/wp-admin/js/privacy-tools.min.js deleted file mode 100644 index 5d1e658..0000000 --- a/srcs/wordpress/wp-admin/js/privacy-tools.min.js +++ /dev/null @@ -1 +0,0 @@ -jQuery(document).ready(function(v){var f=window.privacyToolsL10n||{};function h(e,t){e.children().addClass("hidden"),e.children("."+t).removeClass("hidden")}function g(e){e.removeClass("has-request-results"),e.next().hasClass("request-results")&&e.next().remove()}function x(e,t,a,n){var o="",s="request-results";g(e),n.length&&(v.each(n,function(e,t){o=o+"<li>"+t+"</li>"}),o="<ul>"+o+"</ul>"),e.addClass("has-request-results"),e.hasClass("status-request-confirmed")&&(s+=" status-request-confirmed"),e.hasClass("status-request-failed")&&(s+=" status-request-failed"),e.after(function(){return'<tr class="'+s+'"><th colspan="5"><div class="notice inline notice-alt '+t+'"><p>'+a+"</p>"+o+"</div></td></tr>"})}v(".export-personal-data-handle").click(function(e){var s=v(this),r=s.parents(".export-personal-data"),i=s.parents("tr"),t=r.data("request-id"),d=r.data("nonce"),c=r.data("exporters-count"),l=!!r.data("send-as-email");function u(e){h(r,"export-personal-data-failed"),e&&x(i,"notice-error",f.exportError,[e])}e.preventDefault(),e.stopPropagation(),r.blur(),g(i),h(r,"export-personal-data-processing"),function a(n,o){v.ajax({url:window.ajaxurl,data:{action:"wp-privacy-export-personal-data",exporter:n,id:t,page:o,security:d,sendAsEmail:l},method:"post"}).done(function(e){var t=e.data;e.success?t.done?n<c?setTimeout(a(n+1,1)):function(e){var t=f.emailSent;h(r,"export-personal-data-success"),x(i,"notice-success",t,[]),s.hide(),void 0!==e?window.location=e:l||u(f.noExportFile)}(t.url):setTimeout(a(n,o+1)):u(e.data)}).fail(function(e,t,a){u(a)})}(1,1)}),v(".remove-personal-data-handle").click(function(e){var s=v(this),r=s.parents(".remove-personal-data"),i=s.parents("tr"),t=r.data("request-id"),d=r.data("nonce"),c=r.data("erasers-count"),l=!1,u=!1,p=[];function m(){h(r,"remove-personal-data-failed"),x(i,"notice-error",f.removalError,[])}e.stopPropagation(),r.blur(),g(i),h(r,"remove-personal-data-processing"),function a(n,o){v.ajax({url:window.ajaxurl,data:{action:"wp-privacy-erase-personal-data",eraser:n,id:t,page:o,security:d},method:"post"}).done(function(e){var t=e.data;e.success?(t.items_removed&&(l=l||t.items_removed),t.items_retained&&(u=u||t.items_retained),t.messages&&(p=p.concat(t.messages)),t.done?n<c?setTimeout(a(n+1,1)):function(){var e=f.noDataFound,t="notice-success";h(r,"remove-personal-data-success"),!1===l?!1===u?e=f.noDataFound:(e=f.noneRemoved,t="notice-warning"):!1===u?e=f.foundAndRemoved:(e=f.someNotRemoved,t="notice-warning"),x(i,t,e,p),s.hide()}():setTimeout(a(n,o+1))):m()}).fail(function(){m()})}(1,1)}),v(document).on("click",function(e){var t,a,n,o=v(e.target);if(o.is("button.privacy-text-copy")&&((a=(t=o.parent().parent()).find("div.wp-suggested-text")).length||(a=t.find("div.policy-text")),a.length))try{window.getSelection().removeAllRanges(),n=document.createRange(),a.addClass("hide-privacy-policy-tutorial"),n.selectNodeContents(a[0]),window.getSelection().addRange(n),document.execCommand("copy"),a.removeClass("hide-privacy-policy-tutorial"),window.getSelection().removeAllRanges()}catch(e){}})});
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/revisions.js b/srcs/wordpress/wp-admin/js/revisions.js deleted file mode 100644 index adf5865..0000000 --- a/srcs/wordpress/wp-admin/js/revisions.js +++ /dev/null @@ -1,1171 +0,0 @@ -/** - * @file Revisions interface functions, Backbone classes and - * the revisions.php document.ready bootstrap. - * - * @output wp-admin/js/revisions.js - */ - -/* global isRtl */ - -window.wp = window.wp || {}; - -(function($) { - var revisions; - /** - * Expose the module in window.wp.revisions. - */ - revisions = wp.revisions = { model: {}, view: {}, controller: {} }; - - // Link post revisions data served from the back end. - revisions.settings = window._wpRevisionsSettings || {}; - - // For debugging - revisions.debug = false; - - /** - * wp.revisions.log - * - * A debugging utility for revisions. Works only when a - * debug flag is on and the browser supports it. - */ - revisions.log = function() { - if ( window.console && revisions.debug ) { - window.console.log.apply( window.console, arguments ); - } - }; - - // Handy functions to help with positioning - $.fn.allOffsets = function() { - var offset = this.offset() || {top: 0, left: 0}, win = $(window); - return _.extend( offset, { - right: win.width() - offset.left - this.outerWidth(), - bottom: win.height() - offset.top - this.outerHeight() - }); - }; - - $.fn.allPositions = function() { - var position = this.position() || {top: 0, left: 0}, parent = this.parent(); - return _.extend( position, { - right: parent.outerWidth() - position.left - this.outerWidth(), - bottom: parent.outerHeight() - position.top - this.outerHeight() - }); - }; - - /** - * ======================================================================== - * MODELS - * ======================================================================== - */ - revisions.model.Slider = Backbone.Model.extend({ - defaults: { - value: null, - values: null, - min: 0, - max: 1, - step: 1, - range: false, - compareTwoMode: false - }, - - initialize: function( options ) { - this.frame = options.frame; - this.revisions = options.revisions; - - // Listen for changes to the revisions or mode from outside - this.listenTo( this.frame, 'update:revisions', this.receiveRevisions ); - this.listenTo( this.frame, 'change:compareTwoMode', this.updateMode ); - - // Listen for internal changes - this.on( 'change:from', this.handleLocalChanges ); - this.on( 'change:to', this.handleLocalChanges ); - this.on( 'change:compareTwoMode', this.updateSliderSettings ); - this.on( 'update:revisions', this.updateSliderSettings ); - - // Listen for changes to the hovered revision - this.on( 'change:hoveredRevision', this.hoverRevision ); - - this.set({ - max: this.revisions.length - 1, - compareTwoMode: this.frame.get('compareTwoMode'), - from: this.frame.get('from'), - to: this.frame.get('to') - }); - this.updateSliderSettings(); - }, - - getSliderValue: function( a, b ) { - return isRtl ? this.revisions.length - this.revisions.indexOf( this.get(a) ) - 1 : this.revisions.indexOf( this.get(b) ); - }, - - updateSliderSettings: function() { - if ( this.get('compareTwoMode') ) { - this.set({ - values: [ - this.getSliderValue( 'to', 'from' ), - this.getSliderValue( 'from', 'to' ) - ], - value: null, - range: true // ensures handles cannot cross - }); - } else { - this.set({ - value: this.getSliderValue( 'to', 'to' ), - values: null, - range: false - }); - } - this.trigger( 'update:slider' ); - }, - - // Called when a revision is hovered - hoverRevision: function( model, value ) { - this.trigger( 'hovered:revision', value ); - }, - - // Called when `compareTwoMode` changes - updateMode: function( model, value ) { - this.set({ compareTwoMode: value }); - }, - - // Called when `from` or `to` changes in the local model - handleLocalChanges: function() { - this.frame.set({ - from: this.get('from'), - to: this.get('to') - }); - }, - - // Receives revisions changes from outside the model - receiveRevisions: function( from, to ) { - // Bail if nothing changed - if ( this.get('from') === from && this.get('to') === to ) { - return; - } - - this.set({ from: from, to: to }, { silent: true }); - this.trigger( 'update:revisions', from, to ); - } - - }); - - revisions.model.Tooltip = Backbone.Model.extend({ - defaults: { - revision: null, - offset: {}, - hovering: false, // Whether the mouse is hovering - scrubbing: false // Whether the mouse is scrubbing - }, - - initialize: function( options ) { - this.frame = options.frame; - this.revisions = options.revisions; - this.slider = options.slider; - - this.listenTo( this.slider, 'hovered:revision', this.updateRevision ); - this.listenTo( this.slider, 'change:hovering', this.setHovering ); - this.listenTo( this.slider, 'change:scrubbing', this.setScrubbing ); - }, - - - updateRevision: function( revision ) { - this.set({ revision: revision }); - }, - - setHovering: function( model, value ) { - this.set({ hovering: value }); - }, - - setScrubbing: function( model, value ) { - this.set({ scrubbing: value }); - } - }); - - revisions.model.Revision = Backbone.Model.extend({}); - - /** - * wp.revisions.model.Revisions - * - * A collection of post revisions. - */ - revisions.model.Revisions = Backbone.Collection.extend({ - model: revisions.model.Revision, - - initialize: function() { - _.bindAll( this, 'next', 'prev' ); - }, - - next: function( revision ) { - var index = this.indexOf( revision ); - - if ( index !== -1 && index !== this.length - 1 ) { - return this.at( index + 1 ); - } - }, - - prev: function( revision ) { - var index = this.indexOf( revision ); - - if ( index !== -1 && index !== 0 ) { - return this.at( index - 1 ); - } - } - }); - - revisions.model.Field = Backbone.Model.extend({}); - - revisions.model.Fields = Backbone.Collection.extend({ - model: revisions.model.Field - }); - - revisions.model.Diff = Backbone.Model.extend({ - initialize: function() { - var fields = this.get('fields'); - this.unset('fields'); - - this.fields = new revisions.model.Fields( fields ); - } - }); - - revisions.model.Diffs = Backbone.Collection.extend({ - initialize: function( models, options ) { - _.bindAll( this, 'getClosestUnloaded' ); - this.loadAll = _.once( this._loadAll ); - this.revisions = options.revisions; - this.postId = options.postId; - this.requests = {}; - }, - - model: revisions.model.Diff, - - ensure: function( id, context ) { - var diff = this.get( id ), - request = this.requests[ id ], - deferred = $.Deferred(), - ids = {}, - from = id.split(':')[0], - to = id.split(':')[1]; - ids[id] = true; - - wp.revisions.log( 'ensure', id ); - - this.trigger( 'ensure', ids, from, to, deferred.promise() ); - - if ( diff ) { - deferred.resolveWith( context, [ diff ] ); - } else { - this.trigger( 'ensure:load', ids, from, to, deferred.promise() ); - _.each( ids, _.bind( function( id ) { - // Remove anything that has an ongoing request - if ( this.requests[ id ] ) { - delete ids[ id ]; - } - // Remove anything we already have - if ( this.get( id ) ) { - delete ids[ id ]; - } - }, this ) ); - if ( ! request ) { - // Always include the ID that started this ensure - ids[ id ] = true; - request = this.load( _.keys( ids ) ); - } - - request.done( _.bind( function() { - deferred.resolveWith( context, [ this.get( id ) ] ); - }, this ) ).fail( _.bind( function() { - deferred.reject(); - }) ); - } - - return deferred.promise(); - }, - - // Returns an array of proximal diffs - getClosestUnloaded: function( ids, centerId ) { - var self = this; - return _.chain([0].concat( ids )).initial().zip( ids ).sortBy( function( pair ) { - return Math.abs( centerId - pair[1] ); - }).map( function( pair ) { - return pair.join(':'); - }).filter( function( diffId ) { - return _.isUndefined( self.get( diffId ) ) && ! self.requests[ diffId ]; - }).value(); - }, - - _loadAll: function( allRevisionIds, centerId, num ) { - var self = this, deferred = $.Deferred(), - diffs = _.first( this.getClosestUnloaded( allRevisionIds, centerId ), num ); - if ( _.size( diffs ) > 0 ) { - this.load( diffs ).done( function() { - self._loadAll( allRevisionIds, centerId, num ).done( function() { - deferred.resolve(); - }); - }).fail( function() { - if ( 1 === num ) { // Already tried 1. This just isn't working. Give up. - deferred.reject(); - } else { // Request fewer diffs this time - self._loadAll( allRevisionIds, centerId, Math.ceil( num / 2 ) ).done( function() { - deferred.resolve(); - }); - } - }); - } else { - deferred.resolve(); - } - return deferred; - }, - - load: function( comparisons ) { - wp.revisions.log( 'load', comparisons ); - // Our collection should only ever grow, never shrink, so remove: false - return this.fetch({ data: { compare: comparisons }, remove: false }).done( function() { - wp.revisions.log( 'load:complete', comparisons ); - }); - }, - - sync: function( method, model, options ) { - if ( 'read' === method ) { - options = options || {}; - options.context = this; - options.data = _.extend( options.data || {}, { - action: 'get-revision-diffs', - post_id: this.postId - }); - - var deferred = wp.ajax.send( options ), - requests = this.requests; - - // Record that we're requesting each diff. - if ( options.data.compare ) { - _.each( options.data.compare, function( id ) { - requests[ id ] = deferred; - }); - } - - // When the request completes, clear the stored request. - deferred.always( function() { - if ( options.data.compare ) { - _.each( options.data.compare, function( id ) { - delete requests[ id ]; - }); - } - }); - - return deferred; - - // Otherwise, fall back to `Backbone.sync()`. - } else { - return Backbone.Model.prototype.sync.apply( this, arguments ); - } - } - }); - - - /** - * wp.revisions.model.FrameState - * - * The frame state. - * - * @see wp.revisions.view.Frame - * - * @param {object} attributes Model attributes - none are required. - * @param {object} options Options for the model. - * @param {revisions.model.Revisions} options.revisions A collection of revisions. - */ - revisions.model.FrameState = Backbone.Model.extend({ - defaults: { - loading: false, - error: false, - compareTwoMode: false - }, - - initialize: function( attributes, options ) { - var state = this.get( 'initialDiffState' ); - _.bindAll( this, 'receiveDiff' ); - this._debouncedEnsureDiff = _.debounce( this._ensureDiff, 200 ); - - this.revisions = options.revisions; - - this.diffs = new revisions.model.Diffs( [], { - revisions: this.revisions, - postId: this.get( 'postId' ) - } ); - - // Set the initial diffs collection. - this.diffs.set( this.get( 'diffData' ) ); - - // Set up internal listeners - this.listenTo( this, 'change:from', this.changeRevisionHandler ); - this.listenTo( this, 'change:to', this.changeRevisionHandler ); - this.listenTo( this, 'change:compareTwoMode', this.changeMode ); - this.listenTo( this, 'update:revisions', this.updatedRevisions ); - this.listenTo( this.diffs, 'ensure:load', this.updateLoadingStatus ); - this.listenTo( this, 'update:diff', this.updateLoadingStatus ); - - // Set the initial revisions, baseUrl, and mode as provided through attributes. - - this.set( { - to : this.revisions.get( state.to ), - from : this.revisions.get( state.from ), - compareTwoMode : state.compareTwoMode - } ); - - // Start the router if browser supports History API - if ( window.history && window.history.pushState ) { - this.router = new revisions.Router({ model: this }); - if ( Backbone.History.started ) { - Backbone.history.stop(); - } - Backbone.history.start({ pushState: true }); - } - }, - - updateLoadingStatus: function() { - this.set( 'error', false ); - this.set( 'loading', ! this.diff() ); - }, - - changeMode: function( model, value ) { - var toIndex = this.revisions.indexOf( this.get( 'to' ) ); - - // If we were on the first revision before switching to two-handled mode, - // bump the 'to' position over one - if ( value && 0 === toIndex ) { - this.set({ - from: this.revisions.at( toIndex ), - to: this.revisions.at( toIndex + 1 ) - }); - } - - // When switching back to single-handled mode, reset 'from' model to - // one position before the 'to' model - if ( ! value && 0 !== toIndex ) { // '! value' means switching to single-handled mode - this.set({ - from: this.revisions.at( toIndex - 1 ), - to: this.revisions.at( toIndex ) - }); - } - }, - - updatedRevisions: function( from, to ) { - if ( this.get( 'compareTwoMode' ) ) { - // TODO: compare-two loading strategy - } else { - this.diffs.loadAll( this.revisions.pluck('id'), to.id, 40 ); - } - }, - - // Fetch the currently loaded diff. - diff: function() { - return this.diffs.get( this._diffId ); - }, - - // So long as `from` and `to` are changed at the same time, the diff - // will only be updated once. This is because Backbone updates all of - // the changed attributes in `set`, and then fires the `change` events. - updateDiff: function( options ) { - var from, to, diffId, diff; - - options = options || {}; - from = this.get('from'); - to = this.get('to'); - diffId = ( from ? from.id : 0 ) + ':' + to.id; - - // Check if we're actually changing the diff id. - if ( this._diffId === diffId ) { - return $.Deferred().reject().promise(); - } - - this._diffId = diffId; - this.trigger( 'update:revisions', from, to ); - - diff = this.diffs.get( diffId ); - - // If we already have the diff, then immediately trigger the update. - if ( diff ) { - this.receiveDiff( diff ); - return $.Deferred().resolve().promise(); - // Otherwise, fetch the diff. - } else { - if ( options.immediate ) { - return this._ensureDiff(); - } else { - this._debouncedEnsureDiff(); - return $.Deferred().reject().promise(); - } - } - }, - - // A simple wrapper around `updateDiff` to prevent the change event's - // parameters from being passed through. - changeRevisionHandler: function() { - this.updateDiff(); - }, - - receiveDiff: function( diff ) { - // Did we actually get a diff? - if ( _.isUndefined( diff ) || _.isUndefined( diff.id ) ) { - this.set({ - loading: false, - error: true - }); - } else if ( this._diffId === diff.id ) { // Make sure the current diff didn't change - this.trigger( 'update:diff', diff ); - } - }, - - _ensureDiff: function() { - return this.diffs.ensure( this._diffId, this ).always( this.receiveDiff ); - } - }); - - - /** - * ======================================================================== - * VIEWS - * ======================================================================== - */ - - /** - * wp.revisions.view.Frame - * - * Top level frame that orchestrates the revisions experience. - * - * @param {object} options The options hash for the view. - * @param {revisions.model.FrameState} options.model The frame state model. - */ - revisions.view.Frame = wp.Backbone.View.extend({ - className: 'revisions', - template: wp.template('revisions-frame'), - - initialize: function() { - this.listenTo( this.model, 'update:diff', this.renderDiff ); - this.listenTo( this.model, 'change:compareTwoMode', this.updateCompareTwoMode ); - this.listenTo( this.model, 'change:loading', this.updateLoadingStatus ); - this.listenTo( this.model, 'change:error', this.updateErrorStatus ); - - this.views.set( '.revisions-control-frame', new revisions.view.Controls({ - model: this.model - }) ); - }, - - render: function() { - wp.Backbone.View.prototype.render.apply( this, arguments ); - - $('html').css( 'overflow-y', 'scroll' ); - $('#wpbody-content .wrap').append( this.el ); - this.updateCompareTwoMode(); - this.renderDiff( this.model.diff() ); - this.views.ready(); - - return this; - }, - - renderDiff: function( diff ) { - this.views.set( '.revisions-diff-frame', new revisions.view.Diff({ - model: diff - }) ); - }, - - updateLoadingStatus: function() { - this.$el.toggleClass( 'loading', this.model.get('loading') ); - }, - - updateErrorStatus: function() { - this.$el.toggleClass( 'diff-error', this.model.get('error') ); - }, - - updateCompareTwoMode: function() { - this.$el.toggleClass( 'comparing-two-revisions', this.model.get('compareTwoMode') ); - } - }); - - /** - * wp.revisions.view.Controls - * - * The controls view. - * - * Contains the revision slider, previous/next buttons, the meta info and the compare checkbox. - */ - revisions.view.Controls = wp.Backbone.View.extend({ - className: 'revisions-controls', - - initialize: function() { - _.bindAll( this, 'setWidth' ); - - // Add the button view - this.views.add( new revisions.view.Buttons({ - model: this.model - }) ); - - // Add the checkbox view - this.views.add( new revisions.view.Checkbox({ - model: this.model - }) ); - - // Prep the slider model - var slider = new revisions.model.Slider({ - frame: this.model, - revisions: this.model.revisions - }), - - // Prep the tooltip model - tooltip = new revisions.model.Tooltip({ - frame: this.model, - revisions: this.model.revisions, - slider: slider - }); - - // Add the tooltip view - this.views.add( new revisions.view.Tooltip({ - model: tooltip - }) ); - - // Add the tickmarks view - this.views.add( new revisions.view.Tickmarks({ - model: tooltip - }) ); - - // Add the slider view - this.views.add( new revisions.view.Slider({ - model: slider - }) ); - - // Add the Metabox view - this.views.add( new revisions.view.Metabox({ - model: this.model - }) ); - }, - - ready: function() { - this.top = this.$el.offset().top; - this.window = $(window); - this.window.on( 'scroll.wp.revisions', {controls: this}, function(e) { - var controls = e.data.controls, - container = controls.$el.parent(), - scrolled = controls.window.scrollTop(), - frame = controls.views.parent; - - if ( scrolled >= controls.top ) { - if ( ! frame.$el.hasClass('pinned') ) { - controls.setWidth(); - container.css('height', container.height() + 'px' ); - controls.window.on('resize.wp.revisions.pinning click.wp.revisions.pinning', {controls: controls}, function(e) { - e.data.controls.setWidth(); - }); - } - frame.$el.addClass('pinned'); - } else if ( frame.$el.hasClass('pinned') ) { - controls.window.off('.wp.revisions.pinning'); - controls.$el.css('width', 'auto'); - frame.$el.removeClass('pinned'); - container.css('height', 'auto'); - controls.top = controls.$el.offset().top; - } else { - controls.top = controls.$el.offset().top; - } - }); - }, - - setWidth: function() { - this.$el.css('width', this.$el.parent().width() + 'px'); - } - }); - - // The tickmarks view - revisions.view.Tickmarks = wp.Backbone.View.extend({ - className: 'revisions-tickmarks', - direction: isRtl ? 'right' : 'left', - - initialize: function() { - this.listenTo( this.model, 'change:revision', this.reportTickPosition ); - }, - - reportTickPosition: function( model, revision ) { - var offset, thisOffset, parentOffset, tick, index = this.model.revisions.indexOf( revision ); - thisOffset = this.$el.allOffsets(); - parentOffset = this.$el.parent().allOffsets(); - if ( index === this.model.revisions.length - 1 ) { - // Last one - offset = { - rightPlusWidth: thisOffset.left - parentOffset.left + 1, - leftPlusWidth: thisOffset.right - parentOffset.right + 1 - }; - } else { - // Normal tick - tick = this.$('div:nth-of-type(' + (index + 1) + ')'); - offset = tick.allPositions(); - _.extend( offset, { - left: offset.left + thisOffset.left - parentOffset.left, - right: offset.right + thisOffset.right - parentOffset.right - }); - _.extend( offset, { - leftPlusWidth: offset.left + tick.outerWidth(), - rightPlusWidth: offset.right + tick.outerWidth() - }); - } - this.model.set({ offset: offset }); - }, - - ready: function() { - var tickCount, tickWidth; - tickCount = this.model.revisions.length - 1; - tickWidth = 1 / tickCount; - this.$el.css('width', ( this.model.revisions.length * 50 ) + 'px'); - - _(tickCount).times( function( index ){ - this.$el.append( '<div style="' + this.direction + ': ' + ( 100 * tickWidth * index ) + '%"></div>' ); - }, this ); - } - }); - - // The metabox view - revisions.view.Metabox = wp.Backbone.View.extend({ - className: 'revisions-meta', - - initialize: function() { - // Add the 'from' view - this.views.add( new revisions.view.MetaFrom({ - model: this.model, - className: 'diff-meta diff-meta-from' - }) ); - - // Add the 'to' view - this.views.add( new revisions.view.MetaTo({ - model: this.model - }) ); - } - }); - - // The revision meta view (to be extended) - revisions.view.Meta = wp.Backbone.View.extend({ - template: wp.template('revisions-meta'), - - events: { - 'click .restore-revision': 'restoreRevision' - }, - - initialize: function() { - this.listenTo( this.model, 'update:revisions', this.render ); - }, - - prepare: function() { - return _.extend( this.model.toJSON()[this.type] || {}, { - type: this.type - }); - }, - - restoreRevision: function() { - document.location = this.model.get('to').attributes.restoreUrl; - } - }); - - // The revision meta 'from' view - revisions.view.MetaFrom = revisions.view.Meta.extend({ - className: 'diff-meta diff-meta-from', - type: 'from' - }); - - // The revision meta 'to' view - revisions.view.MetaTo = revisions.view.Meta.extend({ - className: 'diff-meta diff-meta-to', - type: 'to' - }); - - // The checkbox view. - revisions.view.Checkbox = wp.Backbone.View.extend({ - className: 'revisions-checkbox', - template: wp.template('revisions-checkbox'), - - events: { - 'click .compare-two-revisions': 'compareTwoToggle' - }, - - initialize: function() { - this.listenTo( this.model, 'change:compareTwoMode', this.updateCompareTwoMode ); - }, - - ready: function() { - if ( this.model.revisions.length < 3 ) { - $('.revision-toggle-compare-mode').hide(); - } - }, - - updateCompareTwoMode: function() { - this.$('.compare-two-revisions').prop( 'checked', this.model.get('compareTwoMode') ); - }, - - // Toggle the compare two mode feature when the compare two checkbox is checked. - compareTwoToggle: function() { - // Activate compare two mode? - this.model.set({ compareTwoMode: $('.compare-two-revisions').prop('checked') }); - } - }); - - // The tooltip view. - // Encapsulates the tooltip. - revisions.view.Tooltip = wp.Backbone.View.extend({ - className: 'revisions-tooltip', - template: wp.template('revisions-meta'), - - initialize: function() { - this.listenTo( this.model, 'change:offset', this.render ); - this.listenTo( this.model, 'change:hovering', this.toggleVisibility ); - this.listenTo( this.model, 'change:scrubbing', this.toggleVisibility ); - }, - - prepare: function() { - if ( _.isNull( this.model.get('revision') ) ) { - return; - } else { - return _.extend( { type: 'tooltip' }, { - attributes: this.model.get('revision').toJSON() - }); - } - }, - - render: function() { - var otherDirection, - direction, - directionVal, - flipped, - css = {}, - position = this.model.revisions.indexOf( this.model.get('revision') ) + 1; - - flipped = ( position / this.model.revisions.length ) > 0.5; - if ( isRtl ) { - direction = flipped ? 'left' : 'right'; - directionVal = flipped ? 'leftPlusWidth' : direction; - } else { - direction = flipped ? 'right' : 'left'; - directionVal = flipped ? 'rightPlusWidth' : direction; - } - otherDirection = 'right' === direction ? 'left': 'right'; - wp.Backbone.View.prototype.render.apply( this, arguments ); - css[direction] = this.model.get('offset')[directionVal] + 'px'; - css[otherDirection] = ''; - this.$el.toggleClass( 'flipped', flipped ).css( css ); - }, - - visible: function() { - return this.model.get( 'scrubbing' ) || this.model.get( 'hovering' ); - }, - - toggleVisibility: function() { - if ( this.visible() ) { - this.$el.stop().show().fadeTo( 100 - this.el.style.opacity * 100, 1 ); - } else { - this.$el.stop().fadeTo( this.el.style.opacity * 300, 0, function(){ $(this).hide(); } ); - } - return; - } - }); - - // The buttons view. - // Encapsulates all of the configuration for the previous/next buttons. - revisions.view.Buttons = wp.Backbone.View.extend({ - className: 'revisions-buttons', - template: wp.template('revisions-buttons'), - - events: { - 'click .revisions-next .button': 'nextRevision', - 'click .revisions-previous .button': 'previousRevision' - }, - - initialize: function() { - this.listenTo( this.model, 'update:revisions', this.disabledButtonCheck ); - }, - - ready: function() { - this.disabledButtonCheck(); - }, - - // Go to a specific model index - gotoModel: function( toIndex ) { - var attributes = { - to: this.model.revisions.at( toIndex ) - }; - // If we're at the first revision, unset 'from'. - if ( toIndex ) { - attributes.from = this.model.revisions.at( toIndex - 1 ); - } else { - this.model.unset('from', { silent: true }); - } - - this.model.set( attributes ); - }, - - // Go to the 'next' revision - nextRevision: function() { - var toIndex = this.model.revisions.indexOf( this.model.get('to') ) + 1; - this.gotoModel( toIndex ); - }, - - // Go to the 'previous' revision - previousRevision: function() { - var toIndex = this.model.revisions.indexOf( this.model.get('to') ) - 1; - this.gotoModel( toIndex ); - }, - - // Check to see if the Previous or Next buttons need to be disabled or enabled. - disabledButtonCheck: function() { - var maxVal = this.model.revisions.length - 1, - minVal = 0, - next = $('.revisions-next .button'), - previous = $('.revisions-previous .button'), - val = this.model.revisions.indexOf( this.model.get('to') ); - - // Disable "Next" button if you're on the last node. - next.prop( 'disabled', ( maxVal === val ) ); - - // Disable "Previous" button if you're on the first node. - previous.prop( 'disabled', ( minVal === val ) ); - } - }); - - - // The slider view. - revisions.view.Slider = wp.Backbone.View.extend({ - className: 'wp-slider', - direction: isRtl ? 'right' : 'left', - - events: { - 'mousemove' : 'mouseMove' - }, - - initialize: function() { - _.bindAll( this, 'start', 'slide', 'stop', 'mouseMove', 'mouseEnter', 'mouseLeave' ); - this.listenTo( this.model, 'update:slider', this.applySliderSettings ); - }, - - ready: function() { - this.$el.css('width', ( this.model.revisions.length * 50 ) + 'px'); - this.$el.slider( _.extend( this.model.toJSON(), { - start: this.start, - slide: this.slide, - stop: this.stop - }) ); - - this.$el.hoverIntent({ - over: this.mouseEnter, - out: this.mouseLeave, - timeout: 800 - }); - - this.applySliderSettings(); - }, - - mouseMove: function( e ) { - var zoneCount = this.model.revisions.length - 1, // One fewer zone than models - sliderFrom = this.$el.allOffsets()[this.direction], // "From" edge of slider - sliderWidth = this.$el.width(), // Width of slider - tickWidth = sliderWidth / zoneCount, // Calculated width of zone - actualX = ( isRtl ? $(window).width() - e.pageX : e.pageX ) - sliderFrom, // Flipped for RTL - sliderFrom; - currentModelIndex = Math.floor( ( actualX + ( tickWidth / 2 ) ) / tickWidth ); // Calculate the model index - - // Ensure sane value for currentModelIndex. - if ( currentModelIndex < 0 ) { - currentModelIndex = 0; - } else if ( currentModelIndex >= this.model.revisions.length ) { - currentModelIndex = this.model.revisions.length - 1; - } - - // Update the tooltip mode - this.model.set({ hoveredRevision: this.model.revisions.at( currentModelIndex ) }); - }, - - mouseLeave: function() { - this.model.set({ hovering: false }); - }, - - mouseEnter: function() { - this.model.set({ hovering: true }); - }, - - applySliderSettings: function() { - this.$el.slider( _.pick( this.model.toJSON(), 'value', 'values', 'range' ) ); - var handles = this.$('a.ui-slider-handle'); - - if ( this.model.get('compareTwoMode') ) { - // in RTL mode the 'left handle' is the second in the slider, 'right' is first - handles.first() - .toggleClass( 'to-handle', !! isRtl ) - .toggleClass( 'from-handle', ! isRtl ); - handles.last() - .toggleClass( 'from-handle', !! isRtl ) - .toggleClass( 'to-handle', ! isRtl ); - } else { - handles.removeClass('from-handle to-handle'); - } - }, - - start: function( event, ui ) { - this.model.set({ scrubbing: true }); - - // Track the mouse position to enable smooth dragging, - // overrides default jQuery UI step behavior. - $( window ).on( 'mousemove.wp.revisions', { view: this }, function( e ) { - var handles, - view = e.data.view, - leftDragBoundary = view.$el.offset().left, - sliderOffset = leftDragBoundary, - sliderRightEdge = leftDragBoundary + view.$el.width(), - rightDragBoundary = sliderRightEdge, - leftDragReset = '0', - rightDragReset = '100%', - handle = $( ui.handle ); - - // In two handle mode, ensure handles can't be dragged past each other. - // Adjust left/right boundaries and reset points. - if ( view.model.get('compareTwoMode') ) { - handles = handle.parent().find('.ui-slider-handle'); - if ( handle.is( handles.first() ) ) { // We're the left handle - rightDragBoundary = handles.last().offset().left; - rightDragReset = rightDragBoundary - sliderOffset; - } else { // We're the right handle - leftDragBoundary = handles.first().offset().left + handles.first().width(); - leftDragReset = leftDragBoundary - sliderOffset; - } - } - - // Follow mouse movements, as long as handle remains inside slider. - if ( e.pageX < leftDragBoundary ) { - handle.css( 'left', leftDragReset ); // Mouse to left of slider. - } else if ( e.pageX > rightDragBoundary ) { - handle.css( 'left', rightDragReset ); // Mouse to right of slider. - } else { - handle.css( 'left', e.pageX - sliderOffset ); // Mouse in slider. - } - } ); - }, - - getPosition: function( position ) { - return isRtl ? this.model.revisions.length - position - 1: position; - }, - - // Responds to slide events - slide: function( event, ui ) { - var attributes, movedRevision; - // Compare two revisions mode - if ( this.model.get('compareTwoMode') ) { - // Prevent sliders from occupying same spot - if ( ui.values[1] === ui.values[0] ) { - return false; - } - if ( isRtl ) { - ui.values.reverse(); - } - attributes = { - from: this.model.revisions.at( this.getPosition( ui.values[0] ) ), - to: this.model.revisions.at( this.getPosition( ui.values[1] ) ) - }; - } else { - attributes = { - to: this.model.revisions.at( this.getPosition( ui.value ) ) - }; - // If we're at the first revision, unset 'from'. - if ( this.getPosition( ui.value ) > 0 ) { - attributes.from = this.model.revisions.at( this.getPosition( ui.value ) - 1 ); - } else { - attributes.from = undefined; - } - } - movedRevision = this.model.revisions.at( this.getPosition( ui.value ) ); - - // If we are scrubbing, a scrub to a revision is considered a hover - if ( this.model.get('scrubbing') ) { - attributes.hoveredRevision = movedRevision; - } - - this.model.set( attributes ); - }, - - stop: function() { - $( window ).off('mousemove.wp.revisions'); - this.model.updateSliderSettings(); // To snap us back to a tick mark - this.model.set({ scrubbing: false }); - } - }); - - // The diff view. - // This is the view for the current active diff. - revisions.view.Diff = wp.Backbone.View.extend({ - className: 'revisions-diff', - template: wp.template('revisions-diff'), - - // Generate the options to be passed to the template. - prepare: function() { - return _.extend({ fields: this.model.fields.toJSON() }, this.options ); - } - }); - - // The revisions router. - // Maintains the URL routes so browser URL matches state. - revisions.Router = Backbone.Router.extend({ - initialize: function( options ) { - this.model = options.model; - - // Maintain state and history when navigating - this.listenTo( this.model, 'update:diff', _.debounce( this.updateUrl, 250 ) ); - this.listenTo( this.model, 'change:compareTwoMode', this.updateUrl ); - }, - - baseUrl: function( url ) { - return this.model.get('baseUrl') + url; - }, - - updateUrl: function() { - var from = this.model.has('from') ? this.model.get('from').id : 0, - to = this.model.get('to').id; - if ( this.model.get('compareTwoMode' ) ) { - this.navigate( this.baseUrl( '?from=' + from + '&to=' + to ), { replace: true } ); - } else { - this.navigate( this.baseUrl( '?revision=' + to ), { replace: true } ); - } - }, - - handleRoute: function( a, b ) { - var compareTwo = _.isUndefined( b ); - - if ( ! compareTwo ) { - b = this.model.revisions.get( a ); - a = this.model.revisions.prev( b ); - b = b ? b.id : 0; - a = a ? a.id : 0; - } - } - }); - - /** - * Initialize the revisions UI for revision.php. - */ - revisions.init = function() { - var state; - - // Bail if the current page is not revision.php. - if ( ! window.adminpage || 'revision-php' !== window.adminpage ) { - return; - } - - state = new revisions.model.FrameState({ - initialDiffState: { - // wp_localize_script doesn't stringifies ints, so cast them. - to: parseInt( revisions.settings.to, 10 ), - from: parseInt( revisions.settings.from, 10 ), - // wp_localize_script does not allow for top-level booleans so do a comparator here. - compareTwoMode: ( revisions.settings.compareTwoMode === '1' ) - }, - diffData: revisions.settings.diffData, - baseUrl: revisions.settings.baseUrl, - postId: parseInt( revisions.settings.postId, 10 ) - }, { - revisions: new revisions.model.Revisions( revisions.settings.revisionData ) - }); - - revisions.view.frame = new revisions.view.Frame({ - model: state - }).render(); - }; - - $( revisions.init ); -}(jQuery)); diff --git a/srcs/wordpress/wp-admin/js/revisions.min.js b/srcs/wordpress/wp-admin/js/revisions.min.js deleted file mode 100644 index e81e8a8..0000000 --- a/srcs/wordpress/wp-admin/js/revisions.min.js +++ /dev/null @@ -1 +0,0 @@ -window.wp=window.wp||{},function(h){var s;(s=wp.revisions={model:{},view:{},controller:{}}).settings=window._wpRevisionsSettings||{},s.debug=!1,s.log=function(){window.console&&s.debug&&window.console.log.apply(window.console,arguments)},h.fn.allOffsets=function(){var e=this.offset()||{top:0,left:0},i=h(window);return _.extend(e,{right:i.width()-e.left-this.outerWidth(),bottom:i.height()-e.top-this.outerHeight()})},h.fn.allPositions=function(){var e=this.position()||{top:0,left:0},i=this.parent();return _.extend(e,{right:i.outerWidth()-e.left-this.outerWidth(),bottom:i.outerHeight()-e.top-this.outerHeight()})},s.model.Slider=Backbone.Model.extend({defaults:{value:null,values:null,min:0,max:1,step:1,range:!1,compareTwoMode:!1},initialize:function(e){this.frame=e.frame,this.revisions=e.revisions,this.listenTo(this.frame,"update:revisions",this.receiveRevisions),this.listenTo(this.frame,"change:compareTwoMode",this.updateMode),this.on("change:from",this.handleLocalChanges),this.on("change:to",this.handleLocalChanges),this.on("change:compareTwoMode",this.updateSliderSettings),this.on("update:revisions",this.updateSliderSettings),this.on("change:hoveredRevision",this.hoverRevision),this.set({max:this.revisions.length-1,compareTwoMode:this.frame.get("compareTwoMode"),from:this.frame.get("from"),to:this.frame.get("to")}),this.updateSliderSettings()},getSliderValue:function(e,i){return isRtl?this.revisions.length-this.revisions.indexOf(this.get(e))-1:this.revisions.indexOf(this.get(i))},updateSliderSettings:function(){this.get("compareTwoMode")?this.set({values:[this.getSliderValue("to","from"),this.getSliderValue("from","to")],value:null,range:!0}):this.set({value:this.getSliderValue("to","to"),values:null,range:!1}),this.trigger("update:slider")},hoverRevision:function(e,i){this.trigger("hovered:revision",i)},updateMode:function(e,i){this.set({compareTwoMode:i})},handleLocalChanges:function(){this.frame.set({from:this.get("from"),to:this.get("to")})},receiveRevisions:function(e,i){this.get("from")===e&&this.get("to")===i||(this.set({from:e,to:i},{silent:!0}),this.trigger("update:revisions",e,i))}}),s.model.Tooltip=Backbone.Model.extend({defaults:{revision:null,offset:{},hovering:!1,scrubbing:!1},initialize:function(e){this.frame=e.frame,this.revisions=e.revisions,this.slider=e.slider,this.listenTo(this.slider,"hovered:revision",this.updateRevision),this.listenTo(this.slider,"change:hovering",this.setHovering),this.listenTo(this.slider,"change:scrubbing",this.setScrubbing)},updateRevision:function(e){this.set({revision:e})},setHovering:function(e,i){this.set({hovering:i})},setScrubbing:function(e,i){this.set({scrubbing:i})}}),s.model.Revision=Backbone.Model.extend({}),s.model.Revisions=Backbone.Collection.extend({model:s.model.Revision,initialize:function(){_.bindAll(this,"next","prev")},next:function(e){var i=this.indexOf(e);if(-1!==i&&i!==this.length-1)return this.at(i+1)},prev:function(e){var i=this.indexOf(e);if(-1!==i&&0!==i)return this.at(i-1)}}),s.model.Field=Backbone.Model.extend({}),s.model.Fields=Backbone.Collection.extend({model:s.model.Field}),s.model.Diff=Backbone.Model.extend({initialize:function(){var e=this.get("fields");this.unset("fields"),this.fields=new s.model.Fields(e)}}),s.model.Diffs=Backbone.Collection.extend({initialize:function(e,i){_.bindAll(this,"getClosestUnloaded"),this.loadAll=_.once(this._loadAll),this.revisions=i.revisions,this.postId=i.postId,this.requests={}},model:s.model.Diff,ensure:function(e,i){var t=this.get(e),s=this.requests[e],o=h.Deferred(),n={},r=e.split(":")[0],l=e.split(":")[1];return n[e]=!0,wp.revisions.log("ensure",e),this.trigger("ensure",n,r,l,o.promise()),t?o.resolveWith(i,[t]):(this.trigger("ensure:load",n,r,l,o.promise()),_.each(n,_.bind(function(e){this.requests[e]&&delete n[e],this.get(e)&&delete n[e]},this)),s||(n[e]=!0,s=this.load(_.keys(n))),s.done(_.bind(function(){o.resolveWith(i,[this.get(e)])},this)).fail(_.bind(function(){o.reject()}))),o.promise()},getClosestUnloaded:function(e,i){var t=this;return _.chain([0].concat(e)).initial().zip(e).sortBy(function(e){return Math.abs(i-e[1])}).map(function(e){return e.join(":")}).filter(function(e){return _.isUndefined(t.get(e))&&!t.requests[e]}).value()},_loadAll:function(e,i,t){var s=this,o=h.Deferred(),n=_.first(this.getClosestUnloaded(e,i),t);return 0<_.size(n)?this.load(n).done(function(){s._loadAll(e,i,t).done(function(){o.resolve()})}).fail(function(){1===t?o.reject():s._loadAll(e,i,Math.ceil(t/2)).done(function(){o.resolve()})}):o.resolve(),o},load:function(e){return wp.revisions.log("load",e),this.fetch({data:{compare:e},remove:!1}).done(function(){wp.revisions.log("load:complete",e)})},sync:function(e,i,t){if("read"!==e)return Backbone.Model.prototype.sync.apply(this,arguments);(t=t||{}).context=this,t.data=_.extend(t.data||{},{action:"get-revision-diffs",post_id:this.postId});var s=wp.ajax.send(t),o=this.requests;return t.data.compare&&_.each(t.data.compare,function(e){o[e]=s}),s.always(function(){t.data.compare&&_.each(t.data.compare,function(e){delete o[e]})}),s}}),s.model.FrameState=Backbone.Model.extend({defaults:{loading:!1,error:!1,compareTwoMode:!1},initialize:function(e,i){var t=this.get("initialDiffState");_.bindAll(this,"receiveDiff"),this._debouncedEnsureDiff=_.debounce(this._ensureDiff,200),this.revisions=i.revisions,this.diffs=new s.model.Diffs([],{revisions:this.revisions,postId:this.get("postId")}),this.diffs.set(this.get("diffData")),this.listenTo(this,"change:from",this.changeRevisionHandler),this.listenTo(this,"change:to",this.changeRevisionHandler),this.listenTo(this,"change:compareTwoMode",this.changeMode),this.listenTo(this,"update:revisions",this.updatedRevisions),this.listenTo(this.diffs,"ensure:load",this.updateLoadingStatus),this.listenTo(this,"update:diff",this.updateLoadingStatus),this.set({to:this.revisions.get(t.to),from:this.revisions.get(t.from),compareTwoMode:t.compareTwoMode}),window.history&&window.history.pushState&&(this.router=new s.Router({model:this}),Backbone.History.started&&Backbone.history.stop(),Backbone.history.start({pushState:!0}))},updateLoadingStatus:function(){this.set("error",!1),this.set("loading",!this.diff())},changeMode:function(e,i){var t=this.revisions.indexOf(this.get("to"));i&&0===t&&this.set({from:this.revisions.at(t),to:this.revisions.at(t+1)}),i||0===t||this.set({from:this.revisions.at(t-1),to:this.revisions.at(t)})},updatedRevisions:function(e,i){this.get("compareTwoMode")||this.diffs.loadAll(this.revisions.pluck("id"),i.id,40)},diff:function(){return this.diffs.get(this._diffId)},updateDiff:function(e){var i,t,s,o;return e=e||{},i=this.get("from"),t=this.get("to"),s=(i?i.id:0)+":"+t.id,this._diffId===s?h.Deferred().reject().promise():(this._diffId=s,this.trigger("update:revisions",i,t),(o=this.diffs.get(s))?(this.receiveDiff(o),h.Deferred().resolve().promise()):e.immediate?this._ensureDiff():(this._debouncedEnsureDiff(),h.Deferred().reject().promise()))},changeRevisionHandler:function(){this.updateDiff()},receiveDiff:function(e){_.isUndefined(e)||_.isUndefined(e.id)?this.set({loading:!1,error:!0}):this._diffId===e.id&&this.trigger("update:diff",e)},_ensureDiff:function(){return this.diffs.ensure(this._diffId,this).always(this.receiveDiff)}}),s.view.Frame=wp.Backbone.View.extend({className:"revisions",template:wp.template("revisions-frame"),initialize:function(){this.listenTo(this.model,"update:diff",this.renderDiff),this.listenTo(this.model,"change:compareTwoMode",this.updateCompareTwoMode),this.listenTo(this.model,"change:loading",this.updateLoadingStatus),this.listenTo(this.model,"change:error",this.updateErrorStatus),this.views.set(".revisions-control-frame",new s.view.Controls({model:this.model}))},render:function(){return wp.Backbone.View.prototype.render.apply(this,arguments),h("html").css("overflow-y","scroll"),h("#wpbody-content .wrap").append(this.el),this.updateCompareTwoMode(),this.renderDiff(this.model.diff()),this.views.ready(),this},renderDiff:function(e){this.views.set(".revisions-diff-frame",new s.view.Diff({model:e}))},updateLoadingStatus:function(){this.$el.toggleClass("loading",this.model.get("loading"))},updateErrorStatus:function(){this.$el.toggleClass("diff-error",this.model.get("error"))},updateCompareTwoMode:function(){this.$el.toggleClass("comparing-two-revisions",this.model.get("compareTwoMode"))}}),s.view.Controls=wp.Backbone.View.extend({className:"revisions-controls",initialize:function(){_.bindAll(this,"setWidth"),this.views.add(new s.view.Buttons({model:this.model})),this.views.add(new s.view.Checkbox({model:this.model}));var e=new s.model.Slider({frame:this.model,revisions:this.model.revisions}),i=new s.model.Tooltip({frame:this.model,revisions:this.model.revisions,slider:e});this.views.add(new s.view.Tooltip({model:i})),this.views.add(new s.view.Tickmarks({model:i})),this.views.add(new s.view.Slider({model:e})),this.views.add(new s.view.Metabox({model:this.model}))},ready:function(){this.top=this.$el.offset().top,this.window=h(window),this.window.on("scroll.wp.revisions",{controls:this},function(e){var i=e.data.controls,t=i.$el.parent(),s=i.window.scrollTop(),o=i.views.parent;s>=i.top?(o.$el.hasClass("pinned")||(i.setWidth(),t.css("height",t.height()+"px"),i.window.on("resize.wp.revisions.pinning click.wp.revisions.pinning",{controls:i},function(e){e.data.controls.setWidth()})),o.$el.addClass("pinned")):(o.$el.hasClass("pinned")&&(i.window.off(".wp.revisions.pinning"),i.$el.css("width","auto"),o.$el.removeClass("pinned"),t.css("height","auto")),i.top=i.$el.offset().top)})},setWidth:function(){this.$el.css("width",this.$el.parent().width()+"px")}}),s.view.Tickmarks=wp.Backbone.View.extend({className:"revisions-tickmarks",direction:isRtl?"right":"left",initialize:function(){this.listenTo(this.model,"change:revision",this.reportTickPosition)},reportTickPosition:function(e,i){var t,s,o,n,r=this.model.revisions.indexOf(i);s=this.$el.allOffsets(),o=this.$el.parent().allOffsets(),r===this.model.revisions.length-1?t={rightPlusWidth:s.left-o.left+1,leftPlusWidth:s.right-o.right+1}:(t=(n=this.$("div:nth-of-type("+(r+1)+")")).allPositions(),_.extend(t,{left:t.left+s.left-o.left,right:t.right+s.right-o.right}),_.extend(t,{leftPlusWidth:t.left+n.outerWidth(),rightPlusWidth:t.right+n.outerWidth()})),this.model.set({offset:t})},ready:function(){var e,i;e=this.model.revisions.length-1,i=1/e,this.$el.css("width",50*this.model.revisions.length+"px"),_(e).times(function(e){this.$el.append('<div style="'+this.direction+": "+100*i*e+'%"></div>')},this)}}),s.view.Metabox=wp.Backbone.View.extend({className:"revisions-meta",initialize:function(){this.views.add(new s.view.MetaFrom({model:this.model,className:"diff-meta diff-meta-from"})),this.views.add(new s.view.MetaTo({model:this.model}))}}),s.view.Meta=wp.Backbone.View.extend({template:wp.template("revisions-meta"),events:{"click .restore-revision":"restoreRevision"},initialize:function(){this.listenTo(this.model,"update:revisions",this.render)},prepare:function(){return _.extend(this.model.toJSON()[this.type]||{},{type:this.type})},restoreRevision:function(){document.location=this.model.get("to").attributes.restoreUrl}}),s.view.MetaFrom=s.view.Meta.extend({className:"diff-meta diff-meta-from",type:"from"}),s.view.MetaTo=s.view.Meta.extend({className:"diff-meta diff-meta-to",type:"to"}),s.view.Checkbox=wp.Backbone.View.extend({className:"revisions-checkbox",template:wp.template("revisions-checkbox"),events:{"click .compare-two-revisions":"compareTwoToggle"},initialize:function(){this.listenTo(this.model,"change:compareTwoMode",this.updateCompareTwoMode)},ready:function(){this.model.revisions.length<3&&h(".revision-toggle-compare-mode").hide()},updateCompareTwoMode:function(){this.$(".compare-two-revisions").prop("checked",this.model.get("compareTwoMode"))},compareTwoToggle:function(){this.model.set({compareTwoMode:h(".compare-two-revisions").prop("checked")})}}),s.view.Tooltip=wp.Backbone.View.extend({className:"revisions-tooltip",template:wp.template("revisions-meta"),initialize:function(){this.listenTo(this.model,"change:offset",this.render),this.listenTo(this.model,"change:hovering",this.toggleVisibility),this.listenTo(this.model,"change:scrubbing",this.toggleVisibility)},prepare:function(){return _.isNull(this.model.get("revision"))?void 0:_.extend({type:"tooltip"},{attributes:this.model.get("revision").toJSON()})},render:function(){var e,i,t,s,o={};s=.5<(this.model.revisions.indexOf(this.model.get("revision"))+1)/this.model.revisions.length,t=isRtl?(i=s?"left":"right",s?"leftPlusWidth":i):(i=s?"right":"left",s?"rightPlusWidth":i),e="right"===i?"left":"right",wp.Backbone.View.prototype.render.apply(this,arguments),o[i]=this.model.get("offset")[t]+"px",o[e]="",this.$el.toggleClass("flipped",s).css(o)},visible:function(){return this.model.get("scrubbing")||this.model.get("hovering")},toggleVisibility:function(){this.visible()?this.$el.stop().show().fadeTo(100-100*this.el.style.opacity,1):this.$el.stop().fadeTo(300*this.el.style.opacity,0,function(){h(this).hide()})}}),s.view.Buttons=wp.Backbone.View.extend({className:"revisions-buttons",template:wp.template("revisions-buttons"),events:{"click .revisions-next .button":"nextRevision","click .revisions-previous .button":"previousRevision"},initialize:function(){this.listenTo(this.model,"update:revisions",this.disabledButtonCheck)},ready:function(){this.disabledButtonCheck()},gotoModel:function(e){var i={to:this.model.revisions.at(e)};e?i.from=this.model.revisions.at(e-1):this.model.unset("from",{silent:!0}),this.model.set(i)},nextRevision:function(){var e=this.model.revisions.indexOf(this.model.get("to"))+1;this.gotoModel(e)},previousRevision:function(){var e=this.model.revisions.indexOf(this.model.get("to"))-1;this.gotoModel(e)},disabledButtonCheck:function(){var e=this.model.revisions.length-1,i=h(".revisions-next .button"),t=h(".revisions-previous .button"),s=this.model.revisions.indexOf(this.model.get("to"));i.prop("disabled",e===s),t.prop("disabled",0===s)}}),s.view.Slider=wp.Backbone.View.extend({className:"wp-slider",direction:isRtl?"right":"left",events:{mousemove:"mouseMove"},initialize:function(){_.bindAll(this,"start","slide","stop","mouseMove","mouseEnter","mouseLeave"),this.listenTo(this.model,"update:slider",this.applySliderSettings)},ready:function(){this.$el.css("width",50*this.model.revisions.length+"px"),this.$el.slider(_.extend(this.model.toJSON(),{start:this.start,slide:this.slide,stop:this.stop})),this.$el.hoverIntent({over:this.mouseEnter,out:this.mouseLeave,timeout:800}),this.applySliderSettings()},mouseMove:function(e){var i=this.model.revisions.length-1,t=this.$el.allOffsets()[this.direction],s=this.$el.width()/i,o=(isRtl?h(window).width()-e.pageX:e.pageX)-t,n=Math.floor((o+s/2)/s);n<0?n=0:n>=this.model.revisions.length&&(n=this.model.revisions.length-1),this.model.set({hoveredRevision:this.model.revisions.at(n)})},mouseLeave:function(){this.model.set({hovering:!1})},mouseEnter:function(){this.model.set({hovering:!0})},applySliderSettings:function(){this.$el.slider(_.pick(this.model.toJSON(),"value","values","range"));var e=this.$("a.ui-slider-handle");this.model.get("compareTwoMode")?(e.first().toggleClass("to-handle",!!isRtl).toggleClass("from-handle",!isRtl),e.last().toggleClass("from-handle",!!isRtl).toggleClass("to-handle",!isRtl)):e.removeClass("from-handle to-handle")},start:function(e,a){this.model.set({scrubbing:!0}),h(window).on("mousemove.wp.revisions",{view:this},function(e){var i,t=e.data.view,s=t.$el.offset().left,o=s,n=s+t.$el.width(),r="0",l="100%",d=h(a.handle);t.model.get("compareTwoMode")&&(i=d.parent().find(".ui-slider-handle"),d.is(i.first())?l=(n=i.last().offset().left)-o:r=(s=i.first().offset().left+i.first().width())-o),e.pageX<s?d.css("left",r):e.pageX>n?d.css("left",l):d.css("left",e.pageX-o)})},getPosition:function(e){return isRtl?this.model.revisions.length-e-1:e},slide:function(e,i){var t,s;if(this.model.get("compareTwoMode")){if(i.values[1]===i.values[0])return!1;isRtl&&i.values.reverse(),t={from:this.model.revisions.at(this.getPosition(i.values[0])),to:this.model.revisions.at(this.getPosition(i.values[1]))}}else t={to:this.model.revisions.at(this.getPosition(i.value))},0<this.getPosition(i.value)?t.from=this.model.revisions.at(this.getPosition(i.value)-1):t.from=void 0;s=this.model.revisions.at(this.getPosition(i.value)),this.model.get("scrubbing")&&(t.hoveredRevision=s),this.model.set(t)},stop:function(){h(window).off("mousemove.wp.revisions"),this.model.updateSliderSettings(),this.model.set({scrubbing:!1})}}),s.view.Diff=wp.Backbone.View.extend({className:"revisions-diff",template:wp.template("revisions-diff"),prepare:function(){return _.extend({fields:this.model.fields.toJSON()},this.options)}}),s.Router=Backbone.Router.extend({initialize:function(e){this.model=e.model,this.listenTo(this.model,"update:diff",_.debounce(this.updateUrl,250)),this.listenTo(this.model,"change:compareTwoMode",this.updateUrl)},baseUrl:function(e){return this.model.get("baseUrl")+e},updateUrl:function(){var e=this.model.has("from")?this.model.get("from").id:0,i=this.model.get("to").id;this.model.get("compareTwoMode")?this.navigate(this.baseUrl("?from="+e+"&to="+i),{replace:!0}):this.navigate(this.baseUrl("?revision="+i),{replace:!0})},handleRoute:function(e,i){_.isUndefined(i)||(i=this.model.revisions.get(e),e=this.model.revisions.prev(i),i=i?i.id:0,e=e?e.id:0)}}),s.init=function(){var e;window.adminpage&&"revision-php"===window.adminpage&&(e=new s.model.FrameState({initialDiffState:{to:parseInt(s.settings.to,10),from:parseInt(s.settings.from,10),compareTwoMode:"1"===s.settings.compareTwoMode},diffData:s.settings.diffData,baseUrl:s.settings.baseUrl,postId:parseInt(s.settings.postId,10)},{revisions:new s.model.Revisions(s.settings.revisionData)}),s.view.frame=new s.view.Frame({model:e}).render())},h(s.init)}(jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/set-post-thumbnail.js b/srcs/wordpress/wp-admin/js/set-post-thumbnail.js deleted file mode 100644 index 0f3849a..0000000 --- a/srcs/wordpress/wp-admin/js/set-post-thumbnail.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @output wp-admin/js/set-post-thumbnail.js - */ - -/* global setPostThumbnailL10n, ajaxurl, post_id, alert */ -/* exported WPSetAsThumbnail */ - -window.WPSetAsThumbnail = function( id, nonce ) { - var $link = jQuery('a#wp-post-thumbnail-' + id); - - $link.text( setPostThumbnailL10n.saving ); - jQuery.post(ajaxurl, { - action: 'set-post-thumbnail', post_id: post_id, thumbnail_id: id, _ajax_nonce: nonce, cookie: encodeURIComponent( document.cookie ) - }, function(str){ - var win = window.dialogArguments || opener || parent || top; - $link.text( setPostThumbnailL10n.setThumbnail ); - if ( str == '0' ) { - alert( setPostThumbnailL10n.error ); - } else { - jQuery('a.wp-post-thumbnail').show(); - $link.text( setPostThumbnailL10n.done ); - $link.fadeOut( 2000 ); - win.WPSetThumbnailID(id); - win.WPSetThumbnailHTML(str); - } - } - ); -}; diff --git a/srcs/wordpress/wp-admin/js/set-post-thumbnail.min.js b/srcs/wordpress/wp-admin/js/set-post-thumbnail.min.js deleted file mode 100644 index 723fa04..0000000 --- a/srcs/wordpress/wp-admin/js/set-post-thumbnail.min.js +++ /dev/null @@ -1 +0,0 @@ -window.WPSetAsThumbnail=function(e,t){var o=jQuery("a#wp-post-thumbnail-"+e);o.text(setPostThumbnailL10n.saving),jQuery.post(ajaxurl,{action:"set-post-thumbnail",post_id:post_id,thumbnail_id:e,_ajax_nonce:t,cookie:encodeURIComponent(document.cookie)},function(t){var n=window.dialogArguments||opener||parent||top;o.text(setPostThumbnailL10n.setThumbnail),"0"==t?alert(setPostThumbnailL10n.error):(jQuery("a.wp-post-thumbnail").show(),o.text(setPostThumbnailL10n.done),o.fadeOut(2e3),n.WPSetThumbnailID(e),n.WPSetThumbnailHTML(t))})};
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/site-health.js b/srcs/wordpress/wp-admin/js/site-health.js deleted file mode 100644 index f5a6fed..0000000 --- a/srcs/wordpress/wp-admin/js/site-health.js +++ /dev/null @@ -1,314 +0,0 @@ -/** - * Interactions used by the Site Health modules in WordPress. - * - * @output wp-admin/js/site-health.js - */ - -/* global ajaxurl, ClipboardJS, SiteHealth, wp */ - -jQuery( document ).ready( function( $ ) { - - var __ = wp.i18n.__, - _n = wp.i18n._n, - sprintf = wp.i18n.sprintf; - - var data; - var clipboard = new ClipboardJS( '.site-health-copy-buttons .copy-button' ); - var isDebugTab = $( '.health-check-body.health-check-debug-tab' ).length; - var pathsSizesSection = $( '#health-check-accordion-block-wp-paths-sizes' ); - - // Debug information copy section. - clipboard.on( 'success', function( e ) { - var $wrapper = $( e.trigger ).closest( 'div' ); - $( '.success', $wrapper ).addClass( 'visible' ); - - wp.a11y.speak( __( 'Site information has been added to your clipboard.' ) ); - } ); - - // Accordion handling in various areas. - $( '.health-check-accordion' ).on( 'click', '.health-check-accordion-trigger', function() { - var isExpanded = ( 'true' === $( this ).attr( 'aria-expanded' ) ); - - if ( isExpanded ) { - $( this ).attr( 'aria-expanded', 'false' ); - $( '#' + $( this ).attr( 'aria-controls' ) ).attr( 'hidden', true ); - } else { - $( this ).attr( 'aria-expanded', 'true' ); - $( '#' + $( this ).attr( 'aria-controls' ) ).attr( 'hidden', false ); - } - } ); - - // Site Health test handling. - - $( '.site-health-view-passed' ).on( 'click', function() { - var goodIssuesWrapper = $( '#health-check-issues-good' ); - - goodIssuesWrapper.toggleClass( 'hidden' ); - $( this ).attr( 'aria-expanded', ! goodIssuesWrapper.hasClass( 'hidden' ) ); - } ); - - /** - * Append a new issue to the issue list. - * - * @since 5.2.0 - * - * @param {Object} issue The issue data. - */ - function AppendIssue( issue ) { - var template = wp.template( 'health-check-issue' ), - issueWrapper = $( '#health-check-issues-' + issue.status ), - heading, - count; - - SiteHealth.site_status.issues[ issue.status ]++; - - count = SiteHealth.site_status.issues[ issue.status ]; - - if ( 'critical' === issue.status ) { - heading = sprintf( _n( '%s critical issue', '%s critical issues', count ), '<span class="issue-count">' + count + '</span>' ); - } else if ( 'recommended' === issue.status ) { - heading = sprintf( _n( '%s recommended improvement', '%s recommended improvements', count ), '<span class="issue-count">' + count + '</span>' ); - } else if ( 'good' === issue.status ) { - heading = sprintf( _n( '%s item with no issues detected', '%s items with no issues detected', count ), '<span class="issue-count">' + count + '</span>' ); - } - - if ( heading ) { - $( '.site-health-issue-count-title', issueWrapper ).html( heading ); - } - - $( '.issues', '#health-check-issues-' + issue.status ).append( template( issue ) ); - } - - /** - * Update site health status indicator as asynchronous tests are run and returned. - * - * @since 5.2.0 - */ - function RecalculateProgression() { - var r, c, pct; - var $progress = $( '.site-health-progress' ); - var $wrapper = $progress.closest( '.site-health-progress-wrapper' ); - var $progressLabel = $( '.site-health-progress-label', $wrapper ); - var $circle = $( '.site-health-progress svg #bar' ); - var totalTests = parseInt( SiteHealth.site_status.issues.good, 0 ) + parseInt( SiteHealth.site_status.issues.recommended, 0 ) + ( parseInt( SiteHealth.site_status.issues.critical, 0 ) * 1.5 ); - var failedTests = ( parseInt( SiteHealth.site_status.issues.recommended, 0 ) * 0.5 ) + ( parseInt( SiteHealth.site_status.issues.critical, 0 ) * 1.5 ); - var val = 100 - Math.ceil( ( failedTests / totalTests ) * 100 ); - - if ( 0 === totalTests ) { - $progress.addClass( 'hidden' ); - return; - } - - $wrapper.removeClass( 'loading' ); - - r = $circle.attr( 'r' ); - c = Math.PI * ( r * 2 ); - - if ( 0 > val ) { - val = 0; - } - if ( 100 < val ) { - val = 100; - } - - pct = ( ( 100 - val ) / 100 ) * c; - - $circle.css( { strokeDashoffset: pct } ); - - if ( 1 > parseInt( SiteHealth.site_status.issues.critical, 0 ) ) { - $( '#health-check-issues-critical' ).addClass( 'hidden' ); - } - - if ( 1 > parseInt( SiteHealth.site_status.issues.recommended, 0 ) ) { - $( '#health-check-issues-recommended' ).addClass( 'hidden' ); - } - - if ( 80 <= val && 0 === parseInt( SiteHealth.site_status.issues.critical, 0 ) ) { - $wrapper.addClass( 'green' ).removeClass( 'orange' ); - - $progressLabel.text( __( 'Good' ) ); - wp.a11y.speak( __( 'All site health tests have finished running. Your site is looking good, and the results are now available on the page.' ) ); - } else { - $wrapper.addClass( 'orange' ).removeClass( 'green' ); - - $progressLabel.text( __( 'Should be improved' ) ); - wp.a11y.speak( __( 'All site health tests have finished running. There are items that should be addressed, and the results are now available on the page.' ) ); - } - - if ( ! isDebugTab ) { - $.post( - ajaxurl, - { - 'action': 'health-check-site-status-result', - '_wpnonce': SiteHealth.nonce.site_status_result, - 'counts': SiteHealth.site_status.issues - } - ); - - if ( 100 === val ) { - $( '.site-status-all-clear' ).removeClass( 'hide' ); - $( '.site-status-has-issues' ).addClass( 'hide' ); - } - } - } - - /** - * Queue the next asynchronous test when we're ready to run it. - * - * @since 5.2.0 - */ - function maybeRunNextAsyncTest() { - var doCalculation = true; - - if ( 1 <= SiteHealth.site_status.async.length ) { - $.each( SiteHealth.site_status.async, function() { - var data = { - 'action': 'health-check-' + this.test.replace( '_', '-' ), - '_wpnonce': SiteHealth.nonce.site_status - }; - - if ( this.completed ) { - return true; - } - - doCalculation = false; - - this.completed = true; - - $.post( - ajaxurl, - data, - function( response ) { - /** This filter is documented in wp-admin/includes/class-wp-site-health.php */ - AppendIssue( wp.hooks.applyFilters( 'site_status_test_result', response.data ) ); - maybeRunNextAsyncTest(); - } - ); - - return false; - } ); - } - - if ( doCalculation ) { - RecalculateProgression(); - } - } - - if ( 'undefined' !== typeof SiteHealth && ! isDebugTab ) { - if ( 0 === SiteHealth.site_status.direct.length && 0 === SiteHealth.site_status.async.length ) { - RecalculateProgression(); - } else { - SiteHealth.site_status.issues = { - 'good': 0, - 'recommended': 0, - 'critical': 0 - }; - } - - if ( 0 < SiteHealth.site_status.direct.length ) { - $.each( SiteHealth.site_status.direct, function() { - AppendIssue( this ); - } ); - } - - if ( 0 < SiteHealth.site_status.async.length ) { - data = { - 'action': 'health-check-' + SiteHealth.site_status.async[0].test.replace( '_', '-' ), - '_wpnonce': SiteHealth.nonce.site_status - }; - - SiteHealth.site_status.async[0].completed = true; - - $.post( - ajaxurl, - data, - function( response ) { - AppendIssue( response.data ); - maybeRunNextAsyncTest(); - } - ); - } else { - RecalculateProgression(); - } - } - - function getDirectorySizes() { - var data = { - action: 'health-check-get-sizes', - _wpnonce: SiteHealth.nonce.site_status_result - }; - - var timestamp = ( new Date().getTime() ); - - // After 3 seconds announce that we're still waiting for directory sizes. - var timeout = window.setTimeout( function() { - wp.a11y.speak( __( 'Please wait...' ) ); - }, 3000 ); - - $.post( { - type: 'POST', - url: ajaxurl, - data: data, - dataType: 'json' - } ).done( function( response ) { - updateDirSizes( response.data || {} ); - } ).always( function() { - var delay = ( new Date().getTime() ) - timestamp; - - $( '.health-check-wp-paths-sizes.spinner' ).css( 'visibility', 'hidden' ); - RecalculateProgression(); - - if ( delay > 3000 ) { - // We have announced that we're waiting. - // Announce that we're ready after giving at least 3 seconds for the first announcement - // to be read out, or the two may collide. - if ( delay > 6000 ) { - delay = 0; - } else { - delay = 6500 - delay; - } - - window.setTimeout( function() { - wp.a11y.speak( __( 'All site health tests have finished running.' ) ); - }, delay ); - } else { - // Cancel the announcement. - window.clearTimeout( timeout ); - } - - $( document ).trigger( 'site-health-info-dirsizes-done' ); - } ); - } - - function updateDirSizes( data ) { - var copyButton = $( 'button.button.copy-button' ); - var clipdoardText = copyButton.attr( 'data-clipboard-text' ); - - $.each( data, function( name, value ) { - var text = value.debug || value.size; - - if ( typeof text !== 'undefined' ) { - clipdoardText = clipdoardText.replace( name + ': loading...', name + ': ' + text ); - } - } ); - - copyButton.attr( 'data-clipboard-text', clipdoardText ); - - pathsSizesSection.find( 'td[class]' ).each( function( i, element ) { - var td = $( element ); - var name = td.attr( 'class' ); - - if ( data.hasOwnProperty( name ) && data[ name ].size ) { - td.text( data[ name ].size ); - } - } ); - } - - if ( isDebugTab ) { - if ( pathsSizesSection.length ) { - getDirectorySizes(); - } else { - RecalculateProgression(); - } - } -} ); diff --git a/srcs/wordpress/wp-admin/js/site-health.min.js b/srcs/wordpress/wp-admin/js/site-health.min.js deleted file mode 100644 index 3652b55..0000000 --- a/srcs/wordpress/wp-admin/js/site-health.min.js +++ /dev/null @@ -1 +0,0 @@ -jQuery(document).ready(function(o){var e,t,s,a,r=wp.i18n.__,n=wp.i18n._n,h=wp.i18n.sprintf,i=new ClipboardJS(".site-health-copy-buttons .copy-button"),u=o(".health-check-body.health-check-debug-tab").length,c=o("#health-check-accordion-block-wp-paths-sizes");function l(e){var t,s,a=wp.template("health-check-issue"),i=o("#health-check-issues-"+e.status);SiteHealth.site_status.issues[e.status]++,s=SiteHealth.site_status.issues[e.status],"critical"===e.status?t=h(n("%s critical issue","%s critical issues",s),'<span class="issue-count">'+s+"</span>"):"recommended"===e.status?t=h(n("%s recommended improvement","%s recommended improvements",s),'<span class="issue-count">'+s+"</span>"):"good"===e.status&&(t=h(n("%s item with no issues detected","%s items with no issues detected",s),'<span class="issue-count">'+s+"</span>")),t&&o(".site-health-issue-count-title",i).html(t),o(".issues","#health-check-issues-"+e.status).append(a(e))}function d(){var e,t,s=o(".site-health-progress"),a=s.closest(".site-health-progress-wrapper"),i=o(".site-health-progress-label",a),n=o(".site-health-progress svg #bar"),h=parseInt(SiteHealth.site_status.issues.good,0)+parseInt(SiteHealth.site_status.issues.recommended,0)+1.5*parseInt(SiteHealth.site_status.issues.critical,0),c=.5*parseInt(SiteHealth.site_status.issues.recommended,0)+1.5*parseInt(SiteHealth.site_status.issues.critical,0),l=100-Math.ceil(c/h*100);0!==h?(a.removeClass("loading"),e=n.attr("r"),l<0&&(l=0),100<l&&(l=100),t=(100-l)/100*(Math.PI*(2*e)),n.css({strokeDashoffset:t}),parseInt(SiteHealth.site_status.issues.critical,0)<1&&o("#health-check-issues-critical").addClass("hidden"),parseInt(SiteHealth.site_status.issues.recommended,0)<1&&o("#health-check-issues-recommended").addClass("hidden"),80<=l&&0===parseInt(SiteHealth.site_status.issues.critical,0)?(a.addClass("green").removeClass("orange"),i.text(r("Good")),wp.a11y.speak(r("All site health tests have finished running. Your site is looking good, and the results are now available on the page."))):(a.addClass("orange").removeClass("green"),i.text(r("Should be improved")),wp.a11y.speak(r("All site health tests have finished running. There are items that should be addressed, and the results are now available on the page."))),u||(o.post(ajaxurl,{action:"health-check-site-status-result",_wpnonce:SiteHealth.nonce.site_status_result,counts:SiteHealth.site_status.issues}),100===l&&(o(".site-status-all-clear").removeClass("hide"),o(".site-status-has-issues").addClass("hide")))):s.addClass("hidden")}i.on("success",function(e){var t=o(e.trigger).closest("div");o(".success",t).addClass("visible"),wp.a11y.speak(r("Site information has been added to your clipboard."))}),o(".health-check-accordion").on("click",".health-check-accordion-trigger",function(){"true"===o(this).attr("aria-expanded")?(o(this).attr("aria-expanded","false"),o("#"+o(this).attr("aria-controls")).attr("hidden",!0)):(o(this).attr("aria-expanded","true"),o("#"+o(this).attr("aria-controls")).attr("hidden",!1))}),o(".site-health-view-passed").on("click",function(){var e=o("#health-check-issues-good");e.toggleClass("hidden"),o(this).attr("aria-expanded",!e.hasClass("hidden"))}),"undefined"==typeof SiteHealth||u||(0===SiteHealth.site_status.direct.length&&0===SiteHealth.site_status.async.length?d():SiteHealth.site_status.issues={good:0,recommended:0,critical:0},0<SiteHealth.site_status.direct.length&&o.each(SiteHealth.site_status.direct,function(){l(this)}),0<SiteHealth.site_status.async.length?(e={action:"health-check-"+SiteHealth.site_status.async[0].test.replace("_","-"),_wpnonce:SiteHealth.nonce.site_status},SiteHealth.site_status.async[0].completed=!0,o.post(ajaxurl,e,function(e){l(e.data),function t(){var s=!0;1<=SiteHealth.site_status.async.length&&o.each(SiteHealth.site_status.async,function(){var e={action:"health-check-"+this.test.replace("_","-"),_wpnonce:SiteHealth.nonce.site_status};return!!this.completed||(s=!1,this.completed=!0,o.post(ajaxurl,e,function(e){l(wp.hooks.applyFilters("site_status_test_result",e.data)),t()}),!1)}),s&&d()}()})):d()),u&&(c.length?(t={action:"health-check-get-sizes",_wpnonce:SiteHealth.nonce.site_status_result},s=(new Date).getTime(),a=window.setTimeout(function(){wp.a11y.speak(r("Please wait..."))},3e3),o.post({type:"POST",url:ajaxurl,data:t,dataType:"json"}).done(function(e){!function(i){var e=o("button.button.copy-button"),a=e.attr("data-clipboard-text");o.each(i,function(e,t){var s=t.debug||t.size;void 0!==s&&(a=a.replace(e+": loading...",e+": "+s))}),e.attr("data-clipboard-text",a),c.find("td[class]").each(function(e,t){var s=o(t),a=s.attr("class");i.hasOwnProperty(a)&&i[a].size&&s.text(i[a].size)})}(e.data||{})}).always(function(){var e=(new Date).getTime()-s;o(".health-check-wp-paths-sizes.spinner").css("visibility","hidden"),d(),3e3<e?(e=6e3<e?0:6500-e,window.setTimeout(function(){wp.a11y.speak(r("All site health tests have finished running."))},e)):window.clearTimeout(a),o(document).trigger("site-health-info-dirsizes-done")})):d())});
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/svg-painter.js b/srcs/wordpress/wp-admin/js/svg-painter.js deleted file mode 100644 index e0277f1..0000000 --- a/srcs/wordpress/wp-admin/js/svg-painter.js +++ /dev/null @@ -1,241 +0,0 @@ -/** - * Attempt to re-color SVG icons used in the admin menu or the toolbar - * - * @output wp-admin/js/svg-painter.js - */ - -window.wp = window.wp || {}; - -wp.svgPainter = ( function( $, window, document, undefined ) { - 'use strict'; - var selector, base64, painter, - colorscheme = {}, - elements = []; - - $(document).ready( function() { - // detection for browser SVG capability - if ( document.implementation.hasFeature( 'http://www.w3.org/TR/SVG11/feature#Image', '1.1' ) ) { - $( document.body ).removeClass( 'no-svg' ).addClass( 'svg' ); - wp.svgPainter.init(); - } - }); - - /** - * Needed only for IE9 - * - * Based on jquery.base64.js 0.0.3 - https://github.com/yckart/jquery.base64.js - * - * Based on: https://gist.github.com/Yaffle/1284012 - * - * Copyright (c) 2012 Yannick Albert (http://yckart.com) - * Licensed under the MIT license - * http://www.opensource.org/licenses/mit-license.php - */ - base64 = ( function() { - var c, - b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', - a256 = '', - r64 = [256], - r256 = [256], - i = 0; - - function init() { - while( i < 256 ) { - c = String.fromCharCode(i); - a256 += c; - r256[i] = i; - r64[i] = b64.indexOf(c); - ++i; - } - } - - function code( s, discard, alpha, beta, w1, w2 ) { - var tmp, length, - buffer = 0, - i = 0, - result = '', - bitsInBuffer = 0; - - s = String(s); - length = s.length; - - while( i < length ) { - c = s.charCodeAt(i); - c = c < 256 ? alpha[c] : -1; - - buffer = ( buffer << w1 ) + c; - bitsInBuffer += w1; - - while( bitsInBuffer >= w2 ) { - bitsInBuffer -= w2; - tmp = buffer >> bitsInBuffer; - result += beta.charAt(tmp); - buffer ^= tmp << bitsInBuffer; - } - ++i; - } - - if ( ! discard && bitsInBuffer > 0 ) { - result += beta.charAt( buffer << ( w2 - bitsInBuffer ) ); - } - - return result; - } - - function btoa( plain ) { - if ( ! c ) { - init(); - } - - plain = code( plain, false, r256, b64, 8, 6 ); - return plain + '===='.slice( ( plain.length % 4 ) || 4 ); - } - - function atob( coded ) { - var i; - - if ( ! c ) { - init(); - } - - coded = coded.replace( /[^A-Za-z0-9\+\/\=]/g, '' ); - coded = String(coded).split('='); - i = coded.length; - - do { - --i; - coded[i] = code( coded[i], true, r64, a256, 6, 8 ); - } while ( i > 0 ); - - coded = coded.join(''); - return coded; - } - - return { - atob: atob, - btoa: btoa - }; - })(); - - return { - init: function() { - painter = this; - selector = $( '#adminmenu .wp-menu-image, #wpadminbar .ab-item' ); - - this.setColors(); - this.findElements(); - this.paint(); - }, - - setColors: function( colors ) { - if ( typeof colors === 'undefined' && typeof window._wpColorScheme !== 'undefined' ) { - colors = window._wpColorScheme; - } - - if ( colors && colors.icons && colors.icons.base && colors.icons.current && colors.icons.focus ) { - colorscheme = colors.icons; - } - }, - - findElements: function() { - selector.each( function() { - var $this = $(this), bgImage = $this.css( 'background-image' ); - - if ( bgImage && bgImage.indexOf( 'data:image/svg+xml;base64' ) != -1 ) { - elements.push( $this ); - } - }); - }, - - paint: function() { - // loop through all elements - $.each( elements, function( index, $element ) { - var $menuitem = $element.parent().parent(); - - if ( $menuitem.hasClass( 'current' ) || $menuitem.hasClass( 'wp-has-current-submenu' ) ) { - // paint icon in 'current' color - painter.paintElement( $element, 'current' ); - } else { - // paint icon in base color - painter.paintElement( $element, 'base' ); - - // set hover callbacks - $menuitem.hover( - function() { - painter.paintElement( $element, 'focus' ); - }, - function() { - // Match the delay from hoverIntent - window.setTimeout( function() { - painter.paintElement( $element, 'base' ); - }, 100 ); - } - ); - } - }); - }, - - paintElement: function( $element, colorType ) { - var xml, encoded, color; - - if ( ! colorType || ! colorscheme.hasOwnProperty( colorType ) ) { - return; - } - - color = colorscheme[ colorType ]; - - // only accept hex colors: #101 or #101010 - if ( ! color.match( /^(#[0-9a-f]{3}|#[0-9a-f]{6})$/i ) ) { - return; - } - - xml = $element.data( 'wp-ui-svg-' + color ); - - if ( xml === 'none' ) { - return; - } - - if ( ! xml ) { - encoded = $element.css( 'background-image' ).match( /.+data:image\/svg\+xml;base64,([A-Za-z0-9\+\/\=]+)/ ); - - if ( ! encoded || ! encoded[1] ) { - $element.data( 'wp-ui-svg-' + color, 'none' ); - return; - } - - try { - if ( 'atob' in window ) { - xml = window.atob( encoded[1] ); - } else { - xml = base64.atob( encoded[1] ); - } - } catch ( error ) {} - - if ( xml ) { - // replace `fill` attributes - xml = xml.replace( /fill="(.+?)"/g, 'fill="' + color + '"'); - - // replace `style` attributes - xml = xml.replace( /style="(.+?)"/g, 'style="fill:' + color + '"'); - - // replace `fill` properties in `<style>` tags - xml = xml.replace( /fill:.*?;/g, 'fill: ' + color + ';'); - - if ( 'btoa' in window ) { - xml = window.btoa( xml ); - } else { - xml = base64.btoa( xml ); - } - - $element.data( 'wp-ui-svg-' + color, xml ); - } else { - $element.data( 'wp-ui-svg-' + color, 'none' ); - return; - } - } - - $element.attr( 'style', 'background-image: url("data:image/svg+xml;base64,' + xml + '") !important;' ); - } - }; - -})( jQuery, window, document ); diff --git a/srcs/wordpress/wp-admin/js/svg-painter.min.js b/srcs/wordpress/wp-admin/js/svg-painter.min.js deleted file mode 100644 index 2466c66..0000000 --- a/srcs/wordpress/wp-admin/js/svg-painter.min.js +++ /dev/null @@ -1 +0,0 @@ -window.wp=window.wp||{},wp.svgPainter=function(a,o,n){"use strict";var t,r,e,m,i,s,c,u,l,f={},g=[];function p(){for(;l<256;)m=String.fromCharCode(l),s+=m,u[l]=l,c[l]=i.indexOf(m),++l}function d(n,t,a,e,i,o){var r,s,c=0,u=0,l="",f=0;for(s=(n=String(n)).length;u<s;){for(c=(c<<i)+(m=(m=n.charCodeAt(u))<256?a[m]:-1),f+=i;o<=f;)r=c>>(f-=o),l+=e.charAt(r),c^=r<<f;++u}return!t&&0<f&&(l+=e.charAt(c<<o-f)),l}return a(n).ready(function(){n.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image","1.1")&&(a(n.body).removeClass("no-svg").addClass("svg"),wp.svgPainter.init())}),i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s="",c=[256],u=[256],l=0,r={atob:function(n){var t;for(m||p(),n=n.replace(/[^A-Za-z0-9\+\/\=]/g,""),t=(n=String(n).split("=")).length;n[--t]=d(n[t],!0,c,s,6,8),0<t;);return n=n.join("")},btoa:function(n){return m||p(),(n=d(n,!1,u,i,8,6))+"====".slice(n.length%4||4)}},{init:function(){e=this,t=a("#adminmenu .wp-menu-image, #wpadminbar .ab-item"),this.setColors(),this.findElements(),this.paint()},setColors:function(n){void 0===n&&void 0!==o._wpColorScheme&&(n=o._wpColorScheme),n&&n.icons&&n.icons.base&&n.icons.current&&n.icons.focus&&(f=n.icons)},findElements:function(){t.each(function(){var n=a(this),t=n.css("background-image");t&&-1!=t.indexOf("data:image/svg+xml;base64")&&g.push(n)})},paint:function(){a.each(g,function(n,t){var a=t.parent().parent();a.hasClass("current")||a.hasClass("wp-has-current-submenu")?e.paintElement(t,"current"):(e.paintElement(t,"base"),a.hover(function(){e.paintElement(t,"focus")},function(){o.setTimeout(function(){e.paintElement(t,"base")},100)}))})},paintElement:function(n,t){var a,e,i;if(t&&f.hasOwnProperty(t)&&(i=f[t]).match(/^(#[0-9a-f]{3}|#[0-9a-f]{6})$/i)&&"none"!==(a=n.data("wp-ui-svg-"+i))){if(!a){if(!(e=n.css("background-image").match(/.+data:image\/svg\+xml;base64,([A-Za-z0-9\+\/\=]+)/))||!e[1])return void n.data("wp-ui-svg-"+i,"none");try{a="atob"in o?o.atob(e[1]):r.atob(e[1])}catch(n){}if(!a)return void n.data("wp-ui-svg-"+i,"none");a=(a=(a=a.replace(/fill="(.+?)"/g,'fill="'+i+'"')).replace(/style="(.+?)"/g,'style="fill:'+i+'"')).replace(/fill:.*?;/g,"fill: "+i+";"),a="btoa"in o?o.btoa(a):r.btoa(a),n.data("wp-ui-svg-"+i,a)}n.attr("style",'background-image: url("data:image/svg+xml;base64,'+a+'") !important;')}}}}(jQuery,window,document);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/tags-box.js b/srcs/wordpress/wp-admin/js/tags-box.js deleted file mode 100644 index c4676f2..0000000 --- a/srcs/wordpress/wp-admin/js/tags-box.js +++ /dev/null @@ -1,430 +0,0 @@ -/** - * @output wp-admin/js/tags-box.js - */ - -/* jshint curly: false, eqeqeq: false */ -/* global ajaxurl, tagBox, array_unique_noempty */ - -( function( $ ) { - var tagDelimiter = ( window.tagsSuggestL10n && window.tagsSuggestL10n.tagDelimiter ) || ','; - - /** - * Filters unique items and returns a new array. - * - * Filters all items from an array into a new array containing only the unique - * items. This also excludes whitespace or empty values. - * - * @since 2.8.0 - * - * @global - * - * @param {Array} array The array to filter through. - * - * @return {Array} A new array containing only the unique items. - */ - window.array_unique_noempty = function( array ) { - var out = []; - - // Trim the values and ensure they are unique. - $.each( array, function( key, val ) { - val = $.trim( val ); - - if ( val && $.inArray( val, out ) === -1 ) { - out.push( val ); - } - } ); - - return out; - }; - - /** - * The TagBox object. - * - * Contains functions to create and manage tags that can be associated with a - * post. - * - * @since 2.9.0 - * - * @global - */ - window.tagBox = { - /** - * Cleans up tags by removing redundant characters. - * - * @since 2.9.0 - * @memberOf tagBox - * - * @param {string} tags Comma separated tags that need to be cleaned up. - * - * @return {string} The cleaned up tags. - */ - clean : function( tags ) { - if ( ',' !== tagDelimiter ) { - tags = tags.replace( new RegExp( tagDelimiter, 'g' ), ',' ); - } - - tags = tags.replace(/\s*,\s*/g, ',').replace(/,+/g, ',').replace(/[,\s]+$/, '').replace(/^[,\s]+/, ''); - - if ( ',' !== tagDelimiter ) { - tags = tags.replace( /,/g, tagDelimiter ); - } - - return tags; - }, - - /** - * Parses tags and makes them editable. - * - * @since 2.9.0 - * @memberOf tagBox - * - * @param {Object} el The tag element to retrieve the ID from. - * - * @return {boolean} Always returns false. - */ - parseTags : function(el) { - var id = el.id, - num = id.split('-check-num-')[1], - taxbox = $(el).closest('.tagsdiv'), - thetags = taxbox.find('.the-tags'), - current_tags = thetags.val().split( tagDelimiter ), - new_tags = []; - - delete current_tags[num]; - - // Sanitize the current tags and push them as if they're new tags. - $.each( current_tags, function( key, val ) { - val = $.trim( val ); - if ( val ) { - new_tags.push( val ); - } - }); - - thetags.val( this.clean( new_tags.join( tagDelimiter ) ) ); - - this.quickClicks( taxbox ); - return false; - }, - - /** - * Creates clickable links, buttons and fields for adding or editing tags. - * - * @since 2.9.0 - * @memberOf tagBox - * - * @param {Object} el The container HTML element. - * - * @return {void} - */ - quickClicks : function( el ) { - var thetags = $('.the-tags', el), - tagchecklist = $('.tagchecklist', el), - id = $(el).attr('id'), - current_tags, disabled; - - if ( ! thetags.length ) - return; - - disabled = thetags.prop('disabled'); - - current_tags = thetags.val().split( tagDelimiter ); - tagchecklist.empty(); - - /** - * Creates a delete button if tag editing is enabled, before adding it to the tag list. - * - * @since 2.5.0 - * @memberOf tagBox - * - * @param {string} key The index of the current tag. - * @param {string} val The value of the current tag. - * - * @return {void} - */ - $.each( current_tags, function( key, val ) { - var listItem, xbutton; - - val = $.trim( val ); - - if ( ! val ) - return; - - // Create a new list item, and ensure the text is properly escaped. - listItem = $( '<li />' ).text( val ); - - // If tags editing isn't disabled, create the X button. - if ( ! disabled ) { - /* - * Build the X buttons, hide the X icon with aria-hidden and - * use visually hidden text for screen readers. - */ - xbutton = $( '<button type="button" id="' + id + '-check-num-' + key + '" class="ntdelbutton">' + - '<span class="remove-tag-icon" aria-hidden="true"></span>' + - '<span class="screen-reader-text">' + window.tagsSuggestL10n.removeTerm + ' ' + listItem.html() + '</span>' + - '</button>' ); - - /** - * Handles the click and keypress event of the tag remove button. - * - * Makes sure the focus ends up in the tag input field when using - * the keyboard to delete the tag. - * - * @since 4.2.0 - * - * @param {Event} e The click or keypress event to handle. - * - * @return {void} - */ - xbutton.on( 'click keypress', function( e ) { - // On click or when using the Enter/Spacebar keys. - if ( 'click' === e.type || 13 === e.keyCode || 32 === e.keyCode ) { - /* - * When using the keyboard, move focus back to the - * add new tag field. Note: when releasing the pressed - * key this will fire the `keyup` event on the input. - */ - if ( 13 === e.keyCode || 32 === e.keyCode ) { - $( this ).closest( '.tagsdiv' ).find( 'input.newtag' ).focus(); - } - - tagBox.userAction = 'remove'; - tagBox.parseTags( this ); - } - }); - - listItem.prepend( ' ' ).prepend( xbutton ); - } - - // Append the list item to the tag list. - tagchecklist.append( listItem ); - }); - - // The buttons list is built now, give feedback to screen reader users. - tagBox.screenReadersMessage(); - }, - - /** - * Adds a new tag. - * - * Also ensures that the quick links are properly generated. - * - * @since 2.9.0 - * @memberOf tagBox - * - * @param {Object} el The container HTML element. - * @param {Object|boolean} a When this is an HTML element the text of that - * element will be used for the new tag. - * @param {number|boolean} f If this value is not passed then the tag input - * field is focused. - * - * @return {boolean} Always returns false. - */ - flushTags : function( el, a, f ) { - var tagsval, newtags, text, - tags = $( '.the-tags', el ), - newtag = $( 'input.newtag', el ); - - a = a || false; - - text = a ? $(a).text() : newtag.val(); - - /* - * Return if there's no new tag or if the input field is empty. - * Note: when using the keyboard to add tags, focus is moved back to - * the input field and the `keyup` event attached on this field will - * fire when releasing the pressed key. Checking also for the field - * emptiness avoids to set the tags and call quickClicks() again. - */ - if ( 'undefined' == typeof( text ) || '' === text ) { - return false; - } - - tagsval = tags.val(); - newtags = tagsval ? tagsval + tagDelimiter + text : text; - - newtags = this.clean( newtags ); - newtags = array_unique_noempty( newtags.split( tagDelimiter ) ).join( tagDelimiter ); - tags.val( newtags ); - this.quickClicks( el ); - - if ( ! a ) - newtag.val(''); - if ( 'undefined' == typeof( f ) ) - newtag.focus(); - - return false; - }, - - /** - * Retrieves the available tags and creates a tagcloud. - * - * Retrieves the available tags from the database and creates an interactive - * tagcloud. Clicking a tag will add it. - * - * @since 2.9.0 - * @memberOf tagBox - * - * @param {string} id The ID to extract the taxonomy from. - * - * @return {void} - */ - get : function( id ) { - var tax = id.substr( id.indexOf('-') + 1 ); - - /** - * Puts a received tag cloud into a DOM element. - * - * The tag cloud HTML is generated on the server. - * - * @since 2.9.0 - * - * @param {number|string} r The response message from the AJAX call. - * @param {string} stat The status of the AJAX request. - * - * @return {void} - */ - $.post( ajaxurl, { 'action': 'get-tagcloud', 'tax': tax }, function( r, stat ) { - if ( 0 === r || 'success' != stat ) { - return; - } - - r = $( '<div id="tagcloud-' + tax + '" class="the-tagcloud">' + r + '</div>' ); - - /** - * Adds a new tag when a tag in the tagcloud is clicked. - * - * @since 2.9.0 - * - * @return {boolean} Returns false to prevent the default action. - */ - $( 'a', r ).click( function() { - tagBox.userAction = 'add'; - tagBox.flushTags( $( '#' + tax ), this ); - return false; - }); - - $( '#' + id ).after( r ); - }); - }, - - /** - * Track the user's last action. - * - * @since 4.7.0 - */ - userAction: '', - - /** - * Dispatches an audible message to screen readers. - * - * This will inform the user when a tag has been added or removed. - * - * @since 4.7.0 - * - * @return {void} - */ - screenReadersMessage: function() { - var message; - - switch ( this.userAction ) { - case 'remove': - message = window.tagsSuggestL10n.termRemoved; - break; - - case 'add': - message = window.tagsSuggestL10n.termAdded; - break; - - default: - return; - } - - window.wp.a11y.speak( message, 'assertive' ); - }, - - /** - * Initializes the tags box by setting up the links, buttons. Sets up event - * handling. - * - * This includes handling of pressing the enter key in the input field and the - * retrieval of tag suggestions. - * - * @since 2.9.0 - * @memberOf tagBox - * - * @return {void} - */ - init : function() { - var ajaxtag = $('div.ajaxtag'); - - $('.tagsdiv').each( function() { - tagBox.quickClicks( this ); - }); - - $( '.tagadd', ajaxtag ).click( function() { - tagBox.userAction = 'add'; - tagBox.flushTags( $( this ).closest( '.tagsdiv' ) ); - }); - - /** - * Handles pressing enter on the new tag input field. - * - * Prevents submitting the post edit form. Uses `keypress` to take - * into account Input Method Editor (IME) converters. - * - * @since 2.9.0 - * - * @param {Event} event The keypress event that occurred. - * - * @return {void} - */ - $( 'input.newtag', ajaxtag ).keypress( function( event ) { - if ( 13 == event.which ) { - tagBox.userAction = 'add'; - tagBox.flushTags( $( this ).closest( '.tagsdiv' ) ); - event.preventDefault(); - event.stopPropagation(); - } - }).each( function( i, element ) { - $( element ).wpTagsSuggest(); - }); - - /** - * Before a post is saved the value currently in the new tag input field will be - * added as a tag. - * - * @since 2.9.0 - * - * @return {void} - */ - $('#post').submit(function(){ - $('div.tagsdiv').each( function() { - tagBox.flushTags(this, false, 1); - }); - }); - - /** - * Handles clicking on the tag cloud link. - * - * Makes sure the ARIA attributes are set correctly. - * - * @since 2.9.0 - * - * @return {void} - */ - $('.tagcloud-link').click(function(){ - // On the first click, fetch the tag cloud and insert it in the DOM. - tagBox.get( $( this ).attr( 'id' ) ); - // Update button state, remove previous click event and attach a new one to toggle the cloud. - $( this ) - .attr( 'aria-expanded', 'true' ) - .unbind() - .click( function() { - $( this ) - .attr( 'aria-expanded', 'false' === $( this ).attr( 'aria-expanded' ) ? 'true' : 'false' ) - .siblings( '.the-tagcloud' ).toggle(); - }); - }); - } - }; -}( jQuery )); diff --git a/srcs/wordpress/wp-admin/js/tags-box.min.js b/srcs/wordpress/wp-admin/js/tags-box.min.js deleted file mode 100644 index f069854..0000000 --- a/srcs/wordpress/wp-admin/js/tags-box.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(r){var u=window.tagsSuggestL10n&&window.tagsSuggestL10n.tagDelimiter||",";window.array_unique_noempty=function(t){var a=[];return r.each(t,function(t,e){(e=r.trim(e))&&-1===r.inArray(e,a)&&a.push(e)}),a},window.tagBox={clean:function(t){return","!==u&&(t=t.replace(new RegExp(u,"g"),",")),t=t.replace(/\s*,\s*/g,",").replace(/,+/g,",").replace(/[,\s]+$/,"").replace(/^[,\s]+/,""),","!==u&&(t=t.replace(/,/g,u)),t},parseTags:function(t){var e=t.id.split("-check-num-")[1],a=r(t).closest(".tagsdiv"),s=a.find(".the-tags"),i=s.val().split(u),n=[];return delete i[e],r.each(i,function(t,e){(e=r.trim(e))&&n.push(e)}),s.val(this.clean(n.join(u))),this.quickClicks(a),!1},quickClicks:function(t){var e,i,a=r(".the-tags",t),n=r(".tagchecklist",t),c=r(t).attr("id");a.length&&(i=a.prop("disabled"),e=a.val().split(u),n.empty(),r.each(e,function(t,e){var a,s;(e=r.trim(e))&&(a=r("<li />").text(e),i||((s=r('<button type="button" id="'+c+"-check-num-"+t+'" class="ntdelbutton"><span class="remove-tag-icon" aria-hidden="true"></span><span class="screen-reader-text">'+window.tagsSuggestL10n.removeTerm+" "+a.html()+"</span></button>")).on("click keypress",function(t){"click"!==t.type&&13!==t.keyCode&&32!==t.keyCode||(13!==t.keyCode&&32!==t.keyCode||r(this).closest(".tagsdiv").find("input.newtag").focus(),tagBox.userAction="remove",tagBox.parseTags(this))}),a.prepend(" ").prepend(s)),n.append(a))}),tagBox.screenReadersMessage())},flushTags:function(t,e,a){var s,i,n,c=r(".the-tags",t),o=r("input.newtag",t);return void 0===(n=(e=e||!1)?r(e).text():o.val())||""===n||(i=(s=c.val())?s+u+n:n,i=this.clean(i),i=array_unique_noempty(i.split(u)).join(u),c.val(i),this.quickClicks(t),e||o.val(""),void 0===a&&o.focus()),!1},get:function(a){var s=a.substr(a.indexOf("-")+1);r.post(ajaxurl,{action:"get-tagcloud",tax:s},function(t,e){0!==t&&"success"==e&&(t=r('<div id="tagcloud-'+s+'" class="the-tagcloud">'+t+"</div>"),r("a",t).click(function(){return tagBox.userAction="add",tagBox.flushTags(r("#"+s),this),!1}),r("#"+a).after(t))})},userAction:"",screenReadersMessage:function(){var t;switch(this.userAction){case"remove":t=window.tagsSuggestL10n.termRemoved;break;case"add":t=window.tagsSuggestL10n.termAdded;break;default:return}window.wp.a11y.speak(t,"assertive")},init:function(){var t=r("div.ajaxtag");r(".tagsdiv").each(function(){tagBox.quickClicks(this)}),r(".tagadd",t).click(function(){tagBox.userAction="add",tagBox.flushTags(r(this).closest(".tagsdiv"))}),r("input.newtag",t).keypress(function(t){13==t.which&&(tagBox.userAction="add",tagBox.flushTags(r(this).closest(".tagsdiv")),t.preventDefault(),t.stopPropagation())}).each(function(t,e){r(e).wpTagsSuggest()}),r("#post").submit(function(){r("div.tagsdiv").each(function(){tagBox.flushTags(this,!1,1)})}),r(".tagcloud-link").click(function(){tagBox.get(r(this).attr("id")),r(this).attr("aria-expanded","true").unbind().click(function(){r(this).attr("aria-expanded","false"===r(this).attr("aria-expanded")?"true":"false").siblings(".the-tagcloud").toggle()})})}}}(jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/tags-suggest.js b/srcs/wordpress/wp-admin/js/tags-suggest.js deleted file mode 100644 index 866d7d0..0000000 --- a/srcs/wordpress/wp-admin/js/tags-suggest.js +++ /dev/null @@ -1,193 +0,0 @@ -/** - * Default settings for jQuery UI Autocomplete for use with non-hierarchical taxonomies. - * - * @output wp-admin/js/tags-suggest.js - */ -( function( $ ) { - if ( typeof window.tagsSuggestL10n === 'undefined' || typeof window.uiAutocompleteL10n === 'undefined' ) { - return; - } - - var tempID = 0; - var separator = window.tagsSuggestL10n.tagDelimiter || ','; - - function split( val ) { - return val.split( new RegExp( separator + '\\s*' ) ); - } - - function getLast( term ) { - return split( term ).pop(); - } - - /** - * Add UI Autocomplete to an input or textarea element with presets for use - * with non-hierarchical taxonomies. - * - * Example: `$( element ).wpTagsSuggest( options )`. - * - * The taxonomy can be passed in a `data-wp-taxonomy` attribute on the element or - * can be in `options.taxonomy`. - * - * @since 4.7.0 - * - * @param {object} options Options that are passed to UI Autocomplete. Can be used to override the default settings. - * @returns {object} jQuery instance. - */ - $.fn.wpTagsSuggest = function( options ) { - var cache; - var last; - var $element = $( this ); - - options = options || {}; - - var taxonomy = options.taxonomy || $element.attr( 'data-wp-taxonomy' ) || 'post_tag'; - - delete( options.taxonomy ); - - options = $.extend( { - source: function( request, response ) { - var term; - - if ( last === request.term ) { - response( cache ); - return; - } - - term = getLast( request.term ); - - $.get( window.ajaxurl, { - action: 'ajax-tag-search', - tax: taxonomy, - q: term - } ).always( function() { - $element.removeClass( 'ui-autocomplete-loading' ); // UI fails to remove this sometimes? - } ).done( function( data ) { - var tagName; - var tags = []; - - if ( data ) { - data = data.split( '\n' ); - - for ( tagName in data ) { - var id = ++tempID; - - tags.push({ - id: id, - name: data[tagName] - }); - } - - cache = tags; - response( tags ); - } else { - response( tags ); - } - } ); - - last = request.term; - }, - focus: function( event, ui ) { - $element.attr( 'aria-activedescendant', 'wp-tags-autocomplete-' + ui.item.id ); - - // Don't empty the input field when using the arrow keys to - // highlight items. See api.jqueryui.com/autocomplete/#event-focus - event.preventDefault(); - }, - select: function( event, ui ) { - var tags = split( $element.val() ); - // Remove the last user input. - tags.pop(); - // Append the new tag and an empty element to get one more separator at the end. - tags.push( ui.item.name, '' ); - - $element.val( tags.join( separator + ' ' ) ); - - if ( $.ui.keyCode.TAB === event.keyCode ) { - // Audible confirmation message when a tag has been selected. - window.wp.a11y.speak( window.tagsSuggestL10n.termSelected, 'assertive' ); - event.preventDefault(); - } else if ( $.ui.keyCode.ENTER === event.keyCode ) { - // If we're in the edit post Tags meta box, add the tag. - if ( window.tagBox ) { - window.tagBox.userAction = 'add'; - window.tagBox.flushTags( $( this ).closest( '.tagsdiv' ) ); - } - - // Do not close Quick Edit / Bulk Edit - event.preventDefault(); - event.stopPropagation(); - } - - return false; - }, - open: function() { - $element.attr( 'aria-expanded', 'true' ); - }, - close: function() { - $element.attr( 'aria-expanded', 'false' ); - }, - minLength: 2, - position: { - my: 'left top+2', - at: 'left bottom', - collision: 'none' - }, - messages: { - noResults: window.uiAutocompleteL10n.noResults, - results: function( number ) { - if ( number > 1 ) { - return window.uiAutocompleteL10n.manyResults.replace( '%d', number ); - } - - return window.uiAutocompleteL10n.oneResult; - } - } - }, options ); - - $element.on( 'keydown', function() { - $element.removeAttr( 'aria-activedescendant' ); - } ) - .autocomplete( options ) - .autocomplete( 'instance' )._renderItem = function( ul, item ) { - return $( '<li role="option" id="wp-tags-autocomplete-' + item.id + '">' ) - .text( item.name ) - .appendTo( ul ); - }; - - $element.attr( { - 'role': 'combobox', - 'aria-autocomplete': 'list', - 'aria-expanded': 'false', - 'aria-owns': $element.autocomplete( 'widget' ).attr( 'id' ) - } ) - .on( 'focus', function() { - var inputValue = split( $element.val() ).pop(); - - // Don't trigger a search if the field is empty. - // Also, avoids screen readers announce `No search results`. - if ( inputValue ) { - $element.autocomplete( 'search' ); - } - } ) - // Returns a jQuery object containing the menu element. - .autocomplete( 'widget' ) - .addClass( 'wp-tags-autocomplete' ) - .attr( 'role', 'listbox' ) - .removeAttr( 'tabindex' ) // Remove the `tabindex=0` attribute added by jQuery UI. - - // Looks like Safari and VoiceOver need an `aria-selected` attribute. See ticket #33301. - // The `menufocus` and `menublur` events are the same events used to add and remove - // the `ui-state-focus` CSS class on the menu items. See jQuery UI Menu Widget. - .on( 'menufocus', function( event, ui ) { - ui.item.attr( 'aria-selected', 'true' ); - }) - .on( 'menublur', function() { - // The `menublur` event returns an object where the item is `null` - // so we need to find the active item with other means. - $( this ).find( '[aria-selected="true"]' ).removeAttr( 'aria-selected' ); - }); - - return this; - }; - -}( jQuery ) ); diff --git a/srcs/wordpress/wp-admin/js/tags-suggest.min.js b/srcs/wordpress/wp-admin/js/tags-suggest.min.js deleted file mode 100644 index d88723c..0000000 --- a/srcs/wordpress/wp-admin/js/tags-suggest.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(r){if(void 0!==window.tagsSuggestL10n&&void 0!==window.uiAutocompleteL10n){var s=0,a=window.tagsSuggestL10n.tagDelimiter||",";r.fn.wpTagsSuggest=function(t){var i,o,n=r(this),u=(t=t||{}).taxonomy||n.attr("data-wp-taxonomy")||"post_tag";return delete t.taxonomy,t=r.extend({source:function(t,a){var e;o!==t.term?(e=function(t){return l(t).pop()}(t.term),r.get(window.ajaxurl,{action:"ajax-tag-search",tax:u,q:e}).always(function(){n.removeClass("ui-autocomplete-loading")}).done(function(t){var e,o=[];if(t){for(e in t=t.split("\n")){var n=++s;o.push({id:n,name:t[e]})}a(i=o)}else a(o)}),o=t.term):a(i)},focus:function(t,e){n.attr("aria-activedescendant","wp-tags-autocomplete-"+e.item.id),t.preventDefault()},select:function(t,e){var o=l(n.val());return o.pop(),o.push(e.item.name,""),n.val(o.join(a+" ")),r.ui.keyCode.TAB===t.keyCode?(window.wp.a11y.speak(window.tagsSuggestL10n.termSelected,"assertive"),t.preventDefault()):r.ui.keyCode.ENTER===t.keyCode&&(window.tagBox&&(window.tagBox.userAction="add",window.tagBox.flushTags(r(this).closest(".tagsdiv"))),t.preventDefault(),t.stopPropagation()),!1},open:function(){n.attr("aria-expanded","true")},close:function(){n.attr("aria-expanded","false")},minLength:2,position:{my:"left top+2",at:"left bottom",collision:"none"},messages:{noResults:window.uiAutocompleteL10n.noResults,results:function(t){return 1<t?window.uiAutocompleteL10n.manyResults.replace("%d",t):window.uiAutocompleteL10n.oneResult}}},t),n.on("keydown",function(){n.removeAttr("aria-activedescendant")}).autocomplete(t).autocomplete("instance")._renderItem=function(t,e){return r('<li role="option" id="wp-tags-autocomplete-'+e.id+'">').text(e.name).appendTo(t)},n.attr({role:"combobox","aria-autocomplete":"list","aria-expanded":"false","aria-owns":n.autocomplete("widget").attr("id")}).on("focus",function(){l(n.val()).pop()&&n.autocomplete("search")}).autocomplete("widget").addClass("wp-tags-autocomplete").attr("role","listbox").removeAttr("tabindex").on("menufocus",function(t,e){e.item.attr("aria-selected","true")}).on("menublur",function(){r(this).find('[aria-selected="true"]').removeAttr("aria-selected")}),this}}function l(t){return t.split(new RegExp(a+"\\s*"))}}(jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/tags.js b/srcs/wordpress/wp-admin/js/tags.js deleted file mode 100644 index a36b2eb..0000000 --- a/srcs/wordpress/wp-admin/js/tags.js +++ /dev/null @@ -1,160 +0,0 @@ -/** - * Contains logic for deleting and adding tags. - * - * For deleting tags it makes a request to the server to delete the tag. - * For adding tags it makes a request to the server to add the tag. - * - * @output wp-admin/js/tags.js - */ - - /* global ajaxurl, wpAjax, tagsl10n, showNotice, validateForm */ - -jQuery(document).ready(function($) { - - var addingTerm = false; - - /** - * Adds an event handler to the delete term link on the term overview page. - * - * Cancels default event handling and event bubbling. - * - * @since 2.8.0 - * - * @returns boolean Always returns false to cancel the default event handling. - */ - $( '#the-list' ).on( 'click', '.delete-tag', function() { - var t = $(this), tr = t.parents('tr'), r = true, data; - - if ( 'undefined' != showNotice ) - r = showNotice.warn(); - - if ( r ) { - data = t.attr('href').replace(/[^?]*\?/, '').replace(/action=delete/, 'action=delete-tag'); - - /** - * Makes a request to the server to delete the term that corresponds to the - * delete term button. - * - * @param {string} r The response from the server. - * - * @returns {void} - */ - $.post(ajaxurl, data, function(r){ - if ( '1' == r ) { - $('#ajax-response').empty(); - tr.fadeOut('normal', function(){ tr.remove(); }); - - /** - * Removes the term from the parent box and the tag cloud. - * - * `data.match(/tag_ID=(\d+)/)[1]` matches the term id from the data variable. - * This term id is then used to select the relevant HTML elements: - * The parent box and the tag cloud. - */ - $('select#parent option[value="' + data.match(/tag_ID=(\d+)/)[1] + '"]').remove(); - $('a.tag-link-' + data.match(/tag_ID=(\d+)/)[1]).remove(); - - } else if ( '-1' == r ) { - $('#ajax-response').empty().append('<div class="error"><p>' + tagsl10n.noPerm + '</p></div>'); - tr.children().css('backgroundColor', ''); - - } else { - $('#ajax-response').empty().append('<div class="error"><p>' + tagsl10n.broken + '</p></div>'); - tr.children().css('backgroundColor', ''); - } - }); - - tr.children().css('backgroundColor', '#f33'); - } - - return false; - }); - - /** - * Adds a deletion confirmation when removing a tag. - * - * @since 4.8.0 - * - * @returns {void} - */ - $( '#edittag' ).on( 'click', '.delete', function( e ) { - if ( 'undefined' === typeof showNotice ) { - return true; - } - - // Confirms the deletion, a negative response means the deletion must not be executed. - var response = showNotice.warn(); - if ( ! response ) { - e.preventDefault(); - } - }); - - /** - * Adds an event handler to the form submit on the term overview page. - * - * Cancels default event handling and event bubbling. - * - * @since 2.8.0 - * - * @returns boolean Always returns false to cancel the default event handling. - */ - $('#submit').click(function(){ - var form = $(this).parents('form'); - - if ( ! validateForm( form ) ) - return false; - - if ( addingTerm ) { - // If we're adding a term, noop the button to avoid duplicate requests. - return false; - } - - addingTerm = true; - form.find( '.submit .spinner' ).addClass( 'is-active' ); - - /** - * Does a request to the server to add a new term to the database - * - * @param {string} r The response from the server. - * - * @returns {void} - */ - $.post(ajaxurl, $('#addtag').serialize(), function(r){ - var res, parent, term, indent, i; - - addingTerm = false; - form.find( '.submit .spinner' ).removeClass( 'is-active' ); - - $('#ajax-response').empty(); - res = wpAjax.parseAjaxResponse( r, 'ajax-response' ); - if ( ! res || res.errors ) - return; - - parent = form.find( 'select#parent' ).val(); - - if ( parent > 0 && $('#tag-' + parent ).length > 0 ) // If the parent exists on this page, insert it below. Else insert it at the top of the list. - $( '.tags #tag-' + parent ).after( res.responses[0].supplemental.noparents ); // As the parent exists, Insert the version with - - - prefixed - else - $( '.tags' ).prepend( res.responses[0].supplemental.parents ); // As the parent is not visible, Insert the version with Parent - Child - ThisTerm - - $('.tags .no-items').remove(); - - if ( form.find('select#parent') ) { - // Parents field exists, Add new term to the list. - term = res.responses[1].supplemental; - - // Create an indent for the Parent field - indent = ''; - for ( i = 0; i < res.responses[1].position; i++ ) - indent += ' '; - - form.find( 'select#parent option:selected' ).after( '<option value="' + term.term_id + '">' + indent + term.name + '</option>' ); - } - - $('input[type="text"]:visible, textarea:visible', form).val(''); - }); - - return false; - }); - -}); diff --git a/srcs/wordpress/wp-admin/js/tags.min.js b/srcs/wordpress/wp-admin/js/tags.min.js deleted file mode 100644 index dc43b6c..0000000 --- a/srcs/wordpress/wp-admin/js/tags.min.js +++ /dev/null @@ -1 +0,0 @@ -jQuery(document).ready(function(i){var p=!1;i("#the-list").on("click",".delete-tag",function(){var t,e=i(this),n=e.parents("tr"),a=!0;return"undefined"!=showNotice&&(a=showNotice.warn()),a&&(t=e.attr("href").replace(/[^?]*\?/,"").replace(/action=delete/,"action=delete-tag"),i.post(ajaxurl,t,function(e){"1"==e?(i("#ajax-response").empty(),n.fadeOut("normal",function(){n.remove()}),i('select#parent option[value="'+t.match(/tag_ID=(\d+)/)[1]+'"]').remove(),i("a.tag-link-"+t.match(/tag_ID=(\d+)/)[1]).remove()):("-1"==e?i("#ajax-response").empty().append('<div class="error"><p>'+tagsl10n.noPerm+"</p></div>"):i("#ajax-response").empty().append('<div class="error"><p>'+tagsl10n.broken+"</p></div>"),n.children().css("backgroundColor",""))}),n.children().css("backgroundColor","#f33")),!1}),i("#edittag").on("click",".delete",function(e){if("undefined"==typeof showNotice)return!0;showNotice.warn()||e.preventDefault()}),i("#submit").click(function(){var o=i(this).parents("form");return validateForm(o)&&(p||(p=!0,o.find(".submit .spinner").addClass("is-active"),i.post(ajaxurl,i("#addtag").serialize(),function(e){var t,n,a,s,r;if(p=!1,o.find(".submit .spinner").removeClass("is-active"),i("#ajax-response").empty(),(t=wpAjax.parseAjaxResponse(e,"ajax-response"))&&!t.errors){if(0<(n=o.find("select#parent").val())&&0<i("#tag-"+n).length?i(".tags #tag-"+n).after(t.responses[0].supplemental.noparents):i(".tags").prepend(t.responses[0].supplemental.parents),i(".tags .no-items").remove(),o.find("select#parent")){for(a=t.responses[1].supplemental,s="",r=0;r<t.responses[1].position;r++)s+=" ";o.find("select#parent option:selected").after('<option value="'+a.term_id+'">'+s+a.name+"</option>")}i('input[type="text"]:visible, textarea:visible',o).val("")}}))),!1})});
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/theme-plugin-editor.js b/srcs/wordpress/wp-admin/js/theme-plugin-editor.js deleted file mode 100644 index 6127b2c..0000000 --- a/srcs/wordpress/wp-admin/js/theme-plugin-editor.js +++ /dev/null @@ -1,1006 +0,0 @@ -/** - * @output wp-admin/js/theme-plugin-editor.js - */ - -/* eslint no-magic-numbers: ["error", { "ignore": [-1, 0, 1] }] */ - -if ( ! window.wp ) { - window.wp = {}; -} - -wp.themePluginEditor = (function( $ ) { - 'use strict'; - var component, TreeLinks; - - component = { - l10n: { - lintError: { - singular: '', - plural: '' - }, - saveAlert: '', - saveError: '' - }, - codeEditor: {}, - instance: null, - noticeElements: {}, - dirty: false, - lintErrors: [] - }; - - /** - * Initialize component. - * - * @since 4.9.0 - * - * @param {jQuery} form - Form element. - * @param {object} settings - Settings. - * @param {object|boolean} settings.codeEditor - Code editor settings (or `false` if syntax highlighting is disabled). - * @returns {void} - */ - component.init = function init( form, settings ) { - - component.form = form; - if ( settings ) { - $.extend( component, settings ); - } - - component.noticeTemplate = wp.template( 'wp-file-editor-notice' ); - component.noticesContainer = component.form.find( '.editor-notices' ); - component.submitButton = component.form.find( ':input[name=submit]' ); - component.spinner = component.form.find( '.submit .spinner' ); - component.form.on( 'submit', component.submit ); - component.textarea = component.form.find( '#newcontent' ); - component.textarea.on( 'change', component.onChange ); - component.warning = $( '.file-editor-warning' ); - component.docsLookUpButton = component.form.find( '#docs-lookup' ); - component.docsLookUpList = component.form.find( '#docs-list' ); - - if ( component.warning.length > 0 ) { - component.showWarning(); - } - - if ( false !== component.codeEditor ) { - /* - * Defer adding notices until after DOM ready as workaround for WP Admin injecting - * its own managed dismiss buttons and also to prevent the editor from showing a notice - * when the file had linting errors to begin with. - */ - _.defer( function() { - component.initCodeEditor(); - } ); - } - - $( component.initFileBrowser ); - - $( window ).on( 'beforeunload', function() { - if ( component.dirty ) { - return component.l10n.saveAlert; - } - return undefined; - } ); - - component.docsLookUpList.on( 'change', function() { - var option = $( this ).val(); - if ( '' === option ) { - component.docsLookUpButton.prop( 'disabled', true ); - } else { - component.docsLookUpButton.prop( 'disabled', false ); - } - } ); - }; - - /** - * Set up and display the warning modal. - * - * @since 4.9.0 - * @returns {void} - */ - component.showWarning = function() { - // Get the text within the modal. - var rawMessage = component.warning.find( '.file-editor-warning-message' ).text(); - // Hide all the #wpwrap content from assistive technologies. - $( '#wpwrap' ).attr( 'aria-hidden', 'true' ); - // Detach the warning modal from its position and append it to the body. - $( document.body ) - .addClass( 'modal-open' ) - .append( component.warning.detach() ); - // Reveal the modal and set focus on the go back button. - component.warning - .removeClass( 'hidden' ) - .find( '.file-editor-warning-go-back' ).focus(); - // Get the links and buttons within the modal. - component.warningTabbables = component.warning.find( 'a, button' ); - // Attach event handlers. - component.warningTabbables.on( 'keydown', component.constrainTabbing ); - component.warning.on( 'click', '.file-editor-warning-dismiss', component.dismissWarning ); - // Make screen readers announce the warning message after a short delay (necessary for some screen readers). - setTimeout( function() { - wp.a11y.speak( wp.sanitize.stripTags( rawMessage.replace( /\s+/g, ' ' ) ), 'assertive' ); - }, 1000 ); - }; - - /** - * Constrain tabbing within the warning modal. - * - * @since 4.9.0 - * @param {object} event jQuery event object. - * @returns {void} - */ - component.constrainTabbing = function( event ) { - var firstTabbable, lastTabbable; - - if ( 9 !== event.which ) { - return; - } - - firstTabbable = component.warningTabbables.first()[0]; - lastTabbable = component.warningTabbables.last()[0]; - - if ( lastTabbable === event.target && ! event.shiftKey ) { - firstTabbable.focus(); - event.preventDefault(); - } else if ( firstTabbable === event.target && event.shiftKey ) { - lastTabbable.focus(); - event.preventDefault(); - } - }; - - /** - * Dismiss the warning modal. - * - * @since 4.9.0 - * @returns {void} - */ - component.dismissWarning = function() { - - wp.ajax.post( 'dismiss-wp-pointer', { - pointer: component.themeOrPlugin + '_editor_notice' - }); - - // Hide modal. - component.warning.remove(); - $( '#wpwrap' ).removeAttr( 'aria-hidden' ); - $( 'body' ).removeClass( 'modal-open' ); - }; - - /** - * Callback for when a change happens. - * - * @since 4.9.0 - * @returns {void} - */ - component.onChange = function() { - component.dirty = true; - component.removeNotice( 'file_saved' ); - }; - - /** - * Submit file via Ajax. - * - * @since 4.9.0 - * @param {jQuery.Event} event - Event. - * @returns {void} - */ - component.submit = function( event ) { - var data = {}, request; - event.preventDefault(); // Prevent form submission in favor of Ajax below. - $.each( component.form.serializeArray(), function() { - data[ this.name ] = this.value; - } ); - - // Use value from codemirror if present. - if ( component.instance ) { - data.newcontent = component.instance.codemirror.getValue(); - } - - if ( component.isSaving ) { - return; - } - - // Scroll ot the line that has the error. - if ( component.lintErrors.length ) { - component.instance.codemirror.setCursor( component.lintErrors[0].from.line ); - return; - } - - component.isSaving = true; - component.textarea.prop( 'readonly', true ); - if ( component.instance ) { - component.instance.codemirror.setOption( 'readOnly', true ); - } - - component.spinner.addClass( 'is-active' ); - request = wp.ajax.post( 'edit-theme-plugin-file', data ); - - // Remove previous save notice before saving. - if ( component.lastSaveNoticeCode ) { - component.removeNotice( component.lastSaveNoticeCode ); - } - - request.done( function( response ) { - component.lastSaveNoticeCode = 'file_saved'; - component.addNotice({ - code: component.lastSaveNoticeCode, - type: 'success', - message: response.message, - dismissible: true - }); - component.dirty = false; - } ); - - request.fail( function( response ) { - var notice = $.extend( - { - code: 'save_error', - message: component.l10n.saveError - }, - response, - { - type: 'error', - dismissible: true - } - ); - component.lastSaveNoticeCode = notice.code; - component.addNotice( notice ); - } ); - - request.always( function() { - component.spinner.removeClass( 'is-active' ); - component.isSaving = false; - - component.textarea.prop( 'readonly', false ); - if ( component.instance ) { - component.instance.codemirror.setOption( 'readOnly', false ); - } - } ); - }; - - /** - * Add notice. - * - * @since 4.9.0 - * - * @param {object} notice - Notice. - * @param {string} notice.code - Code. - * @param {string} notice.type - Type. - * @param {string} notice.message - Message. - * @param {boolean} [notice.dismissible=false] - Dismissible. - * @param {Function} [notice.onDismiss] - Callback for when a user dismisses the notice. - * @returns {jQuery} Notice element. - */ - component.addNotice = function( notice ) { - var noticeElement; - - if ( ! notice.code ) { - throw new Error( 'Missing code.' ); - } - - // Only let one notice of a given type be displayed at a time. - component.removeNotice( notice.code ); - - noticeElement = $( component.noticeTemplate( notice ) ); - noticeElement.hide(); - - noticeElement.find( '.notice-dismiss' ).on( 'click', function() { - component.removeNotice( notice.code ); - if ( notice.onDismiss ) { - notice.onDismiss( notice ); - } - } ); - - wp.a11y.speak( notice.message ); - - component.noticesContainer.append( noticeElement ); - noticeElement.slideDown( 'fast' ); - component.noticeElements[ notice.code ] = noticeElement; - return noticeElement; - }; - - /** - * Remove notice. - * - * @since 4.9.0 - * - * @param {string} code - Notice code. - * @returns {boolean} Whether a notice was removed. - */ - component.removeNotice = function( code ) { - if ( component.noticeElements[ code ] ) { - component.noticeElements[ code ].slideUp( 'fast', function() { - $( this ).remove(); - } ); - delete component.noticeElements[ code ]; - return true; - } - return false; - }; - - /** - * Initialize code editor. - * - * @since 4.9.0 - * @returns {void} - */ - component.initCodeEditor = function initCodeEditor() { - var codeEditorSettings, editor; - - codeEditorSettings = $.extend( {}, component.codeEditor ); - - /** - * Handle tabbing to the field before the editor. - * - * @since 4.9.0 - * - * @returns {void} - */ - codeEditorSettings.onTabPrevious = function() { - $( '#templateside' ).find( ':tabbable' ).last().focus(); - }; - - /** - * Handle tabbing to the field after the editor. - * - * @since 4.9.0 - * - * @returns {void} - */ - codeEditorSettings.onTabNext = function() { - $( '#template' ).find( ':tabbable:not(.CodeMirror-code)' ).first().focus(); - }; - - /** - * Handle change to the linting errors. - * - * @since 4.9.0 - * - * @param {Array} errors - List of linting errors. - * @returns {void} - */ - codeEditorSettings.onChangeLintingErrors = function( errors ) { - component.lintErrors = errors; - - // Only disable the button in onUpdateErrorNotice when there are errors so users can still feel they can click the button. - if ( 0 === errors.length ) { - component.submitButton.toggleClass( 'disabled', false ); - } - }; - - /** - * Update error notice. - * - * @since 4.9.0 - * - * @param {Array} errorAnnotations - Error annotations. - * @returns {void} - */ - codeEditorSettings.onUpdateErrorNotice = function onUpdateErrorNotice( errorAnnotations ) { - var message, noticeElement; - - component.submitButton.toggleClass( 'disabled', errorAnnotations.length > 0 ); - - if ( 0 !== errorAnnotations.length ) { - if ( 1 === errorAnnotations.length ) { - message = component.l10n.lintError.singular.replace( '%d', '1' ); - } else { - message = component.l10n.lintError.plural.replace( '%d', String( errorAnnotations.length ) ); - } - noticeElement = component.addNotice({ - code: 'lint_errors', - type: 'error', - message: message, - dismissible: false - }); - noticeElement.find( 'input[type=checkbox]' ).on( 'click', function() { - codeEditorSettings.onChangeLintingErrors( [] ); - component.removeNotice( 'lint_errors' ); - } ); - } else { - component.removeNotice( 'lint_errors' ); - } - }; - - editor = wp.codeEditor.initialize( $( '#newcontent' ), codeEditorSettings ); - editor.codemirror.on( 'change', component.onChange ); - - // Improve the editor accessibility. - $( editor.codemirror.display.lineDiv ) - .attr({ - role: 'textbox', - 'aria-multiline': 'true', - 'aria-labelledby': 'theme-plugin-editor-label', - 'aria-describedby': 'editor-keyboard-trap-help-1 editor-keyboard-trap-help-2 editor-keyboard-trap-help-3 editor-keyboard-trap-help-4' - }); - - // Focus the editor when clicking on its label. - $( '#theme-plugin-editor-label' ).on( 'click', function() { - editor.codemirror.focus(); - }); - - component.instance = editor; - }; - - /** - * Initialization of the file browser's folder states. - * - * @since 4.9.0 - * @returns {void} - */ - component.initFileBrowser = function initFileBrowser() { - - var $templateside = $( '#templateside' ); - - // Collapse all folders. - $templateside.find( '[role="group"]' ).parent().attr( 'aria-expanded', false ); - - // Expand ancestors to the current file. - $templateside.find( '.notice' ).parents( '[aria-expanded]' ).attr( 'aria-expanded', true ); - - // Find Tree elements and enhance them. - $templateside.find( '[role="tree"]' ).each( function() { - var treeLinks = new TreeLinks( this ); - treeLinks.init(); - } ); - - // Scroll the current file into view. - $templateside.find( '.current-file:first' ).each( function() { - if ( this.scrollIntoViewIfNeeded ) { - this.scrollIntoViewIfNeeded(); - } else { - this.scrollIntoView( false ); - } - } ); - }; - - /* jshint ignore:start */ - /* jscs:disable */ - /* eslint-disable */ - - /** - * Creates a new TreeitemLink. - * - * @since 4.9.0 - * @class - * @private - * @see {@link https://www.w3.org/TR/wai-aria-practices-1.1/examples/treeview/treeview-2/treeview-2b.html|W3C Treeview Example} - * @license W3C-20150513 - */ - var TreeitemLink = (function () { - /** - * This content is licensed according to the W3C Software License at - * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document - * - * File: TreeitemLink.js - * - * Desc: Treeitem widget that implements ARIA Authoring Practices - * for a tree being used as a file viewer - * - * Author: Jon Gunderson, Ku Ja Eun and Nicholas Hoyt - */ - - /** - * @constructor - * - * @desc - * Treeitem object for representing the state and user interactions for a - * treeItem widget - * - * @param node - * An element with the role=tree attribute - */ - - var TreeitemLink = function (node, treeObj, group) { - - // Check whether node is a DOM element - if (typeof node !== 'object') { - return; - } - - node.tabIndex = -1; - this.tree = treeObj; - this.groupTreeitem = group; - this.domNode = node; - this.label = node.textContent.trim(); - this.stopDefaultClick = false; - - if (node.getAttribute('aria-label')) { - this.label = node.getAttribute('aria-label').trim(); - } - - this.isExpandable = false; - this.isVisible = false; - this.inGroup = false; - - if (group) { - this.inGroup = true; - } - - var elem = node.firstElementChild; - - while (elem) { - - if (elem.tagName.toLowerCase() == 'ul') { - elem.setAttribute('role', 'group'); - this.isExpandable = true; - break; - } - - elem = elem.nextElementSibling; - } - - this.keyCode = Object.freeze({ - RETURN: 13, - SPACE: 32, - PAGEUP: 33, - PAGEDOWN: 34, - END: 35, - HOME: 36, - LEFT: 37, - UP: 38, - RIGHT: 39, - DOWN: 40 - }); - }; - - TreeitemLink.prototype.init = function () { - this.domNode.tabIndex = -1; - - if (!this.domNode.getAttribute('role')) { - this.domNode.setAttribute('role', 'treeitem'); - } - - this.domNode.addEventListener('keydown', this.handleKeydown.bind(this)); - this.domNode.addEventListener('click', this.handleClick.bind(this)); - this.domNode.addEventListener('focus', this.handleFocus.bind(this)); - this.domNode.addEventListener('blur', this.handleBlur.bind(this)); - - if (this.isExpandable) { - this.domNode.firstElementChild.addEventListener('mouseover', this.handleMouseOver.bind(this)); - this.domNode.firstElementChild.addEventListener('mouseout', this.handleMouseOut.bind(this)); - } - else { - this.domNode.addEventListener('mouseover', this.handleMouseOver.bind(this)); - this.domNode.addEventListener('mouseout', this.handleMouseOut.bind(this)); - } - }; - - TreeitemLink.prototype.isExpanded = function () { - - if (this.isExpandable) { - return this.domNode.getAttribute('aria-expanded') === 'true'; - } - - return false; - - }; - - /* EVENT HANDLERS */ - - TreeitemLink.prototype.handleKeydown = function (event) { - var tgt = event.currentTarget, - flag = false, - _char = event.key, - clickEvent; - - function isPrintableCharacter(str) { - return str.length === 1 && str.match(/\S/); - } - - function printableCharacter(item) { - if (_char == '*') { - item.tree.expandAllSiblingItems(item); - flag = true; - } - else { - if (isPrintableCharacter(_char)) { - item.tree.setFocusByFirstCharacter(item, _char); - flag = true; - } - } - } - - this.stopDefaultClick = false; - - if (event.altKey || event.ctrlKey || event.metaKey) { - return; - } - - if (event.shift) { - if (event.keyCode == this.keyCode.SPACE || event.keyCode == this.keyCode.RETURN) { - event.stopPropagation(); - this.stopDefaultClick = true; - } - else { - if (isPrintableCharacter(_char)) { - printableCharacter(this); - } - } - } - else { - switch (event.keyCode) { - case this.keyCode.SPACE: - case this.keyCode.RETURN: - if (this.isExpandable) { - if (this.isExpanded()) { - this.tree.collapseTreeitem(this); - } - else { - this.tree.expandTreeitem(this); - } - flag = true; - } - else { - event.stopPropagation(); - this.stopDefaultClick = true; - } - break; - - case this.keyCode.UP: - this.tree.setFocusToPreviousItem(this); - flag = true; - break; - - case this.keyCode.DOWN: - this.tree.setFocusToNextItem(this); - flag = true; - break; - - case this.keyCode.RIGHT: - if (this.isExpandable) { - if (this.isExpanded()) { - this.tree.setFocusToNextItem(this); - } - else { - this.tree.expandTreeitem(this); - } - } - flag = true; - break; - - case this.keyCode.LEFT: - if (this.isExpandable && this.isExpanded()) { - this.tree.collapseTreeitem(this); - flag = true; - } - else { - if (this.inGroup) { - this.tree.setFocusToParentItem(this); - flag = true; - } - } - break; - - case this.keyCode.HOME: - this.tree.setFocusToFirstItem(); - flag = true; - break; - - case this.keyCode.END: - this.tree.setFocusToLastItem(); - flag = true; - break; - - default: - if (isPrintableCharacter(_char)) { - printableCharacter(this); - } - break; - } - } - - if (flag) { - event.stopPropagation(); - event.preventDefault(); - } - }; - - TreeitemLink.prototype.handleClick = function (event) { - - // only process click events that directly happened on this treeitem - if (event.target !== this.domNode && event.target !== this.domNode.firstElementChild) { - return; - } - - if (this.isExpandable) { - if (this.isExpanded()) { - this.tree.collapseTreeitem(this); - } - else { - this.tree.expandTreeitem(this); - } - event.stopPropagation(); - } - }; - - TreeitemLink.prototype.handleFocus = function (event) { - var node = this.domNode; - if (this.isExpandable) { - node = node.firstElementChild; - } - node.classList.add('focus'); - }; - - TreeitemLink.prototype.handleBlur = function (event) { - var node = this.domNode; - if (this.isExpandable) { - node = node.firstElementChild; - } - node.classList.remove('focus'); - }; - - TreeitemLink.prototype.handleMouseOver = function (event) { - event.currentTarget.classList.add('hover'); - }; - - TreeitemLink.prototype.handleMouseOut = function (event) { - event.currentTarget.classList.remove('hover'); - }; - - return TreeitemLink; - })(); - - /** - * Creates a new TreeLinks. - * - * @since 4.9.0 - * @class - * @private - * @see {@link https://www.w3.org/TR/wai-aria-practices-1.1/examples/treeview/treeview-2/treeview-2b.html|W3C Treeview Example} - * @license W3C-20150513 - */ - TreeLinks = (function () { - /* - * This content is licensed according to the W3C Software License at - * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document - * - * File: TreeLinks.js - * - * Desc: Tree widget that implements ARIA Authoring Practices - * for a tree being used as a file viewer - * - * Author: Jon Gunderson, Ku Ja Eun and Nicholas Hoyt - */ - - /* - * @constructor - * - * @desc - * Tree item object for representing the state and user interactions for a - * tree widget - * - * @param node - * An element with the role=tree attribute - */ - - var TreeLinks = function (node) { - // Check whether node is a DOM element - if (typeof node !== 'object') { - return; - } - - this.domNode = node; - - this.treeitems = []; - this.firstChars = []; - - this.firstTreeitem = null; - this.lastTreeitem = null; - - }; - - TreeLinks.prototype.init = function () { - - function findTreeitems(node, tree, group) { - - var elem = node.firstElementChild; - var ti = group; - - while (elem) { - - if ((elem.tagName.toLowerCase() === 'li' && elem.firstElementChild.tagName.toLowerCase() === 'span') || elem.tagName.toLowerCase() === 'a') { - ti = new TreeitemLink(elem, tree, group); - ti.init(); - tree.treeitems.push(ti); - tree.firstChars.push(ti.label.substring(0, 1).toLowerCase()); - } - - if (elem.firstElementChild) { - findTreeitems(elem, tree, ti); - } - - elem = elem.nextElementSibling; - } - } - - // initialize pop up menus - if (!this.domNode.getAttribute('role')) { - this.domNode.setAttribute('role', 'tree'); - } - - findTreeitems(this.domNode, this, false); - - this.updateVisibleTreeitems(); - - this.firstTreeitem.domNode.tabIndex = 0; - - }; - - TreeLinks.prototype.setFocusToItem = function (treeitem) { - - for (var i = 0; i < this.treeitems.length; i++) { - var ti = this.treeitems[i]; - - if (ti === treeitem) { - ti.domNode.tabIndex = 0; - ti.domNode.focus(); - } - else { - ti.domNode.tabIndex = -1; - } - } - - }; - - TreeLinks.prototype.setFocusToNextItem = function (currentItem) { - - var nextItem = false; - - for (var i = (this.treeitems.length - 1); i >= 0; i--) { - var ti = this.treeitems[i]; - if (ti === currentItem) { - break; - } - if (ti.isVisible) { - nextItem = ti; - } - } - - if (nextItem) { - this.setFocusToItem(nextItem); - } - - }; - - TreeLinks.prototype.setFocusToPreviousItem = function (currentItem) { - - var prevItem = false; - - for (var i = 0; i < this.treeitems.length; i++) { - var ti = this.treeitems[i]; - if (ti === currentItem) { - break; - } - if (ti.isVisible) { - prevItem = ti; - } - } - - if (prevItem) { - this.setFocusToItem(prevItem); - } - }; - - TreeLinks.prototype.setFocusToParentItem = function (currentItem) { - - if (currentItem.groupTreeitem) { - this.setFocusToItem(currentItem.groupTreeitem); - } - }; - - TreeLinks.prototype.setFocusToFirstItem = function () { - this.setFocusToItem(this.firstTreeitem); - }; - - TreeLinks.prototype.setFocusToLastItem = function () { - this.setFocusToItem(this.lastTreeitem); - }; - - TreeLinks.prototype.expandTreeitem = function (currentItem) { - - if (currentItem.isExpandable) { - currentItem.domNode.setAttribute('aria-expanded', true); - this.updateVisibleTreeitems(); - } - - }; - - TreeLinks.prototype.expandAllSiblingItems = function (currentItem) { - for (var i = 0; i < this.treeitems.length; i++) { - var ti = this.treeitems[i]; - - if ((ti.groupTreeitem === currentItem.groupTreeitem) && ti.isExpandable) { - this.expandTreeitem(ti); - } - } - - }; - - TreeLinks.prototype.collapseTreeitem = function (currentItem) { - - var groupTreeitem = false; - - if (currentItem.isExpanded()) { - groupTreeitem = currentItem; - } - else { - groupTreeitem = currentItem.groupTreeitem; - } - - if (groupTreeitem) { - groupTreeitem.domNode.setAttribute('aria-expanded', false); - this.updateVisibleTreeitems(); - this.setFocusToItem(groupTreeitem); - } - - }; - - TreeLinks.prototype.updateVisibleTreeitems = function () { - - this.firstTreeitem = this.treeitems[0]; - - for (var i = 0; i < this.treeitems.length; i++) { - var ti = this.treeitems[i]; - - var parent = ti.domNode.parentNode; - - ti.isVisible = true; - - while (parent && (parent !== this.domNode)) { - - if (parent.getAttribute('aria-expanded') == 'false') { - ti.isVisible = false; - } - parent = parent.parentNode; - } - - if (ti.isVisible) { - this.lastTreeitem = ti; - } - } - - }; - - TreeLinks.prototype.setFocusByFirstCharacter = function (currentItem, _char) { - var start, index; - _char = _char.toLowerCase(); - - // Get start index for search based on position of currentItem - start = this.treeitems.indexOf(currentItem) + 1; - if (start === this.treeitems.length) { - start = 0; - } - - // Check remaining slots in the menu - index = this.getIndexFirstChars(start, _char); - - // If not found in remaining slots, check from beginning - if (index === -1) { - index = this.getIndexFirstChars(0, _char); - } - - // If match was found... - if (index > -1) { - this.setFocusToItem(this.treeitems[index]); - } - }; - - TreeLinks.prototype.getIndexFirstChars = function (startIndex, _char) { - for (var i = startIndex; i < this.firstChars.length; i++) { - if (this.treeitems[i].isVisible) { - if (_char === this.firstChars[i]) { - return i; - } - } - } - return -1; - }; - - return TreeLinks; - })(); - - /* jshint ignore:end */ - /* jscs:enable */ - /* eslint-enable */ - - return component; -})( jQuery ); diff --git a/srcs/wordpress/wp-admin/js/theme-plugin-editor.min.js b/srcs/wordpress/wp-admin/js/theme-plugin-editor.min.js deleted file mode 100644 index 4f5fe69..0000000 --- a/srcs/wordpress/wp-admin/js/theme-plugin-editor.min.js +++ /dev/null @@ -1 +0,0 @@ -window.wp||(window.wp={}),wp.themePluginEditor=function(s){"use strict";var o,t;o={l10n:{lintError:{singular:"",plural:""},saveAlert:"",saveError:""},codeEditor:{},instance:null,noticeElements:{},dirty:!1,lintErrors:[],init:function(e,t){o.form=e,t&&s.extend(o,t),o.noticeTemplate=wp.template("wp-file-editor-notice"),o.noticesContainer=o.form.find(".editor-notices"),o.submitButton=o.form.find(":input[name=submit]"),o.spinner=o.form.find(".submit .spinner"),o.form.on("submit",o.submit),o.textarea=o.form.find("#newcontent"),o.textarea.on("change",o.onChange),o.warning=s(".file-editor-warning"),o.docsLookUpButton=o.form.find("#docs-lookup"),o.docsLookUpList=o.form.find("#docs-list"),0<o.warning.length&&o.showWarning(),!1!==o.codeEditor&&_.defer(function(){o.initCodeEditor()}),s(o.initFileBrowser),s(window).on("beforeunload",function(){if(o.dirty)return o.l10n.saveAlert}),o.docsLookUpList.on("change",function(){""===s(this).val()?o.docsLookUpButton.prop("disabled",!0):o.docsLookUpButton.prop("disabled",!1)})},showWarning:function(){var e=o.warning.find(".file-editor-warning-message").text();s("#wpwrap").attr("aria-hidden","true"),s(document.body).addClass("modal-open").append(o.warning.detach()),o.warning.removeClass("hidden").find(".file-editor-warning-go-back").focus(),o.warningTabbables=o.warning.find("a, button"),o.warningTabbables.on("keydown",o.constrainTabbing),o.warning.on("click",".file-editor-warning-dismiss",o.dismissWarning),setTimeout(function(){wp.a11y.speak(wp.sanitize.stripTags(e.replace(/\s+/g," ")),"assertive")},1e3)},constrainTabbing:function(e){var t,i;9===e.which&&(t=o.warningTabbables.first()[0],(i=o.warningTabbables.last()[0])!==e.target||e.shiftKey?t===e.target&&e.shiftKey&&(i.focus(),e.preventDefault()):(t.focus(),e.preventDefault()))},dismissWarning:function(){wp.ajax.post("dismiss-wp-pointer",{pointer:o.themeOrPlugin+"_editor_notice"}),o.warning.remove(),s("#wpwrap").removeAttr("aria-hidden"),s("body").removeClass("modal-open")},onChange:function(){o.dirty=!0,o.removeNotice("file_saved")},submit:function(e){var t,i={};e.preventDefault(),s.each(o.form.serializeArray(),function(){i[this.name]=this.value}),o.instance&&(i.newcontent=o.instance.codemirror.getValue()),o.isSaving||(o.lintErrors.length?o.instance.codemirror.setCursor(o.lintErrors[0].from.line):(o.isSaving=!0,o.textarea.prop("readonly",!0),o.instance&&o.instance.codemirror.setOption("readOnly",!0),o.spinner.addClass("is-active"),t=wp.ajax.post("edit-theme-plugin-file",i),o.lastSaveNoticeCode&&o.removeNotice(o.lastSaveNoticeCode),t.done(function(e){o.lastSaveNoticeCode="file_saved",o.addNotice({code:o.lastSaveNoticeCode,type:"success",message:e.message,dismissible:!0}),o.dirty=!1}),t.fail(function(e){var t=s.extend({code:"save_error",message:o.l10n.saveError},e,{type:"error",dismissible:!0});o.lastSaveNoticeCode=t.code,o.addNotice(t)}),t.always(function(){o.spinner.removeClass("is-active"),o.isSaving=!1,o.textarea.prop("readonly",!1),o.instance&&o.instance.codemirror.setOption("readOnly",!1)})))},addNotice:function(e){var t;if(!e.code)throw new Error("Missing code.");return o.removeNotice(e.code),(t=s(o.noticeTemplate(e))).hide(),t.find(".notice-dismiss").on("click",function(){o.removeNotice(e.code),e.onDismiss&&e.onDismiss(e)}),wp.a11y.speak(e.message),o.noticesContainer.append(t),t.slideDown("fast"),o.noticeElements[e.code]=t},removeNotice:function(e){return!!o.noticeElements[e]&&(o.noticeElements[e].slideUp("fast",function(){s(this).remove()}),delete o.noticeElements[e],!0)},initCodeEditor:function(){var i,e;(i=s.extend({},o.codeEditor)).onTabPrevious=function(){s("#templateside").find(":tabbable").last().focus()},i.onTabNext=function(){s("#template").find(":tabbable:not(.CodeMirror-code)").first().focus()},i.onChangeLintingErrors=function(e){0===(o.lintErrors=e).length&&o.submitButton.toggleClass("disabled",!1)},i.onUpdateErrorNotice=function(e){var t;o.submitButton.toggleClass("disabled",0<e.length),0!==e.length?(t=1===e.length?o.l10n.lintError.singular.replace("%d","1"):o.l10n.lintError.plural.replace("%d",String(e.length)),o.addNotice({code:"lint_errors",type:"error",message:t,dismissible:!1}).find("input[type=checkbox]").on("click",function(){i.onChangeLintingErrors([]),o.removeNotice("lint_errors")})):o.removeNotice("lint_errors")},(e=wp.codeEditor.initialize(s("#newcontent"),i)).codemirror.on("change",o.onChange),s(e.codemirror.display.lineDiv).attr({role:"textbox","aria-multiline":"true","aria-labelledby":"theme-plugin-editor-label","aria-describedby":"editor-keyboard-trap-help-1 editor-keyboard-trap-help-2 editor-keyboard-trap-help-3 editor-keyboard-trap-help-4"}),s("#theme-plugin-editor-label").on("click",function(){e.codemirror.focus()}),o.instance=e},initFileBrowser:function(){var e=s("#templateside");e.find('[role="group"]').parent().attr("aria-expanded",!1),e.find(".notice").parents("[aria-expanded]").attr("aria-expanded",!0),e.find('[role="tree"]').each(function(){new t(this).init()}),e.find(".current-file:first").each(function(){this.scrollIntoViewIfNeeded?this.scrollIntoViewIfNeeded():this.scrollIntoView(!1)})}};var n=(e.prototype.init=function(){this.domNode.tabIndex=-1,this.domNode.getAttribute("role")||this.domNode.setAttribute("role","treeitem"),this.domNode.addEventListener("keydown",this.handleKeydown.bind(this)),this.domNode.addEventListener("click",this.handleClick.bind(this)),this.domNode.addEventListener("focus",this.handleFocus.bind(this)),this.domNode.addEventListener("blur",this.handleBlur.bind(this)),this.isExpandable?(this.domNode.firstElementChild.addEventListener("mouseover",this.handleMouseOver.bind(this)),this.domNode.firstElementChild.addEventListener("mouseout",this.handleMouseOut.bind(this))):(this.domNode.addEventListener("mouseover",this.handleMouseOver.bind(this)),this.domNode.addEventListener("mouseout",this.handleMouseOut.bind(this)))},e.prototype.isExpanded=function(){return!!this.isExpandable&&"true"===this.domNode.getAttribute("aria-expanded")},e.prototype.handleKeydown=function(e){e.currentTarget;var t=!1,i=e.key;function s(e){return 1===e.length&&e.match(/\S/)}function o(e){"*"==i?(e.tree.expandAllSiblingItems(e),t=!0):s(i)&&(e.tree.setFocusByFirstCharacter(e,i),t=!0)}if(this.stopDefaultClick=!1,!(e.altKey||e.ctrlKey||e.metaKey)){if(e.shift)e.keyCode==this.keyCode.SPACE||e.keyCode==this.keyCode.RETURN?(e.stopPropagation(),this.stopDefaultClick=!0):s(i)&&o(this);else switch(e.keyCode){case this.keyCode.SPACE:case this.keyCode.RETURN:this.isExpandable?(this.isExpanded()?this.tree.collapseTreeitem(this):this.tree.expandTreeitem(this),t=!0):(e.stopPropagation(),this.stopDefaultClick=!0);break;case this.keyCode.UP:this.tree.setFocusToPreviousItem(this),t=!0;break;case this.keyCode.DOWN:this.tree.setFocusToNextItem(this),t=!0;break;case this.keyCode.RIGHT:this.isExpandable&&(this.isExpanded()?this.tree.setFocusToNextItem(this):this.tree.expandTreeitem(this)),t=!0;break;case this.keyCode.LEFT:this.isExpandable&&this.isExpanded()?(this.tree.collapseTreeitem(this),t=!0):this.inGroup&&(this.tree.setFocusToParentItem(this),t=!0);break;case this.keyCode.HOME:this.tree.setFocusToFirstItem(),t=!0;break;case this.keyCode.END:this.tree.setFocusToLastItem(),t=!0;break;default:s(i)&&o(this)}t&&(e.stopPropagation(),e.preventDefault())}},e.prototype.handleClick=function(e){e.target!==this.domNode&&e.target!==this.domNode.firstElementChild||this.isExpandable&&(this.isExpanded()?this.tree.collapseTreeitem(this):this.tree.expandTreeitem(this),e.stopPropagation())},e.prototype.handleFocus=function(e){var t=this.domNode;this.isExpandable&&(t=t.firstElementChild),t.classList.add("focus")},e.prototype.handleBlur=function(e){var t=this.domNode;this.isExpandable&&(t=t.firstElementChild),t.classList.remove("focus")},e.prototype.handleMouseOver=function(e){e.currentTarget.classList.add("hover")},e.prototype.handleMouseOut=function(e){e.currentTarget.classList.remove("hover")},e);function e(e,t,i){if("object"==typeof e){e.tabIndex=-1,this.tree=t,this.groupTreeitem=i,this.domNode=e,this.label=e.textContent.trim(),this.stopDefaultClick=!1,e.getAttribute("aria-label")&&(this.label=e.getAttribute("aria-label").trim()),this.isExpandable=!1,this.isVisible=!1,this.inGroup=!1,i&&(this.inGroup=!0);for(var s=e.firstElementChild;s;){if("ul"==s.tagName.toLowerCase()){s.setAttribute("role","group"),this.isExpandable=!0;break}s=s.nextElementSibling}this.keyCode=Object.freeze({RETURN:13,SPACE:32,PAGEUP:33,PAGEDOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40})}}function i(e){"object"==typeof e&&(this.domNode=e,this.treeitems=[],this.firstChars=[],this.firstTreeitem=null,this.lastTreeitem=null)}return i.prototype.init=function(){this.domNode.getAttribute("role")||this.domNode.setAttribute("role","tree"),function e(t,i,s){for(var o=t.firstElementChild,r=s;o;)("li"===o.tagName.toLowerCase()&&"span"===o.firstElementChild.tagName.toLowerCase()||"a"===o.tagName.toLowerCase())&&((r=new n(o,i,s)).init(),i.treeitems.push(r),i.firstChars.push(r.label.substring(0,1).toLowerCase())),o.firstElementChild&&e(o,i,r),o=o.nextElementSibling}(this.domNode,this,!1),this.updateVisibleTreeitems(),this.firstTreeitem.domNode.tabIndex=0},i.prototype.setFocusToItem=function(e){for(var t=0;t<this.treeitems.length;t++){var i=this.treeitems[t];i===e?(i.domNode.tabIndex=0,i.domNode.focus()):i.domNode.tabIndex=-1}},i.prototype.setFocusToNextItem=function(e){for(var t=!1,i=this.treeitems.length-1;0<=i;i--){var s=this.treeitems[i];if(s===e)break;s.isVisible&&(t=s)}t&&this.setFocusToItem(t)},i.prototype.setFocusToPreviousItem=function(e){for(var t=!1,i=0;i<this.treeitems.length;i++){var s=this.treeitems[i];if(s===e)break;s.isVisible&&(t=s)}t&&this.setFocusToItem(t)},i.prototype.setFocusToParentItem=function(e){e.groupTreeitem&&this.setFocusToItem(e.groupTreeitem)},i.prototype.setFocusToFirstItem=function(){this.setFocusToItem(this.firstTreeitem)},i.prototype.setFocusToLastItem=function(){this.setFocusToItem(this.lastTreeitem)},i.prototype.expandTreeitem=function(e){e.isExpandable&&(e.domNode.setAttribute("aria-expanded",!0),this.updateVisibleTreeitems())},i.prototype.expandAllSiblingItems=function(e){for(var t=0;t<this.treeitems.length;t++){var i=this.treeitems[t];i.groupTreeitem===e.groupTreeitem&&i.isExpandable&&this.expandTreeitem(i)}},i.prototype.collapseTreeitem=function(e){var t=!1;(t=e.isExpanded()?e:e.groupTreeitem)&&(t.domNode.setAttribute("aria-expanded",!1),this.updateVisibleTreeitems(),this.setFocusToItem(t))},i.prototype.updateVisibleTreeitems=function(){this.firstTreeitem=this.treeitems[0];for(var e=0;e<this.treeitems.length;e++){var t=this.treeitems[e],i=t.domNode.parentNode;for(t.isVisible=!0;i&&i!==this.domNode;)"false"==i.getAttribute("aria-expanded")&&(t.isVisible=!1),i=i.parentNode;t.isVisible&&(this.lastTreeitem=t)}},i.prototype.setFocusByFirstCharacter=function(e,t){var i,s;t=t.toLowerCase(),(i=this.treeitems.indexOf(e)+1)===this.treeitems.length&&(i=0),-1===(s=this.getIndexFirstChars(i,t))&&(s=this.getIndexFirstChars(0,t)),-1<s&&this.setFocusToItem(this.treeitems[s])},i.prototype.getIndexFirstChars=function(e,t){for(var i=e;i<this.firstChars.length;i++)if(this.treeitems[i].isVisible&&t===this.firstChars[i])return i;return-1},t=i,o}(jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/theme.js b/srcs/wordpress/wp-admin/js/theme.js deleted file mode 100644 index 74a90cc..0000000 --- a/srcs/wordpress/wp-admin/js/theme.js +++ /dev/null @@ -1,2070 +0,0 @@ -/** - * @output wp-admin/js/theme.js - */ - -/* global _wpThemeSettings, confirm, tb_position */ -window.wp = window.wp || {}; - -( function($) { - -// Set up our namespace... -var themes, l10n; -themes = wp.themes = wp.themes || {}; - -// Store the theme data and settings for organized and quick access -// themes.data.settings, themes.data.themes, themes.data.l10n -themes.data = _wpThemeSettings; -l10n = themes.data.l10n; - -// Shortcut for isInstall check -themes.isInstall = !! themes.data.settings.isInstall; - -// Setup app structure -_.extend( themes, { model: {}, view: {}, routes: {}, router: {}, template: wp.template }); - -themes.Model = Backbone.Model.extend({ - // Adds attributes to the default data coming through the .org themes api - // Map `id` to `slug` for shared code - initialize: function() { - var description; - - // If theme is already installed, set an attribute. - if ( _.indexOf( themes.data.installedThemes, this.get( 'slug' ) ) !== -1 ) { - this.set({ installed: true }); - } - - // Set the attributes - this.set({ - // slug is for installation, id is for existing. - id: this.get( 'slug' ) || this.get( 'id' ) - }); - - // Map `section.description` to `description` - // as the API sometimes returns it differently - if ( this.has( 'sections' ) ) { - description = this.get( 'sections' ).description; - this.set({ description: description }); - } - } -}); - -// Main view controller for themes.php -// Unifies and renders all available views -themes.view.Appearance = wp.Backbone.View.extend({ - - el: '#wpbody-content .wrap .theme-browser', - - window: $( window ), - // Pagination instance - page: 0, - - // Sets up a throttler for binding to 'scroll' - initialize: function( options ) { - // Scroller checks how far the scroll position is - _.bindAll( this, 'scroller' ); - - this.SearchView = options.SearchView ? options.SearchView : themes.view.Search; - // Bind to the scroll event and throttle - // the results from this.scroller - this.window.bind( 'scroll', _.throttle( this.scroller, 300 ) ); - }, - - // Main render control - render: function() { - // Setup the main theme view - // with the current theme collection - this.view = new themes.view.Themes({ - collection: this.collection, - parent: this - }); - - // Render search form. - this.search(); - - this.$el.removeClass( 'search-loading' ); - - // Render and append - this.view.render(); - this.$el.empty().append( this.view.el ).addClass( 'rendered' ); - }, - - // Defines search element container - searchContainer: $( '.search-form' ), - - // Search input and view - // for current theme collection - search: function() { - var view, - self = this; - - // Don't render the search if there is only one theme - if ( themes.data.themes.length === 1 ) { - return; - } - - view = new this.SearchView({ - collection: self.collection, - parent: this - }); - self.SearchView = view; - - // Render and append after screen title - view.render(); - this.searchContainer - .append( $.parseHTML( '<label class="screen-reader-text" for="wp-filter-search-input">' + l10n.search + '</label>' ) ) - .append( view.el ) - .on( 'submit', function( event ) { - event.preventDefault(); - }); - }, - - // Checks when the user gets close to the bottom - // of the mage and triggers a theme:scroll event - scroller: function() { - var self = this, - bottom, threshold; - - bottom = this.window.scrollTop() + self.window.height(); - threshold = self.$el.offset().top + self.$el.outerHeight( false ) - self.window.height(); - threshold = Math.round( threshold * 0.9 ); - - if ( bottom > threshold ) { - this.trigger( 'theme:scroll' ); - } - } -}); - -// Set up the Collection for our theme data -// @has 'id' 'name' 'screenshot' 'author' 'authorURI' 'version' 'active' ... -themes.Collection = Backbone.Collection.extend({ - - model: themes.Model, - - // Search terms - terms: '', - - // Controls searching on the current theme collection - // and triggers an update event - doSearch: function( value ) { - - // Don't do anything if we've already done this search - // Useful because the Search handler fires multiple times per keystroke - if ( this.terms === value ) { - return; - } - - // Updates terms with the value passed - this.terms = value; - - // If we have terms, run a search... - if ( this.terms.length > 0 ) { - this.search( this.terms ); - } - - // If search is blank, show all themes - // Useful for resetting the views when you clean the input - if ( this.terms === '' ) { - this.reset( themes.data.themes ); - $( 'body' ).removeClass( 'no-results' ); - } - - // Trigger a 'themes:update' event - this.trigger( 'themes:update' ); - }, - - // Performs a search within the collection - // @uses RegExp - search: function( term ) { - var match, results, haystack, name, description, author; - - // Start with a full collection - this.reset( themes.data.themes, { silent: true } ); - - // Trim the term - term = term.trim(); - - // Escape the term string for RegExp meta characters - term = term.replace( /[-\/\\^$*+?.()|[\]{}]/g, '\\$&' ); - - // Consider spaces as word delimiters and match the whole string - // so matching terms can be combined - term = term.replace( / /g, ')(?=.*' ); - match = new RegExp( '^(?=.*' + term + ').+', 'i' ); - - // Find results - // _.filter and .test - results = this.filter( function( data ) { - name = data.get( 'name' ).replace( /(<([^>]+)>)/ig, '' ); - description = data.get( 'description' ).replace( /(<([^>]+)>)/ig, '' ); - author = data.get( 'author' ).replace( /(<([^>]+)>)/ig, '' ); - - haystack = _.union( [ name, data.get( 'id' ), description, author, data.get( 'tags' ) ] ); - - if ( match.test( data.get( 'author' ) ) && term.length > 2 ) { - data.set( 'displayAuthor', true ); - } - - return match.test( haystack ); - }); - - if ( results.length === 0 ) { - this.trigger( 'query:empty' ); - } else { - $( 'body' ).removeClass( 'no-results' ); - } - - this.reset( results ); - }, - - // Paginates the collection with a helper method - // that slices the collection - paginate: function( instance ) { - var collection = this; - instance = instance || 0; - - // Themes per instance are set at 20 - collection = _( collection.rest( 20 * instance ) ); - collection = _( collection.first( 20 ) ); - - return collection; - }, - - count: false, - - // Handles requests for more themes - // and caches results - // - // When we are missing a cache object we fire an apiCall() - // which triggers events of `query:success` or `query:fail` - query: function( request ) { - /** - * @static - * @type Array - */ - var queries = this.queries, - self = this, - query, isPaginated, count; - - // Store current query request args - // for later use with the event `theme:end` - this.currentQuery.request = request; - - // Search the query cache for matches. - query = _.find( queries, function( query ) { - return _.isEqual( query.request, request ); - }); - - // If the request matches the stored currentQuery.request - // it means we have a paginated request. - isPaginated = _.has( request, 'page' ); - - // Reset the internal api page counter for non paginated queries. - if ( ! isPaginated ) { - this.currentQuery.page = 1; - } - - // Otherwise, send a new API call and add it to the cache. - if ( ! query && ! isPaginated ) { - query = this.apiCall( request ).done( function( data ) { - - // Update the collection with the queried data. - if ( data.themes ) { - self.reset( data.themes ); - count = data.info.results; - // Store the results and the query request - queries.push( { themes: data.themes, request: request, total: count } ); - } - - // Trigger a collection refresh event - // and a `query:success` event with a `count` argument. - self.trigger( 'themes:update' ); - self.trigger( 'query:success', count ); - - if ( data.themes && data.themes.length === 0 ) { - self.trigger( 'query:empty' ); - } - - }).fail( function() { - self.trigger( 'query:fail' ); - }); - } else { - // If it's a paginated request we need to fetch more themes... - if ( isPaginated ) { - return this.apiCall( request, isPaginated ).done( function( data ) { - // Add the new themes to the current collection - // @todo update counter - self.add( data.themes ); - self.trigger( 'query:success' ); - - // We are done loading themes for now. - self.loadingThemes = false; - - }).fail( function() { - self.trigger( 'query:fail' ); - }); - } - - if ( query.themes.length === 0 ) { - self.trigger( 'query:empty' ); - } else { - $( 'body' ).removeClass( 'no-results' ); - } - - // Only trigger an update event since we already have the themes - // on our cached object - if ( _.isNumber( query.total ) ) { - this.count = query.total; - } - - this.reset( query.themes ); - if ( ! query.total ) { - this.count = this.length; - } - - this.trigger( 'themes:update' ); - this.trigger( 'query:success', this.count ); - } - }, - - // Local cache array for API queries - queries: [], - - // Keep track of current query so we can handle pagination - currentQuery: { - page: 1, - request: {} - }, - - // Send request to api.wordpress.org/themes - apiCall: function( request, paginated ) { - return wp.ajax.send( 'query-themes', { - data: { - // Request data - request: _.extend({ - per_page: 100 - }, request) - }, - - beforeSend: function() { - if ( ! paginated ) { - // Spin it - $( 'body' ).addClass( 'loading-content' ).removeClass( 'no-results' ); - } - } - }); - }, - - // Static status controller for when we are loading themes. - loadingThemes: false -}); - -// This is the view that controls each theme item -// that will be displayed on the screen -themes.view.Theme = wp.Backbone.View.extend({ - - // Wrap theme data on a div.theme element - className: 'theme', - - // Reflects which theme view we have - // 'grid' (default) or 'detail' - state: 'grid', - - // The HTML template for each element to be rendered - html: themes.template( 'theme' ), - - events: { - 'click': themes.isInstall ? 'preview': 'expand', - 'keydown': themes.isInstall ? 'preview': 'expand', - 'touchend': themes.isInstall ? 'preview': 'expand', - 'keyup': 'addFocus', - 'touchmove': 'preventExpand', - 'click .theme-install': 'installTheme', - 'click .update-message': 'updateTheme' - }, - - touchDrag: false, - - initialize: function() { - this.model.on( 'change', this.render, this ); - }, - - render: function() { - var data = this.model.toJSON(); - - // Render themes using the html template - this.$el.html( this.html( data ) ).attr({ - tabindex: 0, - 'aria-describedby' : data.id + '-action ' + data.id + '-name', - 'data-slug': data.id - }); - - // Renders active theme styles - this.activeTheme(); - - if ( this.model.get( 'displayAuthor' ) ) { - this.$el.addClass( 'display-author' ); - } - }, - - // Adds a class to the currently active theme - // and to the overlay in detailed view mode - activeTheme: function() { - if ( this.model.get( 'active' ) ) { - this.$el.addClass( 'active' ); - } - }, - - // Add class of focus to the theme we are focused on. - addFocus: function() { - var $themeToFocus = ( $( ':focus' ).hasClass( 'theme' ) ) ? $( ':focus' ) : $(':focus').parents('.theme'); - - $('.theme.focus').removeClass('focus'); - $themeToFocus.addClass('focus'); - }, - - // Single theme overlay screen - // It's shown when clicking a theme - expand: function( event ) { - var self = this; - - event = event || window.event; - - // 'enter' and 'space' keys expand the details view when a theme is :focused - if ( event.type === 'keydown' && ( event.which !== 13 && event.which !== 32 ) ) { - return; - } - - // Bail if the user scrolled on a touch device - if ( this.touchDrag === true ) { - return this.touchDrag = false; - } - - // Prevent the modal from showing when the user clicks - // one of the direct action buttons - if ( $( event.target ).is( '.theme-actions a' ) ) { - return; - } - - // Prevent the modal from showing when the user clicks one of the direct action buttons. - if ( $( event.target ).is( '.theme-actions a, .update-message, .button-link, .notice-dismiss' ) ) { - return; - } - - // Set focused theme to current element - themes.focusedTheme = this.$el; - - this.trigger( 'theme:expand', self.model.cid ); - }, - - preventExpand: function() { - this.touchDrag = true; - }, - - preview: function( event ) { - var self = this, - current, preview; - - event = event || window.event; - - // Bail if the user scrolled on a touch device - if ( this.touchDrag === true ) { - return this.touchDrag = false; - } - - // Allow direct link path to installing a theme. - if ( $( event.target ).not( '.install-theme-preview' ).parents( '.theme-actions' ).length ) { - return; - } - - // 'enter' and 'space' keys expand the details view when a theme is :focused - if ( event.type === 'keydown' && ( event.which !== 13 && event.which !== 32 ) ) { - return; - } - - // pressing enter while focused on the buttons shouldn't open the preview - if ( event.type === 'keydown' && event.which !== 13 && $( ':focus' ).hasClass( 'button' ) ) { - return; - } - - event.preventDefault(); - - event = event || window.event; - - // Set focus to current theme. - themes.focusedTheme = this.$el; - - // Construct a new Preview view. - themes.preview = preview = new themes.view.Preview({ - model: this.model - }); - - // Render the view and append it. - preview.render(); - this.setNavButtonsState(); - - // Hide previous/next navigation if there is only one theme - if ( this.model.collection.length === 1 ) { - preview.$el.addClass( 'no-navigation' ); - } else { - preview.$el.removeClass( 'no-navigation' ); - } - - // Append preview - $( 'div.wrap' ).append( preview.el ); - - // Listen to our preview object - // for `theme:next` and `theme:previous` events. - this.listenTo( preview, 'theme:next', function() { - - // Keep local track of current theme model. - current = self.model; - - // If we have ventured away from current model update the current model position. - if ( ! _.isUndefined( self.current ) ) { - current = self.current; - } - - // Get next theme model. - self.current = self.model.collection.at( self.model.collection.indexOf( current ) + 1 ); - - // If we have no more themes, bail. - if ( _.isUndefined( self.current ) ) { - self.options.parent.parent.trigger( 'theme:end' ); - return self.current = current; - } - - preview.model = self.current; - - // Render and append. - preview.render(); - this.setNavButtonsState(); - $( '.next-theme' ).focus(); - }) - .listenTo( preview, 'theme:previous', function() { - - // Keep track of current theme model. - current = self.model; - - // Bail early if we are at the beginning of the collection - if ( self.model.collection.indexOf( self.current ) === 0 ) { - return; - } - - // If we have ventured away from current model update the current model position. - if ( ! _.isUndefined( self.current ) ) { - current = self.current; - } - - // Get previous theme model. - self.current = self.model.collection.at( self.model.collection.indexOf( current ) - 1 ); - - // If we have no more themes, bail. - if ( _.isUndefined( self.current ) ) { - return; - } - - preview.model = self.current; - - // Render and append. - preview.render(); - this.setNavButtonsState(); - $( '.previous-theme' ).focus(); - }); - - this.listenTo( preview, 'preview:close', function() { - self.current = self.model; - }); - - }, - - // Handles .disabled classes for previous/next buttons in theme installer preview - setNavButtonsState: function() { - var $themeInstaller = $( '.theme-install-overlay' ), - current = _.isUndefined( this.current ) ? this.model : this.current, - previousThemeButton = $themeInstaller.find( '.previous-theme' ), - nextThemeButton = $themeInstaller.find( '.next-theme' ); - - // Disable previous at the zero position - if ( 0 === this.model.collection.indexOf( current ) ) { - previousThemeButton - .addClass( 'disabled' ) - .prop( 'disabled', true ); - - nextThemeButton.focus(); - } - - // Disable next if the next model is undefined - if ( _.isUndefined( this.model.collection.at( this.model.collection.indexOf( current ) + 1 ) ) ) { - nextThemeButton - .addClass( 'disabled' ) - .prop( 'disabled', true ); - - previousThemeButton.focus(); - } - }, - - installTheme: function( event ) { - var _this = this; - - event.preventDefault(); - - wp.updates.maybeRequestFilesystemCredentials( event ); - - $( document ).on( 'wp-theme-install-success', function( event, response ) { - if ( _this.model.get( 'id' ) === response.slug ) { - _this.model.set( { 'installed': true } ); - } - } ); - - wp.updates.installTheme( { - slug: $( event.target ).data( 'slug' ) - } ); - }, - - updateTheme: function( event ) { - var _this = this; - - if ( ! this.model.get( 'hasPackage' ) ) { - return; - } - - event.preventDefault(); - - wp.updates.maybeRequestFilesystemCredentials( event ); - - $( document ).on( 'wp-theme-update-success', function( event, response ) { - _this.model.off( 'change', _this.render, _this ); - if ( _this.model.get( 'id' ) === response.slug ) { - _this.model.set( { - hasUpdate: false, - version: response.newVersion - } ); - } - _this.model.on( 'change', _this.render, _this ); - } ); - - wp.updates.updateTheme( { - slug: $( event.target ).parents( 'div.theme' ).first().data( 'slug' ) - } ); - } -}); - -// Theme Details view -// Set ups a modal overlay with the expanded theme data -themes.view.Details = wp.Backbone.View.extend({ - - // Wrap theme data on a div.theme element - className: 'theme-overlay', - - events: { - 'click': 'collapse', - 'click .delete-theme': 'deleteTheme', - 'click .left': 'previousTheme', - 'click .right': 'nextTheme', - 'click #update-theme': 'updateTheme' - }, - - // The HTML template for the theme overlay - html: themes.template( 'theme-single' ), - - render: function() { - var data = this.model.toJSON(); - this.$el.html( this.html( data ) ); - // Renders active theme styles - this.activeTheme(); - // Set up navigation events - this.navigation(); - // Checks screenshot size - this.screenshotCheck( this.$el ); - // Contain "tabbing" inside the overlay - this.containFocus( this.$el ); - }, - - // Adds a class to the currently active theme - // and to the overlay in detailed view mode - activeTheme: function() { - // Check the model has the active property - this.$el.toggleClass( 'active', this.model.get( 'active' ) ); - }, - - // Set initial focus and constrain tabbing within the theme browser modal. - containFocus: function( $el ) { - - // Set initial focus on the primary action control. - _.delay( function() { - $( '.theme-overlay' ).focus(); - }, 100 ); - - // Constrain tabbing within the modal. - $el.on( 'keydown.wp-themes', function( event ) { - var $firstFocusable = $el.find( '.theme-header button:not(.disabled)' ).first(), - $lastFocusable = $el.find( '.theme-actions a:visible' ).last(); - - // Check for the Tab key. - if ( 9 === event.which ) { - if ( $firstFocusable[0] === event.target && event.shiftKey ) { - $lastFocusable.focus(); - event.preventDefault(); - } else if ( $lastFocusable[0] === event.target && ! event.shiftKey ) { - $firstFocusable.focus(); - event.preventDefault(); - } - } - }); - }, - - // Single theme overlay screen - // It's shown when clicking a theme - collapse: function( event ) { - var self = this, - scroll; - - event = event || window.event; - - // Prevent collapsing detailed view when there is only one theme available - if ( themes.data.themes.length === 1 ) { - return; - } - - // Detect if the click is inside the overlay - // and don't close it unless the target was - // the div.back button - if ( $( event.target ).is( '.theme-backdrop' ) || $( event.target ).is( '.close' ) || event.keyCode === 27 ) { - - // Add a temporary closing class while overlay fades out - $( 'body' ).addClass( 'closing-overlay' ); - - // With a quick fade out animation - this.$el.fadeOut( 130, function() { - // Clicking outside the modal box closes the overlay - $( 'body' ).removeClass( 'closing-overlay' ); - // Handle event cleanup - self.closeOverlay(); - - // Get scroll position to avoid jumping to the top - scroll = document.body.scrollTop; - - // Clean the url structure - themes.router.navigate( themes.router.baseUrl( '' ) ); - - // Restore scroll position - document.body.scrollTop = scroll; - - // Return focus to the theme div - if ( themes.focusedTheme ) { - themes.focusedTheme.focus(); - } - }); - } - }, - - // Handles .disabled classes for next/previous buttons - navigation: function() { - - // Disable Left/Right when at the start or end of the collection - if ( this.model.cid === this.model.collection.at(0).cid ) { - this.$el.find( '.left' ) - .addClass( 'disabled' ) - .prop( 'disabled', true ); - } - if ( this.model.cid === this.model.collection.at( this.model.collection.length - 1 ).cid ) { - this.$el.find( '.right' ) - .addClass( 'disabled' ) - .prop( 'disabled', true ); - } - }, - - // Performs the actions to effectively close - // the theme details overlay - closeOverlay: function() { - $( 'body' ).removeClass( 'modal-open' ); - this.remove(); - this.unbind(); - this.trigger( 'theme:collapse' ); - }, - - updateTheme: function( event ) { - var _this = this; - event.preventDefault(); - - wp.updates.maybeRequestFilesystemCredentials( event ); - - $( document ).on( 'wp-theme-update-success', function( event, response ) { - if ( _this.model.get( 'id' ) === response.slug ) { - _this.model.set( { - hasUpdate: false, - version: response.newVersion - } ); - } - _this.render(); - } ); - - wp.updates.updateTheme( { - slug: $( event.target ).data( 'slug' ) - } ); - }, - - deleteTheme: function( event ) { - var _this = this, - _collection = _this.model.collection, - _themes = themes; - event.preventDefault(); - - // Confirmation dialog for deleting a theme. - if ( ! window.confirm( wp.themes.data.settings.confirmDelete ) ) { - return; - } - - wp.updates.maybeRequestFilesystemCredentials( event ); - - $( document ).one( 'wp-theme-delete-success', function( event, response ) { - _this.$el.find( '.close' ).trigger( 'click' ); - $( '[data-slug="' + response.slug + '"]' ).css( { backgroundColor:'#faafaa' } ).fadeOut( 350, function() { - $( this ).remove(); - _themes.data.themes = _.without( _themes.data.themes, _.findWhere( _themes.data.themes, { id: response.slug } ) ); - - $( '.wp-filter-search' ).val( '' ); - _collection.doSearch( '' ); - _collection.remove( _this.model ); - _collection.trigger( 'themes:update' ); - } ); - } ); - - wp.updates.deleteTheme( { - slug: this.model.get( 'id' ) - } ); - }, - - nextTheme: function() { - var self = this; - self.trigger( 'theme:next', self.model.cid ); - return false; - }, - - previousTheme: function() { - var self = this; - self.trigger( 'theme:previous', self.model.cid ); - return false; - }, - - // Checks if the theme screenshot is the old 300px width version - // and adds a corresponding class if it's true - screenshotCheck: function( el ) { - var screenshot, image; - - screenshot = el.find( '.screenshot img' ); - image = new Image(); - image.src = screenshot.attr( 'src' ); - - // Width check - if ( image.width && image.width <= 300 ) { - el.addClass( 'small-screenshot' ); - } - } -}); - -// Theme Preview view -// Set ups a modal overlay with the expanded theme data -themes.view.Preview = themes.view.Details.extend({ - - className: 'wp-full-overlay expanded', - el: '.theme-install-overlay', - - events: { - 'click .close-full-overlay': 'close', - 'click .collapse-sidebar': 'collapse', - 'click .devices button': 'previewDevice', - 'click .previous-theme': 'previousTheme', - 'click .next-theme': 'nextTheme', - 'keyup': 'keyEvent', - 'click .theme-install': 'installTheme' - }, - - // The HTML template for the theme preview - html: themes.template( 'theme-preview' ), - - render: function() { - var self = this, - currentPreviewDevice, - data = this.model.toJSON(), - $body = $( document.body ); - - $body.attr( 'aria-busy', 'true' ); - - this.$el.removeClass( 'iframe-ready' ).html( this.html( data ) ); - - currentPreviewDevice = this.$el.data( 'current-preview-device' ); - if ( currentPreviewDevice ) { - self.tooglePreviewDeviceButtons( currentPreviewDevice ); - } - - themes.router.navigate( themes.router.baseUrl( themes.router.themePath + this.model.get( 'id' ) ), { replace: false } ); - - this.$el.fadeIn( 200, function() { - $body.addClass( 'theme-installer-active full-overlay-active' ); - }); - - this.$el.find( 'iframe' ).one( 'load', function() { - self.iframeLoaded(); - }); - }, - - iframeLoaded: function() { - this.$el.addClass( 'iframe-ready' ); - $( document.body ).attr( 'aria-busy', 'false' ); - }, - - close: function() { - this.$el.fadeOut( 200, function() { - $( 'body' ).removeClass( 'theme-installer-active full-overlay-active' ); - - // Return focus to the theme div - if ( themes.focusedTheme ) { - themes.focusedTheme.focus(); - } - }).removeClass( 'iframe-ready' ); - - // Restore the previous browse tab if available. - if ( themes.router.selectedTab ) { - themes.router.navigate( themes.router.baseUrl( '?browse=' + themes.router.selectedTab ) ); - themes.router.selectedTab = false; - } else { - themes.router.navigate( themes.router.baseUrl( '' ) ); - } - this.trigger( 'preview:close' ); - this.undelegateEvents(); - this.unbind(); - return false; - }, - - collapse: function( event ) { - var $button = $( event.currentTarget ); - if ( 'true' === $button.attr( 'aria-expanded' ) ) { - $button.attr({ 'aria-expanded': 'false', 'aria-label': l10n.expandSidebar }); - } else { - $button.attr({ 'aria-expanded': 'true', 'aria-label': l10n.collapseSidebar }); - } - - this.$el.toggleClass( 'collapsed' ).toggleClass( 'expanded' ); - return false; - }, - - previewDevice: function( event ) { - var device = $( event.currentTarget ).data( 'device' ); - - this.$el - .removeClass( 'preview-desktop preview-tablet preview-mobile' ) - .addClass( 'preview-' + device ) - .data( 'current-preview-device', device ); - - this.tooglePreviewDeviceButtons( device ); - }, - - tooglePreviewDeviceButtons: function( newDevice ) { - var $devices = $( '.wp-full-overlay-footer .devices' ); - - $devices.find( 'button' ) - .removeClass( 'active' ) - .attr( 'aria-pressed', false ); - - $devices.find( 'button.preview-' + newDevice ) - .addClass( 'active' ) - .attr( 'aria-pressed', true ); - }, - - keyEvent: function( event ) { - // The escape key closes the preview - if ( event.keyCode === 27 ) { - this.undelegateEvents(); - this.close(); - } - // The right arrow key, next theme - if ( event.keyCode === 39 ) { - _.once( this.nextTheme() ); - } - - // The left arrow key, previous theme - if ( event.keyCode === 37 ) { - this.previousTheme(); - } - }, - - installTheme: function( event ) { - var _this = this, - $target = $( event.target ); - event.preventDefault(); - - if ( $target.hasClass( 'disabled' ) ) { - return; - } - - wp.updates.maybeRequestFilesystemCredentials( event ); - - $( document ).on( 'wp-theme-install-success', function() { - _this.model.set( { 'installed': true } ); - } ); - - wp.updates.installTheme( { - slug: $target.data( 'slug' ) - } ); - } -}); - -// Controls the rendering of div.themes, -// a wrapper that will hold all the theme elements -themes.view.Themes = wp.Backbone.View.extend({ - - className: 'themes wp-clearfix', - $overlay: $( 'div.theme-overlay' ), - - // Number to keep track of scroll position - // while in theme-overlay mode - index: 0, - - // The theme count element - count: $( '.wrap .theme-count' ), - - // The live themes count - liveThemeCount: 0, - - initialize: function( options ) { - var self = this; - - // Set up parent - this.parent = options.parent; - - // Set current view to [grid] - this.setView( 'grid' ); - - // Move the active theme to the beginning of the collection - self.currentTheme(); - - // When the collection is updated by user input... - this.listenTo( self.collection, 'themes:update', function() { - self.parent.page = 0; - self.currentTheme(); - self.render( this ); - } ); - - // Update theme count to full result set when available. - this.listenTo( self.collection, 'query:success', function( count ) { - if ( _.isNumber( count ) ) { - self.count.text( count ); - self.announceSearchResults( count ); - } else { - self.count.text( self.collection.length ); - self.announceSearchResults( self.collection.length ); - } - }); - - this.listenTo( self.collection, 'query:empty', function() { - $( 'body' ).addClass( 'no-results' ); - }); - - this.listenTo( this.parent, 'theme:scroll', function() { - self.renderThemes( self.parent.page ); - }); - - this.listenTo( this.parent, 'theme:close', function() { - if ( self.overlay ) { - self.overlay.closeOverlay(); - } - } ); - - // Bind keyboard events. - $( 'body' ).on( 'keyup', function( event ) { - if ( ! self.overlay ) { - return; - } - - // Bail if the filesystem credentials dialog is shown. - if ( $( '#request-filesystem-credentials-dialog' ).is( ':visible' ) ) { - return; - } - - // Pressing the right arrow key fires a theme:next event - if ( event.keyCode === 39 ) { - self.overlay.nextTheme(); - } - - // Pressing the left arrow key fires a theme:previous event - if ( event.keyCode === 37 ) { - self.overlay.previousTheme(); - } - - // Pressing the escape key fires a theme:collapse event - if ( event.keyCode === 27 ) { - self.overlay.collapse( event ); - } - }); - }, - - // Manages rendering of theme pages - // and keeping theme count in sync - render: function() { - // Clear the DOM, please - this.$el.empty(); - - // If the user doesn't have switch capabilities - // or there is only one theme in the collection - // render the detailed view of the active theme - if ( themes.data.themes.length === 1 ) { - - // Constructs the view - this.singleTheme = new themes.view.Details({ - model: this.collection.models[0] - }); - - // Render and apply a 'single-theme' class to our container - this.singleTheme.render(); - this.$el.addClass( 'single-theme' ); - this.$el.append( this.singleTheme.el ); - } - - // Generate the themes - // Using page instance - // While checking the collection has items - if ( this.options.collection.size() > 0 ) { - this.renderThemes( this.parent.page ); - } - - // Display a live theme count for the collection - this.liveThemeCount = this.collection.count ? this.collection.count : this.collection.length; - this.count.text( this.liveThemeCount ); - - /* - * In the theme installer the themes count is already announced - * because `announceSearchResults` is called on `query:success`. - */ - if ( ! themes.isInstall ) { - this.announceSearchResults( this.liveThemeCount ); - } - }, - - // Iterates through each instance of the collection - // and renders each theme module - renderThemes: function( page ) { - var self = this; - - self.instance = self.collection.paginate( page ); - - // If we have no more themes bail - if ( self.instance.size() === 0 ) { - // Fire a no-more-themes event. - this.parent.trigger( 'theme:end' ); - return; - } - - // Make sure the add-new stays at the end - if ( ! themes.isInstall && page >= 1 ) { - $( '.add-new-theme' ).remove(); - } - - // Loop through the themes and setup each theme view - self.instance.each( function( theme ) { - self.theme = new themes.view.Theme({ - model: theme, - parent: self - }); - - // Render the views... - self.theme.render(); - // and append them to div.themes - self.$el.append( self.theme.el ); - - // Binds to theme:expand to show the modal box - // with the theme details - self.listenTo( self.theme, 'theme:expand', self.expand, self ); - }); - - // 'Add new theme' element shown at the end of the grid - if ( ! themes.isInstall && themes.data.settings.canInstall ) { - this.$el.append( '<div class="theme add-new-theme"><a href="' + themes.data.settings.installURI + '"><div class="theme-screenshot"><span></span></div><h2 class="theme-name">' + l10n.addNew + '</h2></a></div>' ); - } - - this.parent.page++; - }, - - // Grabs current theme and puts it at the beginning of the collection - currentTheme: function() { - var self = this, - current; - - current = self.collection.findWhere({ active: true }); - - // Move the active theme to the beginning of the collection - if ( current ) { - self.collection.remove( current ); - self.collection.add( current, { at:0 } ); - } - }, - - // Sets current view - setView: function( view ) { - return view; - }, - - // Renders the overlay with the ThemeDetails view - // Uses the current model data - expand: function( id ) { - var self = this, $card, $modal; - - // Set the current theme model - this.model = self.collection.get( id ); - - // Trigger a route update for the current model - themes.router.navigate( themes.router.baseUrl( themes.router.themePath + this.model.id ) ); - - // Sets this.view to 'detail' - this.setView( 'detail' ); - $( 'body' ).addClass( 'modal-open' ); - - // Set up the theme details view - this.overlay = new themes.view.Details({ - model: self.model - }); - - this.overlay.render(); - - if ( this.model.get( 'hasUpdate' ) ) { - $card = $( '[data-slug="' + this.model.id + '"]' ); - $modal = $( this.overlay.el ); - - if ( $card.find( '.updating-message' ).length ) { - $modal.find( '.notice-warning h3' ).remove(); - $modal.find( '.notice-warning' ) - .removeClass( 'notice-large' ) - .addClass( 'updating-message' ) - .find( 'p' ).text( wp.updates.l10n.updating ); - } else if ( $card.find( '.notice-error' ).length ) { - $modal.find( '.notice-warning' ).remove(); - } - } - - this.$overlay.html( this.overlay.el ); - - // Bind to theme:next and theme:previous - // triggered by the arrow keys - // - // Keep track of the current model so we - // can infer an index position - this.listenTo( this.overlay, 'theme:next', function() { - // Renders the next theme on the overlay - self.next( [ self.model.cid ] ); - - }) - .listenTo( this.overlay, 'theme:previous', function() { - // Renders the previous theme on the overlay - self.previous( [ self.model.cid ] ); - }); - }, - - // This method renders the next theme on the overlay modal - // based on the current position in the collection - // @params [model cid] - next: function( args ) { - var self = this, - model, nextModel; - - // Get the current theme - model = self.collection.get( args[0] ); - // Find the next model within the collection - nextModel = self.collection.at( self.collection.indexOf( model ) + 1 ); - - // Sanity check which also serves as a boundary test - if ( nextModel !== undefined ) { - - // We have a new theme... - // Close the overlay - this.overlay.closeOverlay(); - - // Trigger a route update for the current model - self.theme.trigger( 'theme:expand', nextModel.cid ); - - } - }, - - // This method renders the previous theme on the overlay modal - // based on the current position in the collection - // @params [model cid] - previous: function( args ) { - var self = this, - model, previousModel; - - // Get the current theme - model = self.collection.get( args[0] ); - // Find the previous model within the collection - previousModel = self.collection.at( self.collection.indexOf( model ) - 1 ); - - if ( previousModel !== undefined ) { - - // We have a new theme... - // Close the overlay - this.overlay.closeOverlay(); - - // Trigger a route update for the current model - self.theme.trigger( 'theme:expand', previousModel.cid ); - - } - }, - - // Dispatch audible search results feedback message - announceSearchResults: function( count ) { - if ( 0 === count ) { - wp.a11y.speak( l10n.noThemesFound ); - } else { - wp.a11y.speak( l10n.themesFound.replace( '%d', count ) ); - } - } -}); - -// Search input view controller. -themes.view.Search = wp.Backbone.View.extend({ - - tagName: 'input', - className: 'wp-filter-search', - id: 'wp-filter-search-input', - searching: false, - - attributes: { - placeholder: l10n.searchPlaceholder, - type: 'search', - 'aria-describedby': 'live-search-desc' - }, - - events: { - 'input': 'search', - 'keyup': 'search', - 'blur': 'pushState' - }, - - initialize: function( options ) { - - this.parent = options.parent; - - this.listenTo( this.parent, 'theme:close', function() { - this.searching = false; - } ); - - }, - - search: function( event ) { - // Clear on escape. - if ( event.type === 'keyup' && event.which === 27 ) { - event.target.value = ''; - } - - // Since doSearch is debounced, it will only run when user input comes to a rest. - this.doSearch( event ); - }, - - // Runs a search on the theme collection. - doSearch: function( event ) { - var options = {}; - - this.collection.doSearch( event.target.value.replace( /\+/g, ' ' ) ); - - // if search is initiated and key is not return - if ( this.searching && event.which !== 13 ) { - options.replace = true; - } else { - this.searching = true; - } - - // Update the URL hash - if ( event.target.value ) { - themes.router.navigate( themes.router.baseUrl( themes.router.searchPath + event.target.value ), options ); - } else { - themes.router.navigate( themes.router.baseUrl( '' ) ); - } - }, - - pushState: function( event ) { - var url = themes.router.baseUrl( '' ); - - if ( event.target.value ) { - url = themes.router.baseUrl( themes.router.searchPath + encodeURIComponent( event.target.value ) ); - } - - this.searching = false; - themes.router.navigate( url ); - - } -}); - -/** - * Navigate router. - * - * @since 4.9.0 - * - * @param {string} url - URL to navigate to. - * @param {object} state - State. - * @returns {void} - */ -function navigateRouter( url, state ) { - var router = this; - if ( Backbone.history._hasPushState ) { - Backbone.Router.prototype.navigate.call( router, url, state ); - } -} - -// Sets up the routes events for relevant url queries -// Listens to [theme] and [search] params -themes.Router = Backbone.Router.extend({ - - routes: { - 'themes.php?theme=:slug': 'theme', - 'themes.php?search=:query': 'search', - 'themes.php?s=:query': 'search', - 'themes.php': 'themes', - '': 'themes' - }, - - baseUrl: function( url ) { - return 'themes.php' + url; - }, - - themePath: '?theme=', - searchPath: '?search=', - - search: function( query ) { - $( '.wp-filter-search' ).val( query.replace( /\+/g, ' ' ) ); - }, - - themes: function() { - $( '.wp-filter-search' ).val( '' ); - }, - - navigate: navigateRouter - -}); - -// Execute and setup the application -themes.Run = { - init: function() { - // Initializes the blog's theme library view - // Create a new collection with data - this.themes = new themes.Collection( themes.data.themes ); - - // Set up the view - this.view = new themes.view.Appearance({ - collection: this.themes - }); - - this.render(); - - // Start debouncing user searches after Backbone.history.start(). - this.view.SearchView.doSearch = _.debounce( this.view.SearchView.doSearch, 500 ); - }, - - render: function() { - - // Render results - this.view.render(); - this.routes(); - - if ( Backbone.History.started ) { - Backbone.history.stop(); - } - Backbone.history.start({ - root: themes.data.settings.adminUrl, - pushState: true, - hashChange: false - }); - }, - - routes: function() { - var self = this; - // Bind to our global thx object - // so that the object is available to sub-views - themes.router = new themes.Router(); - - // Handles theme details route event - themes.router.on( 'route:theme', function( slug ) { - self.view.view.expand( slug ); - }); - - themes.router.on( 'route:themes', function() { - self.themes.doSearch( '' ); - self.view.trigger( 'theme:close' ); - }); - - // Handles search route event - themes.router.on( 'route:search', function() { - $( '.wp-filter-search' ).trigger( 'keyup' ); - }); - - this.extraRoutes(); - }, - - extraRoutes: function() { - return false; - } -}; - -// Extend the main Search view -themes.view.InstallerSearch = themes.view.Search.extend({ - - events: { - 'input': 'search', - 'keyup': 'search' - }, - - terms: '', - - // Handles Ajax request for searching through themes in public repo - search: function( event ) { - - // Tabbing or reverse tabbing into the search input shouldn't trigger a search - if ( event.type === 'keyup' && ( event.which === 9 || event.which === 16 ) ) { - return; - } - - this.collection = this.options.parent.view.collection; - - // Clear on escape. - if ( event.type === 'keyup' && event.which === 27 ) { - event.target.value = ''; - } - - this.doSearch( event.target.value ); - }, - - doSearch: function( value ) { - var request = {}; - - // Don't do anything if the search terms haven't changed. - if ( this.terms === value ) { - return; - } - - // Updates terms with the value passed. - this.terms = value; - - request.search = value; - - // Intercept an [author] search. - // - // If input value starts with `author:` send a request - // for `author` instead of a regular `search` - if ( value.substring( 0, 7 ) === 'author:' ) { - request.search = ''; - request.author = value.slice( 7 ); - } - - // Intercept a [tag] search. - // - // If input value starts with `tag:` send a request - // for `tag` instead of a regular `search` - if ( value.substring( 0, 4 ) === 'tag:' ) { - request.search = ''; - request.tag = [ value.slice( 4 ) ]; - } - - $( '.filter-links li > a.current' ) - .removeClass( 'current' ) - .removeAttr( 'aria-current' ); - - $( 'body' ).removeClass( 'show-filters filters-applied show-favorites-form' ); - $( '.drawer-toggle' ).attr( 'aria-expanded', 'false' ); - - // Get the themes by sending Ajax POST request to api.wordpress.org/themes - // or searching the local cache - this.collection.query( request ); - - // Set route - themes.router.navigate( themes.router.baseUrl( themes.router.searchPath + encodeURIComponent( value ) ), { replace: true } ); - } -}); - -themes.view.Installer = themes.view.Appearance.extend({ - - el: '#wpbody-content .wrap', - - // Register events for sorting and filters in theme-navigation - events: { - 'click .filter-links li > a': 'onSort', - 'click .theme-filter': 'onFilter', - 'click .drawer-toggle': 'moreFilters', - 'click .filter-drawer .apply-filters': 'applyFilters', - 'click .filter-group [type="checkbox"]': 'addFilter', - 'click .filter-drawer .clear-filters': 'clearFilters', - 'click .edit-filters': 'backToFilters', - 'click .favorites-form-submit' : 'saveUsername', - 'keyup #wporg-username-input': 'saveUsername' - }, - - // Initial render method - render: function() { - var self = this; - - this.search(); - this.uploader(); - - this.collection = new themes.Collection(); - - // Bump `collection.currentQuery.page` and request more themes if we hit the end of the page. - this.listenTo( this, 'theme:end', function() { - - // Make sure we are not already loading - if ( self.collection.loadingThemes ) { - return; - } - - // Set loadingThemes to true and bump page instance of currentQuery. - self.collection.loadingThemes = true; - self.collection.currentQuery.page++; - - // Use currentQuery.page to build the themes request. - _.extend( self.collection.currentQuery.request, { page: self.collection.currentQuery.page } ); - self.collection.query( self.collection.currentQuery.request ); - }); - - this.listenTo( this.collection, 'query:success', function() { - $( 'body' ).removeClass( 'loading-content' ); - $( '.theme-browser' ).find( 'div.error' ).remove(); - }); - - this.listenTo( this.collection, 'query:fail', function() { - $( 'body' ).removeClass( 'loading-content' ); - $( '.theme-browser' ).find( 'div.error' ).remove(); - $( '.theme-browser' ).find( 'div.themes' ).before( '<div class="error"><p>' + l10n.error + '</p><p><button class="button try-again">' + l10n.tryAgain + '</button></p></div>' ); - $( '.theme-browser .error .try-again' ).on( 'click', function( e ) { - e.preventDefault(); - $( 'input.wp-filter-search' ).trigger( 'input' ); - } ); - }); - - if ( this.view ) { - this.view.remove(); - } - - // Set ups the view and passes the section argument - this.view = new themes.view.Themes({ - collection: this.collection, - parent: this - }); - - // Reset pagination every time the install view handler is run - this.page = 0; - - // Render and append - this.$el.find( '.themes' ).remove(); - this.view.render(); - this.$el.find( '.theme-browser' ).append( this.view.el ).addClass( 'rendered' ); - }, - - // Handles all the rendering of the public theme directory - browse: function( section ) { - // Create a new collection with the proper theme data - // for each section - this.collection.query( { browse: section } ); - }, - - // Sorting navigation - onSort: function( event ) { - var $el = $( event.target ), - sort = $el.data( 'sort' ); - - event.preventDefault(); - - $( 'body' ).removeClass( 'filters-applied show-filters' ); - $( '.drawer-toggle' ).attr( 'aria-expanded', 'false' ); - - // Bail if this is already active - if ( $el.hasClass( this.activeClass ) ) { - return; - } - - this.sort( sort ); - - // Trigger a router.naviagte update - themes.router.navigate( themes.router.baseUrl( themes.router.browsePath + sort ) ); - }, - - sort: function( sort ) { - this.clearSearch(); - - // Track sorting so we can restore the correct tab when closing preview. - themes.router.selectedTab = sort; - - $( '.filter-links li > a, .theme-filter' ) - .removeClass( this.activeClass ) - .removeAttr( 'aria-current' ); - - $( '[data-sort="' + sort + '"]' ) - .addClass( this.activeClass ) - .attr( 'aria-current', 'page' ); - - if ( 'favorites' === sort ) { - $( 'body' ).addClass( 'show-favorites-form' ); - } else { - $( 'body' ).removeClass( 'show-favorites-form' ); - } - - this.browse( sort ); - }, - - // Filters and Tags - onFilter: function( event ) { - var request, - $el = $( event.target ), - filter = $el.data( 'filter' ); - - // Bail if this is already active - if ( $el.hasClass( this.activeClass ) ) { - return; - } - - $( '.filter-links li > a, .theme-section' ) - .removeClass( this.activeClass ) - .removeAttr( 'aria-current' ); - $el - .addClass( this.activeClass ) - .attr( 'aria-current', 'page' ); - - if ( ! filter ) { - return; - } - - // Construct the filter request - // using the default values - filter = _.union( [ filter, this.filtersChecked() ] ); - request = { tag: [ filter ] }; - - // Get the themes by sending Ajax POST request to api.wordpress.org/themes - // or searching the local cache - this.collection.query( request ); - }, - - // Clicking on a checkbox to add another filter to the request - addFilter: function() { - this.filtersChecked(); - }, - - // Applying filters triggers a tag request - applyFilters: function( event ) { - var name, - tags = this.filtersChecked(), - request = { tag: tags }, - filteringBy = $( '.filtered-by .tags' ); - - if ( event ) { - event.preventDefault(); - } - - if ( ! tags ) { - wp.a11y.speak( l10n.selectFeatureFilter ); - return; - } - - $( 'body' ).addClass( 'filters-applied' ); - $( '.filter-links li > a.current' ) - .removeClass( 'current' ) - .removeAttr( 'aria-current' ); - - filteringBy.empty(); - - _.each( tags, function( tag ) { - name = $( 'label[for="filter-id-' + tag + '"]' ).text(); - filteringBy.append( '<span class="tag">' + name + '</span>' ); - }); - - // Get the themes by sending Ajax POST request to api.wordpress.org/themes - // or searching the local cache - this.collection.query( request ); - }, - - // Save the user's WordPress.org username and get his favorite themes. - saveUsername: function ( event ) { - var username = $( '#wporg-username-input' ).val(), - nonce = $( '#wporg-username-nonce' ).val(), - request = { browse: 'favorites', user: username }, - that = this; - - if ( event ) { - event.preventDefault(); - } - - // save username on enter - if ( event.type === 'keyup' && event.which !== 13 ) { - return; - } - - return wp.ajax.send( 'save-wporg-username', { - data: { - _wpnonce: nonce, - username: username - }, - success: function () { - // Get the themes by sending Ajax POST request to api.wordpress.org/themes - // or searching the local cache - that.collection.query( request ); - } - } ); - }, - - // Get the checked filters - // @return {array} of tags or false - filtersChecked: function() { - var items = $( '.filter-group' ).find( ':checkbox' ), - tags = []; - - _.each( items.filter( ':checked' ), function( item ) { - tags.push( $( item ).prop( 'value' ) ); - }); - - // When no filters are checked, restore initial state and return - if ( tags.length === 0 ) { - $( '.filter-drawer .apply-filters' ).find( 'span' ).text( '' ); - $( '.filter-drawer .clear-filters' ).hide(); - $( 'body' ).removeClass( 'filters-applied' ); - return false; - } - - $( '.filter-drawer .apply-filters' ).find( 'span' ).text( tags.length ); - $( '.filter-drawer .clear-filters' ).css( 'display', 'inline-block' ); - - return tags; - }, - - activeClass: 'current', - - /* - * When users press the "Upload Theme" button, show the upload form in place. - */ - uploader: function() { - var uploadViewToggle = $( '.upload-view-toggle' ), - $body = $( document.body ); - - uploadViewToggle.on( 'click', function() { - // Toggle the upload view. - $body.toggleClass( 'show-upload-view' ); - // Toggle the `aria-expanded` button attribute. - uploadViewToggle.attr( 'aria-expanded', $body.hasClass( 'show-upload-view' ) ); - }); - }, - - // Toggle the full filters navigation - moreFilters: function( event ) { - var $body = $( 'body' ), - $toggleButton = $( '.drawer-toggle' ); - - event.preventDefault(); - - if ( $body.hasClass( 'filters-applied' ) ) { - return this.backToFilters(); - } - - this.clearSearch(); - - themes.router.navigate( themes.router.baseUrl( '' ) ); - // Toggle the feature filters view. - $body.toggleClass( 'show-filters' ); - // Toggle the `aria-expanded` button attribute. - $toggleButton.attr( 'aria-expanded', $body.hasClass( 'show-filters' ) ); - }, - - // Clears all the checked filters - // @uses filtersChecked() - clearFilters: function( event ) { - var items = $( '.filter-group' ).find( ':checkbox' ), - self = this; - - event.preventDefault(); - - _.each( items.filter( ':checked' ), function( item ) { - $( item ).prop( 'checked', false ); - return self.filtersChecked(); - }); - }, - - backToFilters: function( event ) { - if ( event ) { - event.preventDefault(); - } - - $( 'body' ).removeClass( 'filters-applied' ); - }, - - clearSearch: function() { - $( '#wp-filter-search-input').val( '' ); - } -}); - -themes.InstallerRouter = Backbone.Router.extend({ - routes: { - 'theme-install.php?theme=:slug': 'preview', - 'theme-install.php?browse=:sort': 'sort', - 'theme-install.php?search=:query': 'search', - 'theme-install.php': 'sort' - }, - - baseUrl: function( url ) { - return 'theme-install.php' + url; - }, - - themePath: '?theme=', - browsePath: '?browse=', - searchPath: '?search=', - - search: function( query ) { - $( '.wp-filter-search' ).val( query.replace( /\+/g, ' ' ) ); - }, - - navigate: navigateRouter -}); - - -themes.RunInstaller = { - - init: function() { - // Set up the view - // Passes the default 'section' as an option - this.view = new themes.view.Installer({ - section: 'featured', - SearchView: themes.view.InstallerSearch - }); - - // Render results - this.render(); - - // Start debouncing user searches after Backbone.history.start(). - this.view.SearchView.doSearch = _.debounce( this.view.SearchView.doSearch, 500 ); - }, - - render: function() { - - // Render results - this.view.render(); - this.routes(); - - if ( Backbone.History.started ) { - Backbone.history.stop(); - } - Backbone.history.start({ - root: themes.data.settings.adminUrl, - pushState: true, - hashChange: false - }); - }, - - routes: function() { - var self = this, - request = {}; - - // Bind to our global `wp.themes` object - // so that the router is available to sub-views - themes.router = new themes.InstallerRouter(); - - // Handles `theme` route event - // Queries the API for the passed theme slug - themes.router.on( 'route:preview', function( slug ) { - - // Remove existing handlers. - if ( themes.preview ) { - themes.preview.undelegateEvents(); - themes.preview.unbind(); - } - - // If the theme preview is active, set the current theme. - if ( self.view.view.theme && self.view.view.theme.preview ) { - self.view.view.theme.model = self.view.collection.findWhere( { 'slug': slug } ); - self.view.view.theme.preview(); - } else { - - // Select the theme by slug. - request.theme = slug; - self.view.collection.query( request ); - self.view.collection.trigger( 'update' ); - - // Open the theme preview. - self.view.collection.once( 'query:success', function() { - $( 'div[data-slug="' + slug + '"]' ).trigger( 'click' ); - }); - - } - }); - - // Handles sorting / browsing routes - // Also handles the root URL triggering a sort request - // for `featured`, the default view - themes.router.on( 'route:sort', function( sort ) { - if ( ! sort ) { - sort = 'featured'; - themes.router.navigate( themes.router.baseUrl( '?browse=featured' ), { replace: true } ); - } - self.view.sort( sort ); - - // Close the preview if open. - if ( themes.preview ) { - themes.preview.close(); - } - }); - - // The `search` route event. The router populates the input field. - themes.router.on( 'route:search', function() { - $( '.wp-filter-search' ).focus().trigger( 'keyup' ); - }); - - this.extraRoutes(); - }, - - extraRoutes: function() { - return false; - } -}; - -// Ready... -$( document ).ready(function() { - if ( themes.isInstall ) { - themes.RunInstaller.init(); - } else { - themes.Run.init(); - } - - // Update the return param just in time. - $( document.body ).on( 'click', '.load-customize', function() { - var link = $( this ), urlParser = document.createElement( 'a' ); - urlParser.href = link.prop( 'href' ); - urlParser.search = $.param( _.extend( - wp.customize.utils.parseQueryString( urlParser.search.substr( 1 ) ), - { - 'return': window.location.href - } - ) ); - link.prop( 'href', urlParser.href ); - }); - - $( '.broken-themes .delete-theme' ).on( 'click', function() { - return confirm( _wpThemeSettings.settings.confirmDelete ); - }); -}); - -})( jQuery ); - -// Align theme browser thickbox -jQuery(document).ready( function($) { - window.tb_position = function() { - var tbWindow = $('#TB_window'), - width = $(window).width(), - H = $(window).height(), - W = ( 1040 < width ) ? 1040 : width, - adminbar_height = 0; - - if ( $('#wpadminbar').length ) { - adminbar_height = parseInt( $('#wpadminbar').css('height'), 10 ); - } - - if ( tbWindow.size() ) { - tbWindow.width( W - 50 ).height( H - 45 - adminbar_height ); - $('#TB_iframeContent').width( W - 50 ).height( H - 75 - adminbar_height ); - tbWindow.css({'margin-left': '-' + parseInt( ( ( W - 50 ) / 2 ), 10 ) + 'px'}); - if ( typeof document.body.style.maxWidth !== 'undefined' ) { - tbWindow.css({'top': 20 + adminbar_height + 'px', 'margin-top': '0'}); - } - } - }; - - $(window).resize(function(){ tb_position(); }); -}); diff --git a/srcs/wordpress/wp-admin/js/theme.min.js b/srcs/wordpress/wp-admin/js/theme.min.js deleted file mode 100644 index b08b069..0000000 --- a/srcs/wordpress/wp-admin/js/theme.min.js +++ /dev/null @@ -1 +0,0 @@ -window.wp=window.wp||{},function(o){var l,a;function e(e,t){Backbone.history._hasPushState&&Backbone.Router.prototype.navigate.call(this,e,t)}(l=wp.themes=wp.themes||{}).data=_wpThemeSettings,a=l.data.l10n,l.isInstall=!!l.data.settings.isInstall,_.extend(l,{model:{},view:{},routes:{},router:{},template:wp.template}),l.Model=Backbone.Model.extend({initialize:function(){var e;-1!==_.indexOf(l.data.installedThemes,this.get("slug"))&&this.set({installed:!0}),this.set({id:this.get("slug")||this.get("id")}),this.has("sections")&&(e=this.get("sections").description,this.set({description:e}))}}),l.view.Appearance=wp.Backbone.View.extend({el:"#wpbody-content .wrap .theme-browser",window:o(window),page:0,initialize:function(e){_.bindAll(this,"scroller"),this.SearchView=e.SearchView?e.SearchView:l.view.Search,this.window.bind("scroll",_.throttle(this.scroller,300))},render:function(){this.view=new l.view.Themes({collection:this.collection,parent:this}),this.search(),this.$el.removeClass("search-loading"),this.view.render(),this.$el.empty().append(this.view.el).addClass("rendered")},searchContainer:o(".search-form"),search:function(){var e;1!==l.data.themes.length&&(e=new this.SearchView({collection:this.collection,parent:this}),(this.SearchView=e).render(),this.searchContainer.append(o.parseHTML('<label class="screen-reader-text" for="wp-filter-search-input">'+a.search+"</label>")).append(e.el).on("submit",function(e){e.preventDefault()}))},scroller:function(){var e,t,i=this;e=this.window.scrollTop()+i.window.height(),t=i.$el.offset().top+i.$el.outerHeight(!1)-i.window.height(),(t=Math.round(.9*t))<e&&this.trigger("theme:scroll")}}),l.Collection=Backbone.Collection.extend({model:l.Model,terms:"",doSearch:function(e){this.terms!==e&&(this.terms=e,0<this.terms.length&&this.search(this.terms),""===this.terms&&(this.reset(l.data.themes),o("body").removeClass("no-results")),this.trigger("themes:update"))},search:function(t){var i,e,s,r,a,n;this.reset(l.data.themes,{silent:!0}),t=(t=(t=t.trim()).replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")).replace(/ /g,")(?=.*"),i=new RegExp("^(?=.*"+t+").+","i"),0===(e=this.filter(function(e){return r=e.get("name").replace(/(<([^>]+)>)/gi,""),a=e.get("description").replace(/(<([^>]+)>)/gi,""),n=e.get("author").replace(/(<([^>]+)>)/gi,""),s=_.union([r,e.get("id"),a,n,e.get("tags")]),i.test(e.get("author"))&&2<t.length&&e.set("displayAuthor",!0),i.test(s)})).length?this.trigger("query:empty"):o("body").removeClass("no-results"),this.reset(e)},paginate:function(e){var t=this;return e=e||0,t=_(t.rest(20*e)),t=_(t.first(20))},count:!1,query:function(t){var e,i,s,r=this.queries,a=this;if(this.currentQuery.request=t,e=_.find(r,function(e){return _.isEqual(e.request,t)}),(i=_.has(t,"page"))||(this.currentQuery.page=1),e||i){if(i)return this.apiCall(t,i).done(function(e){a.add(e.themes),a.trigger("query:success"),a.loadingThemes=!1}).fail(function(){a.trigger("query:fail")});0===e.themes.length?a.trigger("query:empty"):o("body").removeClass("no-results"),_.isNumber(e.total)&&(this.count=e.total),this.reset(e.themes),e.total||(this.count=this.length),this.trigger("themes:update"),this.trigger("query:success",this.count)}else e=this.apiCall(t).done(function(e){e.themes&&(a.reset(e.themes),s=e.info.results,r.push({themes:e.themes,request:t,total:s})),a.trigger("themes:update"),a.trigger("query:success",s),e.themes&&0===e.themes.length&&a.trigger("query:empty")}).fail(function(){a.trigger("query:fail")})},queries:[],currentQuery:{page:1,request:{}},apiCall:function(e,t){return wp.ajax.send("query-themes",{data:{request:_.extend({per_page:100},e)},beforeSend:function(){t||o("body").addClass("loading-content").removeClass("no-results")}})},loadingThemes:!1}),l.view.Theme=wp.Backbone.View.extend({className:"theme",state:"grid",html:l.template("theme"),events:{click:l.isInstall?"preview":"expand",keydown:l.isInstall?"preview":"expand",touchend:l.isInstall?"preview":"expand",keyup:"addFocus",touchmove:"preventExpand","click .theme-install":"installTheme","click .update-message":"updateTheme"},touchDrag:!1,initialize:function(){this.model.on("change",this.render,this)},render:function(){var e=this.model.toJSON();this.$el.html(this.html(e)).attr({tabindex:0,"aria-describedby":e.id+"-action "+e.id+"-name","data-slug":e.id}),this.activeTheme(),this.model.get("displayAuthor")&&this.$el.addClass("display-author")},activeTheme:function(){this.model.get("active")&&this.$el.addClass("active")},addFocus:function(){var e=o(":focus").hasClass("theme")?o(":focus"):o(":focus").parents(".theme");o(".theme.focus").removeClass("focus"),e.addClass("focus")},expand:function(e){if("keydown"!==(e=e||window.event).type||13===e.which||32===e.which)return!0===this.touchDrag?this.touchDrag=!1:void(o(e.target).is(".theme-actions a")||o(e.target).is(".theme-actions a, .update-message, .button-link, .notice-dismiss")||(l.focusedTheme=this.$el,this.trigger("theme:expand",this.model.cid)))},preventExpand:function(){this.touchDrag=!0},preview:function(e){var t,i,s=this;if(e=e||window.event,!0===this.touchDrag)return this.touchDrag=!1;o(e.target).not(".install-theme-preview").parents(".theme-actions").length||"keydown"===e.type&&13!==e.which&&32!==e.which||"keydown"===e.type&&13!==e.which&&o(":focus").hasClass("button")||(e.preventDefault(),e=e||window.event,l.focusedTheme=this.$el,l.preview=i=new l.view.Preview({model:this.model}),i.render(),this.setNavButtonsState(),1===this.model.collection.length?i.$el.addClass("no-navigation"):i.$el.removeClass("no-navigation"),o("div.wrap").append(i.el),this.listenTo(i,"theme:next",function(){if(t=s.model,_.isUndefined(s.current)||(t=s.current),s.current=s.model.collection.at(s.model.collection.indexOf(t)+1),_.isUndefined(s.current))return s.options.parent.parent.trigger("theme:end"),s.current=t;i.model=s.current,i.render(),this.setNavButtonsState(),o(".next-theme").focus()}).listenTo(i,"theme:previous",function(){t=s.model,0!==s.model.collection.indexOf(s.current)&&(_.isUndefined(s.current)||(t=s.current),s.current=s.model.collection.at(s.model.collection.indexOf(t)-1),_.isUndefined(s.current)||(i.model=s.current,i.render(),this.setNavButtonsState(),o(".previous-theme").focus()))}),this.listenTo(i,"preview:close",function(){s.current=s.model}))},setNavButtonsState:function(){var e=o(".theme-install-overlay"),t=_.isUndefined(this.current)?this.model:this.current,i=e.find(".previous-theme"),s=e.find(".next-theme");0===this.model.collection.indexOf(t)&&(i.addClass("disabled").prop("disabled",!0),s.focus()),_.isUndefined(this.model.collection.at(this.model.collection.indexOf(t)+1))&&(s.addClass("disabled").prop("disabled",!0),i.focus())},installTheme:function(e){var i=this;e.preventDefault(),wp.updates.maybeRequestFilesystemCredentials(e),o(document).on("wp-theme-install-success",function(e,t){i.model.get("id")===t.slug&&i.model.set({installed:!0})}),wp.updates.installTheme({slug:o(e.target).data("slug")})},updateTheme:function(e){var i=this;this.model.get("hasPackage")&&(e.preventDefault(),wp.updates.maybeRequestFilesystemCredentials(e),o(document).on("wp-theme-update-success",function(e,t){i.model.off("change",i.render,i),i.model.get("id")===t.slug&&i.model.set({hasUpdate:!1,version:t.newVersion}),i.model.on("change",i.render,i)}),wp.updates.updateTheme({slug:o(e.target).parents("div.theme").first().data("slug")}))}}),l.view.Details=wp.Backbone.View.extend({className:"theme-overlay",events:{click:"collapse","click .delete-theme":"deleteTheme","click .left":"previousTheme","click .right":"nextTheme","click #update-theme":"updateTheme"},html:l.template("theme-single"),render:function(){var e=this.model.toJSON();this.$el.html(this.html(e)),this.activeTheme(),this.navigation(),this.screenshotCheck(this.$el),this.containFocus(this.$el)},activeTheme:function(){this.$el.toggleClass("active",this.model.get("active"))},containFocus:function(s){_.delay(function(){o(".theme-overlay").focus()},100),s.on("keydown.wp-themes",function(e){var t=s.find(".theme-header button:not(.disabled)").first(),i=s.find(".theme-actions a:visible").last();9===e.which&&(t[0]===e.target&&e.shiftKey?(i.focus(),e.preventDefault()):i[0]!==e.target||e.shiftKey||(t.focus(),e.preventDefault()))})},collapse:function(e){var t,i=this;e=e||window.event,1!==l.data.themes.length&&(o(e.target).is(".theme-backdrop")||o(e.target).is(".close")||27===e.keyCode)&&(o("body").addClass("closing-overlay"),this.$el.fadeOut(130,function(){o("body").removeClass("closing-overlay"),i.closeOverlay(),t=document.body.scrollTop,l.router.navigate(l.router.baseUrl("")),document.body.scrollTop=t,l.focusedTheme&&l.focusedTheme.focus()}))},navigation:function(){this.model.cid===this.model.collection.at(0).cid&&this.$el.find(".left").addClass("disabled").prop("disabled",!0),this.model.cid===this.model.collection.at(this.model.collection.length-1).cid&&this.$el.find(".right").addClass("disabled").prop("disabled",!0)},closeOverlay:function(){o("body").removeClass("modal-open"),this.remove(),this.unbind(),this.trigger("theme:collapse")},updateTheme:function(e){var i=this;e.preventDefault(),wp.updates.maybeRequestFilesystemCredentials(e),o(document).on("wp-theme-update-success",function(e,t){i.model.get("id")===t.slug&&i.model.set({hasUpdate:!1,version:t.newVersion}),i.render()}),wp.updates.updateTheme({slug:o(e.target).data("slug")})},deleteTheme:function(e){var i=this,s=i.model.collection,r=l;e.preventDefault(),window.confirm(wp.themes.data.settings.confirmDelete)&&(wp.updates.maybeRequestFilesystemCredentials(e),o(document).one("wp-theme-delete-success",function(e,t){i.$el.find(".close").trigger("click"),o('[data-slug="'+t.slug+'"]').css({backgroundColor:"#faafaa"}).fadeOut(350,function(){o(this).remove(),r.data.themes=_.without(r.data.themes,_.findWhere(r.data.themes,{id:t.slug})),o(".wp-filter-search").val(""),s.doSearch(""),s.remove(i.model),s.trigger("themes:update")})}),wp.updates.deleteTheme({slug:this.model.get("id")}))},nextTheme:function(){return this.trigger("theme:next",this.model.cid),!1},previousTheme:function(){return this.trigger("theme:previous",this.model.cid),!1},screenshotCheck:function(e){var t,i;t=e.find(".screenshot img"),(i=new Image).src=t.attr("src"),i.width&&i.width<=300&&e.addClass("small-screenshot")}}),l.view.Preview=l.view.Details.extend({className:"wp-full-overlay expanded",el:".theme-install-overlay",events:{"click .close-full-overlay":"close","click .collapse-sidebar":"collapse","click .devices button":"previewDevice","click .previous-theme":"previousTheme","click .next-theme":"nextTheme",keyup:"keyEvent","click .theme-install":"installTheme"},html:l.template("theme-preview"),render:function(){var e,t=this,i=this.model.toJSON(),s=o(document.body);s.attr("aria-busy","true"),this.$el.removeClass("iframe-ready").html(this.html(i)),(e=this.$el.data("current-preview-device"))&&t.tooglePreviewDeviceButtons(e),l.router.navigate(l.router.baseUrl(l.router.themePath+this.model.get("id")),{replace:!1}),this.$el.fadeIn(200,function(){s.addClass("theme-installer-active full-overlay-active")}),this.$el.find("iframe").one("load",function(){t.iframeLoaded()})},iframeLoaded:function(){this.$el.addClass("iframe-ready"),o(document.body).attr("aria-busy","false")},close:function(){return this.$el.fadeOut(200,function(){o("body").removeClass("theme-installer-active full-overlay-active"),l.focusedTheme&&l.focusedTheme.focus()}).removeClass("iframe-ready"),l.router.selectedTab?(l.router.navigate(l.router.baseUrl("?browse="+l.router.selectedTab)),l.router.selectedTab=!1):l.router.navigate(l.router.baseUrl("")),this.trigger("preview:close"),this.undelegateEvents(),this.unbind(),!1},collapse:function(e){var t=o(e.currentTarget);return"true"===t.attr("aria-expanded")?t.attr({"aria-expanded":"false","aria-label":a.expandSidebar}):t.attr({"aria-expanded":"true","aria-label":a.collapseSidebar}),this.$el.toggleClass("collapsed").toggleClass("expanded"),!1},previewDevice:function(e){var t=o(e.currentTarget).data("device");this.$el.removeClass("preview-desktop preview-tablet preview-mobile").addClass("preview-"+t).data("current-preview-device",t),this.tooglePreviewDeviceButtons(t)},tooglePreviewDeviceButtons:function(e){var t=o(".wp-full-overlay-footer .devices");t.find("button").removeClass("active").attr("aria-pressed",!1),t.find("button.preview-"+e).addClass("active").attr("aria-pressed",!0)},keyEvent:function(e){27===e.keyCode&&(this.undelegateEvents(),this.close()),39===e.keyCode&&_.once(this.nextTheme()),37===e.keyCode&&this.previousTheme()},installTheme:function(e){var t=this,i=o(e.target);e.preventDefault(),i.hasClass("disabled")||(wp.updates.maybeRequestFilesystemCredentials(e),o(document).on("wp-theme-install-success",function(){t.model.set({installed:!0})}),wp.updates.installTheme({slug:i.data("slug")}))}}),l.view.Themes=wp.Backbone.View.extend({className:"themes wp-clearfix",$overlay:o("div.theme-overlay"),index:0,count:o(".wrap .theme-count"),liveThemeCount:0,initialize:function(e){var t=this;this.parent=e.parent,this.setView("grid"),t.currentTheme(),this.listenTo(t.collection,"themes:update",function(){t.parent.page=0,t.currentTheme(),t.render(this)}),this.listenTo(t.collection,"query:success",function(e){_.isNumber(e)?(t.count.text(e),t.announceSearchResults(e)):(t.count.text(t.collection.length),t.announceSearchResults(t.collection.length))}),this.listenTo(t.collection,"query:empty",function(){o("body").addClass("no-results")}),this.listenTo(this.parent,"theme:scroll",function(){t.renderThemes(t.parent.page)}),this.listenTo(this.parent,"theme:close",function(){t.overlay&&t.overlay.closeOverlay()}),o("body").on("keyup",function(e){t.overlay&&(o("#request-filesystem-credentials-dialog").is(":visible")||(39===e.keyCode&&t.overlay.nextTheme(),37===e.keyCode&&t.overlay.previousTheme(),27===e.keyCode&&t.overlay.collapse(e)))})},render:function(){this.$el.empty(),1===l.data.themes.length&&(this.singleTheme=new l.view.Details({model:this.collection.models[0]}),this.singleTheme.render(),this.$el.addClass("single-theme"),this.$el.append(this.singleTheme.el)),0<this.options.collection.size()&&this.renderThemes(this.parent.page),this.liveThemeCount=this.collection.count?this.collection.count:this.collection.length,this.count.text(this.liveThemeCount),l.isInstall||this.announceSearchResults(this.liveThemeCount)},renderThemes:function(e){var t=this;t.instance=t.collection.paginate(e),0!==t.instance.size()?(!l.isInstall&&1<=e&&o(".add-new-theme").remove(),t.instance.each(function(e){t.theme=new l.view.Theme({model:e,parent:t}),t.theme.render(),t.$el.append(t.theme.el),t.listenTo(t.theme,"theme:expand",t.expand,t)}),!l.isInstall&&l.data.settings.canInstall&&this.$el.append('<div class="theme add-new-theme"><a href="'+l.data.settings.installURI+'"><div class="theme-screenshot"><span></span></div><h2 class="theme-name">'+a.addNew+"</h2></a></div>"),this.parent.page++):this.parent.trigger("theme:end")},currentTheme:function(){var e;(e=this.collection.findWhere({active:!0}))&&(this.collection.remove(e),this.collection.add(e,{at:0}))},setView:function(e){return e},expand:function(e){var t,i,s=this;this.model=s.collection.get(e),l.router.navigate(l.router.baseUrl(l.router.themePath+this.model.id)),this.setView("detail"),o("body").addClass("modal-open"),this.overlay=new l.view.Details({model:s.model}),this.overlay.render(),this.model.get("hasUpdate")&&(t=o('[data-slug="'+this.model.id+'"]'),i=o(this.overlay.el),t.find(".updating-message").length?(i.find(".notice-warning h3").remove(),i.find(".notice-warning").removeClass("notice-large").addClass("updating-message").find("p").text(wp.updates.l10n.updating)):t.find(".notice-error").length&&i.find(".notice-warning").remove()),this.$overlay.html(this.overlay.el),this.listenTo(this.overlay,"theme:next",function(){s.next([s.model.cid])}).listenTo(this.overlay,"theme:previous",function(){s.previous([s.model.cid])})},next:function(e){var t,i;t=this.collection.get(e[0]),void 0!==(i=this.collection.at(this.collection.indexOf(t)+1))&&(this.overlay.closeOverlay(),this.theme.trigger("theme:expand",i.cid))},previous:function(e){var t,i;t=this.collection.get(e[0]),void 0!==(i=this.collection.at(this.collection.indexOf(t)-1))&&(this.overlay.closeOverlay(),this.theme.trigger("theme:expand",i.cid))},announceSearchResults:function(e){0===e?wp.a11y.speak(a.noThemesFound):wp.a11y.speak(a.themesFound.replace("%d",e))}}),l.view.Search=wp.Backbone.View.extend({tagName:"input",className:"wp-filter-search",id:"wp-filter-search-input",searching:!1,attributes:{placeholder:a.searchPlaceholder,type:"search","aria-describedby":"live-search-desc"},events:{input:"search",keyup:"search",blur:"pushState"},initialize:function(e){this.parent=e.parent,this.listenTo(this.parent,"theme:close",function(){this.searching=!1})},search:function(e){"keyup"===e.type&&27===e.which&&(e.target.value=""),this.doSearch(e)},doSearch:function(e){var t={};this.collection.doSearch(e.target.value.replace(/\+/g," ")),this.searching&&13!==e.which?t.replace=!0:this.searching=!0,e.target.value?l.router.navigate(l.router.baseUrl(l.router.searchPath+e.target.value),t):l.router.navigate(l.router.baseUrl(""))},pushState:function(e){var t=l.router.baseUrl("");e.target.value&&(t=l.router.baseUrl(l.router.searchPath+encodeURIComponent(e.target.value))),this.searching=!1,l.router.navigate(t)}}),l.Router=Backbone.Router.extend({routes:{"themes.php?theme=:slug":"theme","themes.php?search=:query":"search","themes.php?s=:query":"search","themes.php":"themes","":"themes"},baseUrl:function(e){return"themes.php"+e},themePath:"?theme=",searchPath:"?search=",search:function(e){o(".wp-filter-search").val(e.replace(/\+/g," "))},themes:function(){o(".wp-filter-search").val("")},navigate:e}),l.Run={init:function(){this.themes=new l.Collection(l.data.themes),this.view=new l.view.Appearance({collection:this.themes}),this.render(),this.view.SearchView.doSearch=_.debounce(this.view.SearchView.doSearch,500)},render:function(){this.view.render(),this.routes(),Backbone.History.started&&Backbone.history.stop(),Backbone.history.start({root:l.data.settings.adminUrl,pushState:!0,hashChange:!1})},routes:function(){var t=this;l.router=new l.Router,l.router.on("route:theme",function(e){t.view.view.expand(e)}),l.router.on("route:themes",function(){t.themes.doSearch(""),t.view.trigger("theme:close")}),l.router.on("route:search",function(){o(".wp-filter-search").trigger("keyup")}),this.extraRoutes()},extraRoutes:function(){return!1}},l.view.InstallerSearch=l.view.Search.extend({events:{input:"search",keyup:"search"},terms:"",search:function(e){("keyup"!==e.type||9!==e.which&&16!==e.which)&&(this.collection=this.options.parent.view.collection,"keyup"===e.type&&27===e.which&&(e.target.value=""),this.doSearch(e.target.value))},doSearch:function(e){var t={};this.terms!==e&&(this.terms=e,"author:"===(t.search=e).substring(0,7)&&(t.search="",t.author=e.slice(7)),"tag:"===e.substring(0,4)&&(t.search="",t.tag=[e.slice(4)]),o(".filter-links li > a.current").removeClass("current").removeAttr("aria-current"),o("body").removeClass("show-filters filters-applied show-favorites-form"),o(".drawer-toggle").attr("aria-expanded","false"),this.collection.query(t),l.router.navigate(l.router.baseUrl(l.router.searchPath+encodeURIComponent(e)),{replace:!0}))}}),l.view.Installer=l.view.Appearance.extend({el:"#wpbody-content .wrap",events:{"click .filter-links li > a":"onSort","click .theme-filter":"onFilter","click .drawer-toggle":"moreFilters","click .filter-drawer .apply-filters":"applyFilters",'click .filter-group [type="checkbox"]':"addFilter","click .filter-drawer .clear-filters":"clearFilters","click .edit-filters":"backToFilters","click .favorites-form-submit":"saveUsername","keyup #wporg-username-input":"saveUsername"},render:function(){var e=this;this.search(),this.uploader(),this.collection=new l.Collection,this.listenTo(this,"theme:end",function(){e.collection.loadingThemes||(e.collection.loadingThemes=!0,e.collection.currentQuery.page++,_.extend(e.collection.currentQuery.request,{page:e.collection.currentQuery.page}),e.collection.query(e.collection.currentQuery.request))}),this.listenTo(this.collection,"query:success",function(){o("body").removeClass("loading-content"),o(".theme-browser").find("div.error").remove()}),this.listenTo(this.collection,"query:fail",function(){o("body").removeClass("loading-content"),o(".theme-browser").find("div.error").remove(),o(".theme-browser").find("div.themes").before('<div class="error"><p>'+a.error+'</p><p><button class="button try-again">'+a.tryAgain+"</button></p></div>"),o(".theme-browser .error .try-again").on("click",function(e){e.preventDefault(),o("input.wp-filter-search").trigger("input")})}),this.view&&this.view.remove(),this.view=new l.view.Themes({collection:this.collection,parent:this}),this.page=0,this.$el.find(".themes").remove(),this.view.render(),this.$el.find(".theme-browser").append(this.view.el).addClass("rendered")},browse:function(e){this.collection.query({browse:e})},onSort:function(e){var t=o(e.target),i=t.data("sort");e.preventDefault(),o("body").removeClass("filters-applied show-filters"),o(".drawer-toggle").attr("aria-expanded","false"),t.hasClass(this.activeClass)||(this.sort(i),l.router.navigate(l.router.baseUrl(l.router.browsePath+i)))},sort:function(e){this.clearSearch(),l.router.selectedTab=e,o(".filter-links li > a, .theme-filter").removeClass(this.activeClass).removeAttr("aria-current"),o('[data-sort="'+e+'"]').addClass(this.activeClass).attr("aria-current","page"),"favorites"===e?o("body").addClass("show-favorites-form"):o("body").removeClass("show-favorites-form"),this.browse(e)},onFilter:function(e){var t,i=o(e.target),s=i.data("filter");i.hasClass(this.activeClass)||(o(".filter-links li > a, .theme-section").removeClass(this.activeClass).removeAttr("aria-current"),i.addClass(this.activeClass).attr("aria-current","page"),s&&(t={tag:[s=_.union([s,this.filtersChecked()])]},this.collection.query(t)))},addFilter:function(){this.filtersChecked()},applyFilters:function(e){var t,i=this.filtersChecked(),s={tag:i},r=o(".filtered-by .tags");e&&e.preventDefault(),i?(o("body").addClass("filters-applied"),o(".filter-links li > a.current").removeClass("current").removeAttr("aria-current"),r.empty(),_.each(i,function(e){t=o('label[for="filter-id-'+e+'"]').text(),r.append('<span class="tag">'+t+"</span>")}),this.collection.query(s)):wp.a11y.speak(a.selectFeatureFilter)},saveUsername:function(e){var t=o("#wporg-username-input").val(),i=o("#wporg-username-nonce").val(),s={browse:"favorites",user:t},r=this;if(e&&e.preventDefault(),"keyup"!==e.type||13===e.which)return wp.ajax.send("save-wporg-username",{data:{_wpnonce:i,username:t},success:function(){r.collection.query(s)}})},filtersChecked:function(){var e=o(".filter-group").find(":checkbox"),t=[];return _.each(e.filter(":checked"),function(e){t.push(o(e).prop("value"))}),0===t.length?(o(".filter-drawer .apply-filters").find("span").text(""),o(".filter-drawer .clear-filters").hide(),o("body").removeClass("filters-applied"),!1):(o(".filter-drawer .apply-filters").find("span").text(t.length),o(".filter-drawer .clear-filters").css("display","inline-block"),t)},activeClass:"current",uploader:function(){var e=o(".upload-view-toggle"),t=o(document.body);e.on("click",function(){t.toggleClass("show-upload-view"),e.attr("aria-expanded",t.hasClass("show-upload-view"))})},moreFilters:function(e){var t=o("body"),i=o(".drawer-toggle");if(e.preventDefault(),t.hasClass("filters-applied"))return this.backToFilters();this.clearSearch(),l.router.navigate(l.router.baseUrl("")),t.toggleClass("show-filters"),i.attr("aria-expanded",t.hasClass("show-filters"))},clearFilters:function(e){var t=o(".filter-group").find(":checkbox"),i=this;e.preventDefault(),_.each(t.filter(":checked"),function(e){return o(e).prop("checked",!1),i.filtersChecked()})},backToFilters:function(e){e&&e.preventDefault(),o("body").removeClass("filters-applied")},clearSearch:function(){o("#wp-filter-search-input").val("")}}),l.InstallerRouter=Backbone.Router.extend({routes:{"theme-install.php?theme=:slug":"preview","theme-install.php?browse=:sort":"sort","theme-install.php?search=:query":"search","theme-install.php":"sort"},baseUrl:function(e){return"theme-install.php"+e},themePath:"?theme=",browsePath:"?browse=",searchPath:"?search=",search:function(e){o(".wp-filter-search").val(e.replace(/\+/g," "))},navigate:e}),l.RunInstaller={init:function(){this.view=new l.view.Installer({section:"featured",SearchView:l.view.InstallerSearch}),this.render(),this.view.SearchView.doSearch=_.debounce(this.view.SearchView.doSearch,500)},render:function(){this.view.render(),this.routes(),Backbone.History.started&&Backbone.history.stop(),Backbone.history.start({root:l.data.settings.adminUrl,pushState:!0,hashChange:!1})},routes:function(){var t=this,i={};l.router=new l.InstallerRouter,l.router.on("route:preview",function(e){l.preview&&(l.preview.undelegateEvents(),l.preview.unbind()),t.view.view.theme&&t.view.view.theme.preview?(t.view.view.theme.model=t.view.collection.findWhere({slug:e}),t.view.view.theme.preview()):(i.theme=e,t.view.collection.query(i),t.view.collection.trigger("update"),t.view.collection.once("query:success",function(){o('div[data-slug="'+e+'"]').trigger("click")}))}),l.router.on("route:sort",function(e){e||(e="featured",l.router.navigate(l.router.baseUrl("?browse=featured"),{replace:!0})),t.view.sort(e),l.preview&&l.preview.close()}),l.router.on("route:search",function(){o(".wp-filter-search").focus().trigger("keyup")}),this.extraRoutes()},extraRoutes:function(){return!1}},o(document).ready(function(){l.isInstall?l.RunInstaller.init():l.Run.init(),o(document.body).on("click",".load-customize",function(){var e=o(this),t=document.createElement("a");t.href=e.prop("href"),t.search=o.param(_.extend(wp.customize.utils.parseQueryString(t.search.substr(1)),{return:window.location.href})),e.prop("href",t.href)}),o(".broken-themes .delete-theme").on("click",function(){return confirm(_wpThemeSettings.settings.confirmDelete)})})}(jQuery),jQuery(document).ready(function(a){window.tb_position=function(){var e=a("#TB_window"),t=a(window).width(),i=a(window).height(),s=1040<t?1040:t,r=0;a("#wpadminbar").length&&(r=parseInt(a("#wpadminbar").css("height"),10)),e.size()&&(e.width(s-50).height(i-45-r),a("#TB_iframeContent").width(s-50).height(i-75-r),e.css({"margin-left":"-"+parseInt((s-50)/2,10)+"px"}),void 0!==document.body.style.maxWidth&&e.css({top:20+r+"px","margin-top":"0"}))},a(window).resize(function(){tb_position()})});
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/updates.js b/srcs/wordpress/wp-admin/js/updates.js deleted file mode 100644 index ee5bf3c..0000000 --- a/srcs/wordpress/wp-admin/js/updates.js +++ /dev/null @@ -1,2465 +0,0 @@ -/** - * Functions for ajaxified updates, deletions and installs inside the WordPress admin. - * - * @version 4.2.0 - * @output wp-admin/js/updates.js - */ - -/* global pagenow */ - -/** - * @param {jQuery} $ jQuery object. - * @param {object} wp WP object. - * @param {object} settings WP Updates settings. - * @param {string} settings.ajax_nonce AJAX nonce. - * @param {object} settings.l10n Translation strings. - * @param {object=} settings.plugins Base names of plugins in their different states. - * @param {Array} settings.plugins.all Base names of all plugins. - * @param {Array} settings.plugins.active Base names of active plugins. - * @param {Array} settings.plugins.inactive Base names of inactive plugins. - * @param {Array} settings.plugins.upgrade Base names of plugins with updates available. - * @param {Array} settings.plugins.recently_activated Base names of recently activated plugins. - * @param {object=} settings.themes Plugin/theme status information or null. - * @param {number} settings.themes.all Amount of all themes. - * @param {number} settings.themes.upgrade Amount of themes with updates available. - * @param {number} settings.themes.disabled Amount of disabled themes. - * @param {object=} settings.totals Combined information for available update counts. - * @param {number} settings.totals.count Holds the amount of available updates. - */ -(function( $, wp, settings ) { - var $document = $( document ); - - wp = wp || {}; - - /** - * The WP Updates object. - * - * @since 4.2.0 - * - * @namespace wp.updates - */ - wp.updates = {}; - - /** - * User nonce for ajax calls. - * - * @since 4.2.0 - * - * @type {string} - */ - wp.updates.ajaxNonce = settings.ajax_nonce; - - /** - * Localized strings. - * - * @since 4.2.0 - * - * @type {object} - */ - wp.updates.l10n = settings.l10n; - - /** - * Current search term. - * - * @since 4.6.0 - * - * @type {string} - */ - wp.updates.searchTerm = ''; - - /** - * Whether filesystem credentials need to be requested from the user. - * - * @since 4.2.0 - * - * @type {bool} - */ - wp.updates.shouldRequestFilesystemCredentials = false; - - /** - * Filesystem credentials to be packaged along with the request. - * - * @since 4.2.0 - * @since 4.6.0 Added `available` property to indicate whether credentials have been provided. - * - * @type {Object} - * @property {Object} filesystemCredentials.ftp Holds FTP credentials. - * @property {string} filesystemCredentials.ftp.host FTP host. Default empty string. - * @property {string} filesystemCredentials.ftp.username FTP user name. Default empty string. - * @property {string} filesystemCredentials.ftp.password FTP password. Default empty string. - * @property {string} filesystemCredentials.ftp.connectionType Type of FTP connection. 'ssh', 'ftp', or 'ftps'. - * Default empty string. - * @property {Object} filesystemCredentials.ssh Holds SSH credentials. - * @property {string} filesystemCredentials.ssh.publicKey The public key. Default empty string. - * @property {string} filesystemCredentials.ssh.privateKey The private key. Default empty string. - * @property {string} filesystemCredentials.fsNonce Filesystem credentials form nonce. - * @property {bool} filesystemCredentials.available Whether filesystem credentials have been provided. - * Default 'false'. - */ - wp.updates.filesystemCredentials = { - ftp: { - host: '', - username: '', - password: '', - connectionType: '' - }, - ssh: { - publicKey: '', - privateKey: '' - }, - fsNonce: '', - available: false - }; - - /** - * Whether we're waiting for an Ajax request to complete. - * - * @since 4.2.0 - * @since 4.6.0 More accurately named `ajaxLocked`. - * - * @type {bool} - */ - wp.updates.ajaxLocked = false; - - /** - * Admin notice template. - * - * @since 4.6.0 - * - * @type {function} - */ - wp.updates.adminNotice = wp.template( 'wp-updates-admin-notice' ); - - /** - * Update queue. - * - * If the user tries to update a plugin while an update is - * already happening, it can be placed in this queue to perform later. - * - * @since 4.2.0 - * @since 4.6.0 More accurately named `queue`. - * - * @type {Array.object} - */ - wp.updates.queue = []; - - /** - * Holds a jQuery reference to return focus to when exiting the request credentials modal. - * - * @since 4.2.0 - * - * @type {jQuery} - */ - wp.updates.$elToReturnFocusToFromCredentialsModal = undefined; - - /** - * Adds or updates an admin notice. - * - * @since 4.6.0 - * - * @param {object} data - * @param {*=} data.selector Optional. Selector of an element to be replaced with the admin notice. - * @param {string=} data.id Optional. Unique id that will be used as the notice's id attribute. - * @param {string=} data.className Optional. Class names that will be used in the admin notice. - * @param {string=} data.message Optional. The message displayed in the notice. - * @param {number=} data.successes Optional. The amount of successful operations. - * @param {number=} data.errors Optional. The amount of failed operations. - * @param {Array=} data.errorMessages Optional. Error messages of failed operations. - * - */ - wp.updates.addAdminNotice = function( data ) { - var $notice = $( data.selector ), - $headerEnd = $( '.wp-header-end' ), - $adminNotice; - - delete data.selector; - $adminNotice = wp.updates.adminNotice( data ); - - // Check if this admin notice already exists. - if ( ! $notice.length ) { - $notice = $( '#' + data.id ); - } - - if ( $notice.length ) { - $notice.replaceWith( $adminNotice ); - } else if ( $headerEnd.length ) { - $headerEnd.after( $adminNotice ); - } else { - if ( 'customize' === pagenow ) { - $( '.customize-themes-notifications' ).append( $adminNotice ); - } else { - $( '.wrap' ).find( '> h1' ).after( $adminNotice ); - } - } - - $document.trigger( 'wp-updates-notice-added' ); - }; - - /** - * Handles Ajax requests to WordPress. - * - * @since 4.6.0 - * - * @param {string} action The type of Ajax request ('update-plugin', 'install-theme', etc). - * @param {object} data Data that needs to be passed to the ajax callback. - * @return {$.promise} A jQuery promise that represents the request, - * decorated with an abort() method. - */ - wp.updates.ajax = function( action, data ) { - var options = {}; - - if ( wp.updates.ajaxLocked ) { - wp.updates.queue.push( { - action: action, - data: data - } ); - - // Return a Deferred object so callbacks can always be registered. - return $.Deferred(); - } - - wp.updates.ajaxLocked = true; - - if ( data.success ) { - options.success = data.success; - delete data.success; - } - - if ( data.error ) { - options.error = data.error; - delete data.error; - } - - options.data = _.extend( data, { - action: action, - _ajax_nonce: wp.updates.ajaxNonce, - _fs_nonce: wp.updates.filesystemCredentials.fsNonce, - username: wp.updates.filesystemCredentials.ftp.username, - password: wp.updates.filesystemCredentials.ftp.password, - hostname: wp.updates.filesystemCredentials.ftp.hostname, - connection_type: wp.updates.filesystemCredentials.ftp.connectionType, - public_key: wp.updates.filesystemCredentials.ssh.publicKey, - private_key: wp.updates.filesystemCredentials.ssh.privateKey - } ); - - return wp.ajax.send( options ).always( wp.updates.ajaxAlways ); - }; - - /** - * Actions performed after every Ajax request. - * - * @since 4.6.0 - * - * @param {object} response - * @param {array=} response.debug Optional. Debug information. - * @param {string=} response.errorCode Optional. Error code for an error that occurred. - */ - wp.updates.ajaxAlways = function( response ) { - if ( ! response.errorCode || 'unable_to_connect_to_filesystem' !== response.errorCode ) { - wp.updates.ajaxLocked = false; - wp.updates.queueChecker(); - } - - if ( 'undefined' !== typeof response.debug && window.console && window.console.log ) { - _.map( response.debug, function( message ) { - // Remove all HTML tags and write a message to the console. - window.console.log( wp.sanitize.stripTagsAndEncodeText( message ) ); - } ); - } - }; - - /** - * Refreshes update counts everywhere on the screen. - * - * @since 4.7.0 - */ - wp.updates.refreshCount = function() { - var $adminBarUpdates = $( '#wp-admin-bar-updates' ), - $dashboardNavMenuUpdateCount = $( 'a[href="update-core.php"] .update-plugins' ), - $pluginsNavMenuUpdateCount = $( 'a[href="plugins.php"] .update-plugins' ), - $appearanceNavMenuUpdateCount = $( 'a[href="themes.php"] .update-plugins' ), - itemCount; - - $adminBarUpdates.find( '.ab-item' ).removeAttr( 'title' ); - $adminBarUpdates.find( '.ab-label' ).text( settings.totals.counts.total ); - - // Remove the update count from the toolbar if it's zero. - if ( 0 === settings.totals.counts.total ) { - $adminBarUpdates.find( '.ab-label' ).parents( 'li' ).remove(); - } - - // Update the "Updates" menu item. - $dashboardNavMenuUpdateCount.each( function( index, element ) { - element.className = element.className.replace( /count-\d+/, 'count-' + settings.totals.counts.total ); - } ); - if ( settings.totals.counts.total > 0 ) { - $dashboardNavMenuUpdateCount.find( '.update-count' ).text( settings.totals.counts.total ); - } else { - $dashboardNavMenuUpdateCount.remove(); - } - - // Update the "Plugins" menu item. - $pluginsNavMenuUpdateCount.each( function( index, element ) { - element.className = element.className.replace( /count-\d+/, 'count-' + settings.totals.counts.plugins ); - } ); - if ( settings.totals.counts.total > 0 ) { - $pluginsNavMenuUpdateCount.find( '.plugin-count' ).text( settings.totals.counts.plugins ); - } else { - $pluginsNavMenuUpdateCount.remove(); - } - - // Update the "Appearance" menu item. - $appearanceNavMenuUpdateCount.each( function( index, element ) { - element.className = element.className.replace( /count-\d+/, 'count-' + settings.totals.counts.themes ); - } ); - if ( settings.totals.counts.total > 0 ) { - $appearanceNavMenuUpdateCount.find( '.theme-count' ).text( settings.totals.counts.themes ); - } else { - $appearanceNavMenuUpdateCount.remove(); - } - - // Update list table filter navigation. - if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) { - itemCount = settings.totals.counts.plugins; - } else if ( 'themes' === pagenow || 'themes-network' === pagenow ) { - itemCount = settings.totals.counts.themes; - } - - if ( itemCount > 0 ) { - $( '.subsubsub .upgrade .count' ).text( '(' + itemCount + ')' ); - } else { - $( '.subsubsub .upgrade' ).remove(); - $( '.subsubsub li:last' ).html( function() { return $( this ).children(); } ); - } - }; - - /** - * Decrements the update counts throughout the various menus. - * - * This includes the toolbar, the "Updates" menu item and the menu items - * for plugins and themes. - * - * @since 3.9.0 - * - * @param {string} type The type of item that was updated or deleted. - * Can be 'plugin', 'theme'. - */ - wp.updates.decrementCount = function( type ) { - settings.totals.counts.total = Math.max( --settings.totals.counts.total, 0 ); - - if ( 'plugin' === type ) { - settings.totals.counts.plugins = Math.max( --settings.totals.counts.plugins, 0 ); - } else if ( 'theme' === type ) { - settings.totals.counts.themes = Math.max( --settings.totals.counts.themes, 0 ); - } - - wp.updates.refreshCount( type ); - }; - - /** - * Sends an Ajax request to the server to update a plugin. - * - * @since 4.2.0 - * @since 4.6.0 More accurately named `updatePlugin`. - * - * @param {object} args Arguments. - * @param {string} args.plugin Plugin basename. - * @param {string} args.slug Plugin slug. - * @param {updatePluginSuccess=} args.success Optional. Success callback. Default: wp.updates.updatePluginSuccess - * @param {updatePluginError=} args.error Optional. Error callback. Default: wp.updates.updatePluginError - * @return {$.promise} A jQuery promise that represents the request, - * decorated with an abort() method. - */ - wp.updates.updatePlugin = function( args ) { - var $updateRow, $card, $message, message; - - args = _.extend( { - success: wp.updates.updatePluginSuccess, - error: wp.updates.updatePluginError - }, args ); - - if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) { - $updateRow = $( 'tr[data-plugin="' + args.plugin + '"]' ); - $message = $updateRow.find( '.update-message' ).removeClass( 'notice-error' ).addClass( 'updating-message notice-warning' ).find( 'p' ); - message = wp.updates.l10n.pluginUpdatingLabel.replace( '%s', $updateRow.find( '.plugin-title strong' ).text() ); - } else if ( 'plugin-install' === pagenow || 'plugin-install-network' === pagenow ) { - $card = $( '.plugin-card-' + args.slug ); - $message = $card.find( '.update-now' ).addClass( 'updating-message' ); - message = wp.updates.l10n.pluginUpdatingLabel.replace( '%s', $message.data( 'name' ) ); - - // Remove previous error messages, if any. - $card.removeClass( 'plugin-card-update-failed' ).find( '.notice.notice-error' ).remove(); - } - - if ( $message.html() !== wp.updates.l10n.updating ) { - $message.data( 'originaltext', $message.html() ); - } - - $message - .attr( 'aria-label', message ) - .text( wp.updates.l10n.updating ); - - $document.trigger( 'wp-plugin-updating', args ); - - return wp.updates.ajax( 'update-plugin', args ); - }; - - /** - * Updates the UI appropriately after a successful plugin update. - * - * @since 4.2.0 - * @since 4.6.0 More accurately named `updatePluginSuccess`. - * - * @param {object} response Response from the server. - * @param {string} response.slug Slug of the plugin to be updated. - * @param {string} response.plugin Basename of the plugin to be updated. - * @param {string} response.pluginName Name of the plugin to be updated. - * @param {string} response.oldVersion Old version of the plugin. - * @param {string} response.newVersion New version of the plugin. - */ - wp.updates.updatePluginSuccess = function( response ) { - var $pluginRow, $updateMessage, newText; - - if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) { - $pluginRow = $( 'tr[data-plugin="' + response.plugin + '"]' ) - .removeClass( 'update' ) - .addClass( 'updated' ); - $updateMessage = $pluginRow.find( '.update-message' ) - .removeClass( 'updating-message notice-warning' ) - .addClass( 'updated-message notice-success' ).find( 'p' ); - - // Update the version number in the row. - newText = $pluginRow.find( '.plugin-version-author-uri' ).html().replace( response.oldVersion, response.newVersion ); - $pluginRow.find( '.plugin-version-author-uri' ).html( newText ); - } else if ( 'plugin-install' === pagenow || 'plugin-install-network' === pagenow ) { - $updateMessage = $( '.plugin-card-' + response.slug ).find( '.update-now' ) - .removeClass( 'updating-message' ) - .addClass( 'button-disabled updated-message' ); - } - - $updateMessage - .attr( 'aria-label', wp.updates.l10n.pluginUpdatedLabel.replace( '%s', response.pluginName ) ) - .text( wp.updates.l10n.pluginUpdated ); - - wp.a11y.speak( wp.updates.l10n.updatedMsg, 'polite' ); - - wp.updates.decrementCount( 'plugin' ); - - $document.trigger( 'wp-plugin-update-success', response ); - }; - - /** - * Updates the UI appropriately after a failed plugin update. - * - * @since 4.2.0 - * @since 4.6.0 More accurately named `updatePluginError`. - * - * @param {object} response Response from the server. - * @param {string} response.slug Slug of the plugin to be updated. - * @param {string} response.plugin Basename of the plugin to be updated. - * @param {string=} response.pluginName Optional. Name of the plugin to be updated. - * @param {string} response.errorCode Error code for the error that occurred. - * @param {string} response.errorMessage The error that occurred. - */ - wp.updates.updatePluginError = function( response ) { - var $card, $message, errorMessage; - - if ( ! wp.updates.isValidResponse( response, 'update' ) ) { - return; - } - - if ( wp.updates.maybeHandleCredentialError( response, 'update-plugin' ) ) { - return; - } - - errorMessage = wp.updates.l10n.updateFailed.replace( '%s', response.errorMessage ); - - if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) { - if ( response.plugin ) { - $message = $( 'tr[data-plugin="' + response.plugin + '"]' ).find( '.update-message' ); - } else { - $message = $( 'tr[data-slug="' + response.slug + '"]' ).find( '.update-message' ); - } - $message.removeClass( 'updating-message notice-warning' ).addClass( 'notice-error' ).find( 'p' ).html( errorMessage ); - - if ( response.pluginName ) { - $message.find( 'p' ) - .attr( 'aria-label', wp.updates.l10n.pluginUpdateFailedLabel.replace( '%s', response.pluginName ) ); - } else { - $message.find( 'p' ).removeAttr( 'aria-label' ); - } - } else if ( 'plugin-install' === pagenow || 'plugin-install-network' === pagenow ) { - $card = $( '.plugin-card-' + response.slug ) - .addClass( 'plugin-card-update-failed' ) - .append( wp.updates.adminNotice( { - className: 'update-message notice-error notice-alt is-dismissible', - message: errorMessage - } ) ); - - $card.find( '.update-now' ) - .text( wp.updates.l10n.updateFailedShort ).removeClass( 'updating-message' ); - - if ( response.pluginName ) { - $card.find( '.update-now' ) - .attr( 'aria-label', wp.updates.l10n.pluginUpdateFailedLabel.replace( '%s', response.pluginName ) ); - } else { - $card.find( '.update-now' ).removeAttr( 'aria-label' ); - } - - $card.on( 'click', '.notice.is-dismissible .notice-dismiss', function() { - - // Use same delay as the total duration of the notice fadeTo + slideUp animation. - setTimeout( function() { - $card - .removeClass( 'plugin-card-update-failed' ) - .find( '.column-name a' ).focus(); - - $card.find( '.update-now' ) - .attr( 'aria-label', false ) - .text( wp.updates.l10n.updateNow ); - }, 200 ); - } ); - } - - wp.a11y.speak( errorMessage, 'assertive' ); - - $document.trigger( 'wp-plugin-update-error', response ); - }; - - /** - * Sends an Ajax request to the server to install a plugin. - * - * @since 4.6.0 - * - * @param {object} args Arguments. - * @param {string} args.slug Plugin identifier in the WordPress.org Plugin repository. - * @param {installPluginSuccess=} args.success Optional. Success callback. Default: wp.updates.installPluginSuccess - * @param {installPluginError=} args.error Optional. Error callback. Default: wp.updates.installPluginError - * @return {$.promise} A jQuery promise that represents the request, - * decorated with an abort() method. - */ - wp.updates.installPlugin = function( args ) { - var $card = $( '.plugin-card-' + args.slug ), - $message = $card.find( '.install-now' ); - - args = _.extend( { - success: wp.updates.installPluginSuccess, - error: wp.updates.installPluginError - }, args ); - - if ( 'import' === pagenow ) { - $message = $( '[data-slug="' + args.slug + '"]' ); - } - - if ( $message.html() !== wp.updates.l10n.installing ) { - $message.data( 'originaltext', $message.html() ); - } - - $message - .addClass( 'updating-message' ) - .attr( 'aria-label', wp.updates.l10n.pluginInstallingLabel.replace( '%s', $message.data( 'name' ) ) ) - .text( wp.updates.l10n.installing ); - - wp.a11y.speak( wp.updates.l10n.installingMsg, 'polite' ); - - // Remove previous error messages, if any. - $card.removeClass( 'plugin-card-install-failed' ).find( '.notice.notice-error' ).remove(); - - $document.trigger( 'wp-plugin-installing', args ); - - return wp.updates.ajax( 'install-plugin', args ); - }; - - /** - * Updates the UI appropriately after a successful plugin install. - * - * @since 4.6.0 - * - * @param {object} response Response from the server. - * @param {string} response.slug Slug of the installed plugin. - * @param {string} response.pluginName Name of the installed plugin. - * @param {string} response.activateUrl URL to activate the just installed plugin. - */ - wp.updates.installPluginSuccess = function( response ) { - var $message = $( '.plugin-card-' + response.slug ).find( '.install-now' ); - - $message - .removeClass( 'updating-message' ) - .addClass( 'updated-message installed button-disabled' ) - .attr( 'aria-label', wp.updates.l10n.pluginInstalledLabel.replace( '%s', response.pluginName ) ) - .text( wp.updates.l10n.pluginInstalled ); - - wp.a11y.speak( wp.updates.l10n.installedMsg, 'polite' ); - - $document.trigger( 'wp-plugin-install-success', response ); - - if ( response.activateUrl ) { - setTimeout( function() { - - // Transform the 'Install' button into an 'Activate' button. - $message.removeClass( 'install-now installed button-disabled updated-message' ).addClass( 'activate-now button-primary' ) - .attr( 'href', response.activateUrl ) - .attr( 'aria-label', wp.updates.l10n.activatePluginLabel.replace( '%s', response.pluginName ) ) - .text( wp.updates.l10n.activatePlugin ); - }, 1000 ); - } - }; - - /** - * Updates the UI appropriately after a failed plugin install. - * - * @since 4.6.0 - * - * @param {object} response Response from the server. - * @param {string} response.slug Slug of the plugin to be installed. - * @param {string=} response.pluginName Optional. Name of the plugin to be installed. - * @param {string} response.errorCode Error code for the error that occurred. - * @param {string} response.errorMessage The error that occurred. - */ - wp.updates.installPluginError = function( response ) { - var $card = $( '.plugin-card-' + response.slug ), - $button = $card.find( '.install-now' ), - errorMessage; - - if ( ! wp.updates.isValidResponse( response, 'install' ) ) { - return; - } - - if ( wp.updates.maybeHandleCredentialError( response, 'install-plugin' ) ) { - return; - } - - errorMessage = wp.updates.l10n.installFailed.replace( '%s', response.errorMessage ); - - $card - .addClass( 'plugin-card-update-failed' ) - .append( '<div class="notice notice-error notice-alt is-dismissible"><p>' + errorMessage + '</p></div>' ); - - $card.on( 'click', '.notice.is-dismissible .notice-dismiss', function() { - - // Use same delay as the total duration of the notice fadeTo + slideUp animation. - setTimeout( function() { - $card - .removeClass( 'plugin-card-update-failed' ) - .find( '.column-name a' ).focus(); - }, 200 ); - } ); - - $button - .removeClass( 'updating-message' ).addClass( 'button-disabled' ) - .attr( 'aria-label', wp.updates.l10n.pluginInstallFailedLabel.replace( '%s', $button.data( 'name' ) ) ) - .text( wp.updates.l10n.installFailedShort ); - - wp.a11y.speak( errorMessage, 'assertive' ); - - $document.trigger( 'wp-plugin-install-error', response ); - }; - - /** - * Updates the UI appropriately after a successful importer install. - * - * @since 4.6.0 - * - * @param {object} response Response from the server. - * @param {string} response.slug Slug of the installed plugin. - * @param {string} response.pluginName Name of the installed plugin. - * @param {string} response.activateUrl URL to activate the just installed plugin. - */ - wp.updates.installImporterSuccess = function( response ) { - wp.updates.addAdminNotice( { - id: 'install-success', - className: 'notice-success is-dismissible', - message: wp.updates.l10n.importerInstalledMsg.replace( '%s', response.activateUrl + '&from=import' ) - } ); - - $( '[data-slug="' + response.slug + '"]' ) - .removeClass( 'install-now updating-message' ) - .addClass( 'activate-now' ) - .attr({ - 'href': response.activateUrl + '&from=import', - 'aria-label': wp.updates.l10n.activateImporterLabel.replace( '%s', response.pluginName ) - }) - .text( wp.updates.l10n.activateImporter ); - - wp.a11y.speak( wp.updates.l10n.installedMsg, 'polite' ); - - $document.trigger( 'wp-importer-install-success', response ); - }; - - /** - * Updates the UI appropriately after a failed importer install. - * - * @since 4.6.0 - * - * @param {object} response Response from the server. - * @param {string} response.slug Slug of the plugin to be installed. - * @param {string=} response.pluginName Optional. Name of the plugin to be installed. - * @param {string} response.errorCode Error code for the error that occurred. - * @param {string} response.errorMessage The error that occurred. - */ - wp.updates.installImporterError = function( response ) { - var errorMessage = wp.updates.l10n.installFailed.replace( '%s', response.errorMessage ), - $installLink = $( '[data-slug="' + response.slug + '"]' ), - pluginName = $installLink.data( 'name' ); - - if ( ! wp.updates.isValidResponse( response, 'install' ) ) { - return; - } - - if ( wp.updates.maybeHandleCredentialError( response, 'install-plugin' ) ) { - return; - } - - wp.updates.addAdminNotice( { - id: response.errorCode, - className: 'notice-error is-dismissible', - message: errorMessage - } ); - - $installLink - .removeClass( 'updating-message' ) - .text( wp.updates.l10n.installNow ) - .attr( 'aria-label', wp.updates.l10n.pluginInstallNowLabel.replace( '%s', pluginName ) ); - - wp.a11y.speak( errorMessage, 'assertive' ); - - $document.trigger( 'wp-importer-install-error', response ); - }; - - /** - * Sends an Ajax request to the server to delete a plugin. - * - * @since 4.6.0 - * - * @param {object} args Arguments. - * @param {string} args.plugin Basename of the plugin to be deleted. - * @param {string} args.slug Slug of the plugin to be deleted. - * @param {deletePluginSuccess=} args.success Optional. Success callback. Default: wp.updates.deletePluginSuccess - * @param {deletePluginError=} args.error Optional. Error callback. Default: wp.updates.deletePluginError - * @return {$.promise} A jQuery promise that represents the request, - * decorated with an abort() method. - */ - wp.updates.deletePlugin = function( args ) { - var $link = $( '[data-plugin="' + args.plugin + '"]' ).find( '.row-actions a.delete' ); - - args = _.extend( { - success: wp.updates.deletePluginSuccess, - error: wp.updates.deletePluginError - }, args ); - - if ( $link.html() !== wp.updates.l10n.deleting ) { - $link - .data( 'originaltext', $link.html() ) - .text( wp.updates.l10n.deleting ); - } - - wp.a11y.speak( wp.updates.l10n.deleting, 'polite' ); - - $document.trigger( 'wp-plugin-deleting', args ); - - return wp.updates.ajax( 'delete-plugin', args ); - }; - - /** - * Updates the UI appropriately after a successful plugin deletion. - * - * @since 4.6.0 - * - * @param {Object} response Response from the server. - * @param {string} response.slug Slug of the plugin that was deleted. - * @param {string} response.plugin Base name of the plugin that was deleted. - * @param {string} response.pluginName Name of the plugin that was deleted. - */ - wp.updates.deletePluginSuccess = function( response ) { - - // Removes the plugin and updates rows. - $( '[data-plugin="' + response.plugin + '"]' ).css( { backgroundColor: '#faafaa' } ).fadeOut( 350, function() { - var $form = $( '#bulk-action-form' ), - $views = $( '.subsubsub' ), - $pluginRow = $( this ), - columnCount = $form.find( 'thead th:not(.hidden), thead td' ).length, - pluginDeletedRow = wp.template( 'item-deleted-row' ), - /** - * Plugins Base names of plugins in their different states. - * - * @type {Object} - */ - plugins = settings.plugins; - - // Add a success message after deleting a plugin. - if ( ! $pluginRow.hasClass( 'plugin-update-tr' ) ) { - $pluginRow.after( - pluginDeletedRow( { - slug: response.slug, - plugin: response.plugin, - colspan: columnCount, - name: response.pluginName - } ) - ); - } - - $pluginRow.remove(); - - // Remove plugin from update count. - if ( -1 !== _.indexOf( plugins.upgrade, response.plugin ) ) { - plugins.upgrade = _.without( plugins.upgrade, response.plugin ); - wp.updates.decrementCount( 'plugin' ); - } - - // Remove from views. - if ( -1 !== _.indexOf( plugins.inactive, response.plugin ) ) { - plugins.inactive = _.without( plugins.inactive, response.plugin ); - if ( plugins.inactive.length ) { - $views.find( '.inactive .count' ).text( '(' + plugins.inactive.length + ')' ); - } else { - $views.find( '.inactive' ).remove(); - } - } - - if ( -1 !== _.indexOf( plugins.active, response.plugin ) ) { - plugins.active = _.without( plugins.active, response.plugin ); - if ( plugins.active.length ) { - $views.find( '.active .count' ).text( '(' + plugins.active.length + ')' ); - } else { - $views.find( '.active' ).remove(); - } - } - - if ( -1 !== _.indexOf( plugins.recently_activated, response.plugin ) ) { - plugins.recently_activated = _.without( plugins.recently_activated, response.plugin ); - if ( plugins.recently_activated.length ) { - $views.find( '.recently_activated .count' ).text( '(' + plugins.recently_activated.length + ')' ); - } else { - $views.find( '.recently_activated' ).remove(); - } - } - - plugins.all = _.without( plugins.all, response.plugin ); - - if ( plugins.all.length ) { - $views.find( '.all .count' ).text( '(' + plugins.all.length + ')' ); - } else { - $form.find( '.tablenav' ).css( { visibility: 'hidden' } ); - $views.find( '.all' ).remove(); - - if ( ! $form.find( 'tr.no-items' ).length ) { - $form.find( '#the-list' ).append( '<tr class="no-items"><td class="colspanchange" colspan="' + columnCount + '">' + wp.updates.l10n.noPlugins + '</td></tr>' ); - } - } - } ); - - wp.a11y.speak( wp.updates.l10n.pluginDeleted, 'polite' ); - - $document.trigger( 'wp-plugin-delete-success', response ); - }; - - /** - * Updates the UI appropriately after a failed plugin deletion. - * - * @since 4.6.0 - * - * @param {object} response Response from the server. - * @param {string} response.slug Slug of the plugin to be deleted. - * @param {string} response.plugin Base name of the plugin to be deleted - * @param {string=} response.pluginName Optional. Name of the plugin to be deleted. - * @param {string} response.errorCode Error code for the error that occurred. - * @param {string} response.errorMessage The error that occurred. - */ - wp.updates.deletePluginError = function( response ) { - var $plugin, $pluginUpdateRow, - pluginUpdateRow = wp.template( 'item-update-row' ), - noticeContent = wp.updates.adminNotice( { - className: 'update-message notice-error notice-alt', - message: response.errorMessage - } ); - - if ( response.plugin ) { - $plugin = $( 'tr.inactive[data-plugin="' + response.plugin + '"]' ); - $pluginUpdateRow = $plugin.siblings( '[data-plugin="' + response.plugin + '"]' ); - } else { - $plugin = $( 'tr.inactive[data-slug="' + response.slug + '"]' ); - $pluginUpdateRow = $plugin.siblings( '[data-slug="' + response.slug + '"]' ); - } - - if ( ! wp.updates.isValidResponse( response, 'delete' ) ) { - return; - } - - if ( wp.updates.maybeHandleCredentialError( response, 'delete-plugin' ) ) { - return; - } - - // Add a plugin update row if it doesn't exist yet. - if ( ! $pluginUpdateRow.length ) { - $plugin.addClass( 'update' ).after( - pluginUpdateRow( { - slug: response.slug, - plugin: response.plugin || response.slug, - colspan: $( '#bulk-action-form' ).find( 'thead th:not(.hidden), thead td' ).length, - content: noticeContent - } ) - ); - } else { - - // Remove previous error messages, if any. - $pluginUpdateRow.find( '.notice-error' ).remove(); - - $pluginUpdateRow.find( '.plugin-update' ).append( noticeContent ); - } - - $document.trigger( 'wp-plugin-delete-error', response ); - }; - - /** - * Sends an Ajax request to the server to update a theme. - * - * @since 4.6.0 - * - * @param {object} args Arguments. - * @param {string} args.slug Theme stylesheet. - * @param {updateThemeSuccess=} args.success Optional. Success callback. Default: wp.updates.updateThemeSuccess - * @param {updateThemeError=} args.error Optional. Error callback. Default: wp.updates.updateThemeError - * @return {$.promise} A jQuery promise that represents the request, - * decorated with an abort() method. - */ - wp.updates.updateTheme = function( args ) { - var $notice; - - args = _.extend( { - success: wp.updates.updateThemeSuccess, - error: wp.updates.updateThemeError - }, args ); - - if ( 'themes-network' === pagenow ) { - $notice = $( '[data-slug="' + args.slug + '"]' ).find( '.update-message' ).removeClass( 'notice-error' ).addClass( 'updating-message notice-warning' ).find( 'p' ); - - } else if ( 'customize' === pagenow ) { - - // Update the theme details UI. - $notice = $( '[data-slug="' + args.slug + '"].notice' ).removeClass( 'notice-large' ); - - $notice.find( 'h3' ).remove(); - - // Add the top-level UI, and update both. - $notice = $notice.add( $( '#customize-control-installed_theme_' + args.slug ).find( '.update-message' ) ); - $notice = $notice.addClass( 'updating-message' ).find( 'p' ); - - } else { - $notice = $( '#update-theme' ).closest( '.notice' ).removeClass( 'notice-large' ); - - $notice.find( 'h3' ).remove(); - - $notice = $notice.add( $( '[data-slug="' + args.slug + '"]' ).find( '.update-message' ) ); - $notice = $notice.addClass( 'updating-message' ).find( 'p' ); - } - - if ( $notice.html() !== wp.updates.l10n.updating ) { - $notice.data( 'originaltext', $notice.html() ); - } - - wp.a11y.speak( wp.updates.l10n.updatingMsg, 'polite' ); - $notice.text( wp.updates.l10n.updating ); - - $document.trigger( 'wp-theme-updating', args ); - - return wp.updates.ajax( 'update-theme', args ); - }; - - /** - * Updates the UI appropriately after a successful theme update. - * - * @since 4.6.0 - * - * @param {object} response - * @param {string} response.slug Slug of the theme to be updated. - * @param {object} response.theme Updated theme. - * @param {string} response.oldVersion Old version of the theme. - * @param {string} response.newVersion New version of the theme. - */ - wp.updates.updateThemeSuccess = function( response ) { - var isModalOpen = $( 'body.modal-open' ).length, - $theme = $( '[data-slug="' + response.slug + '"]' ), - updatedMessage = { - className: 'updated-message notice-success notice-alt', - message: wp.updates.l10n.themeUpdated - }, - $notice, newText; - - if ( 'customize' === pagenow ) { - $theme = $( '.updating-message' ).siblings( '.theme-name' ); - - if ( $theme.length ) { - - // Update the version number in the row. - newText = $theme.html().replace( response.oldVersion, response.newVersion ); - $theme.html( newText ); - } - - $notice = $( '.theme-info .notice' ).add( wp.customize.control( 'installed_theme_' + response.slug ).container.find( '.theme' ).find( '.update-message' ) ); - } else if ( 'themes-network' === pagenow ) { - $notice = $theme.find( '.update-message' ); - - // Update the version number in the row. - newText = $theme.find( '.theme-version-author-uri' ).html().replace( response.oldVersion, response.newVersion ); - $theme.find( '.theme-version-author-uri' ).html( newText ); - } else { - $notice = $( '.theme-info .notice' ).add( $theme.find( '.update-message' ) ); - - // Focus on Customize button after updating. - if ( isModalOpen ) { - $( '.load-customize:visible' ).focus(); - } else { - $theme.find( '.load-customize' ).focus(); - } - } - - wp.updates.addAdminNotice( _.extend( { selector: $notice }, updatedMessage ) ); - wp.a11y.speak( wp.updates.l10n.updatedMsg, 'polite' ); - - wp.updates.decrementCount( 'theme' ); - - $document.trigger( 'wp-theme-update-success', response ); - - // Show updated message after modal re-rendered. - if ( isModalOpen && 'customize' !== pagenow ) { - $( '.theme-info .theme-author' ).after( wp.updates.adminNotice( updatedMessage ) ); - } - }; - - /** - * Updates the UI appropriately after a failed theme update. - * - * @since 4.6.0 - * - * @param {object} response Response from the server. - * @param {string} response.slug Slug of the theme to be updated. - * @param {string} response.errorCode Error code for the error that occurred. - * @param {string} response.errorMessage The error that occurred. - */ - wp.updates.updateThemeError = function( response ) { - var $theme = $( '[data-slug="' + response.slug + '"]' ), - errorMessage = wp.updates.l10n.updateFailed.replace( '%s', response.errorMessage ), - $notice; - - if ( ! wp.updates.isValidResponse( response, 'update' ) ) { - return; - } - - if ( wp.updates.maybeHandleCredentialError( response, 'update-theme' ) ) { - return; - } - - if ( 'customize' === pagenow ) { - $theme = wp.customize.control( 'installed_theme_' + response.slug ).container.find( '.theme' ); - } - - if ( 'themes-network' === pagenow ) { - $notice = $theme.find( '.update-message ' ); - } else { - $notice = $( '.theme-info .notice' ).add( $theme.find( '.notice' ) ); - - $( 'body.modal-open' ).length ? $( '.load-customize:visible' ).focus() : $theme.find( '.load-customize' ).focus(); - } - - wp.updates.addAdminNotice( { - selector: $notice, - className: 'update-message notice-error notice-alt is-dismissible', - message: errorMessage - } ); - - wp.a11y.speak( errorMessage, 'polite' ); - - $document.trigger( 'wp-theme-update-error', response ); - }; - - /** - * Sends an Ajax request to the server to install a theme. - * - * @since 4.6.0 - * - * @param {object} args - * @param {string} args.slug Theme stylesheet. - * @param {installThemeSuccess=} args.success Optional. Success callback. Default: wp.updates.installThemeSuccess - * @param {installThemeError=} args.error Optional. Error callback. Default: wp.updates.installThemeError - * @return {$.promise} A jQuery promise that represents the request, - * decorated with an abort() method. - */ - wp.updates.installTheme = function( args ) { - var $message = $( '.theme-install[data-slug="' + args.slug + '"]' ); - - args = _.extend( { - success: wp.updates.installThemeSuccess, - error: wp.updates.installThemeError - }, args ); - - $message.addClass( 'updating-message' ); - $message.parents( '.theme' ).addClass( 'focus' ); - if ( $message.html() !== wp.updates.l10n.installing ) { - $message.data( 'originaltext', $message.html() ); - } - - $message - .text( wp.updates.l10n.installing ) - .attr( 'aria-label', wp.updates.l10n.themeInstallingLabel.replace( '%s', $message.data( 'name' ) ) ); - wp.a11y.speak( wp.updates.l10n.installingMsg, 'polite' ); - - // Remove previous error messages, if any. - $( '.install-theme-info, [data-slug="' + args.slug + '"]' ).removeClass( 'theme-install-failed' ).find( '.notice.notice-error' ).remove(); - - $document.trigger( 'wp-theme-installing', args ); - - return wp.updates.ajax( 'install-theme', args ); - }; - - /** - * Updates the UI appropriately after a successful theme install. - * - * @since 4.6.0 - * - * @param {object} response Response from the server. - * @param {string} response.slug Slug of the theme to be installed. - * @param {string} response.customizeUrl URL to the Customizer for the just installed theme. - * @param {string} response.activateUrl URL to activate the just installed theme. - */ - wp.updates.installThemeSuccess = function( response ) { - var $card = $( '.wp-full-overlay-header, [data-slug=' + response.slug + ']' ), - $message; - - $document.trigger( 'wp-theme-install-success', response ); - - $message = $card.find( '.button-primary' ) - .removeClass( 'updating-message' ) - .addClass( 'updated-message disabled' ) - .attr( 'aria-label', wp.updates.l10n.themeInstalledLabel.replace( '%s', response.themeName ) ) - .text( wp.updates.l10n.themeInstalled ); - - wp.a11y.speak( wp.updates.l10n.installedMsg, 'polite' ); - - setTimeout( function() { - - if ( response.activateUrl ) { - - // Transform the 'Install' button into an 'Activate' button. - $message - .attr( 'href', response.activateUrl ) - .removeClass( 'theme-install updated-message disabled' ) - .addClass( 'activate' ) - .attr( 'aria-label', wp.updates.l10n.activateThemeLabel.replace( '%s', response.themeName ) ) - .text( wp.updates.l10n.activateTheme ); - } - - if ( response.customizeUrl ) { - - // Transform the 'Preview' button into a 'Live Preview' button. - $message.siblings( '.preview' ).replaceWith( function () { - return $( '<a>' ) - .attr( 'href', response.customizeUrl ) - .addClass( 'button load-customize' ) - .text( wp.updates.l10n.livePreview ); - } ); - } - }, 1000 ); - }; - - /** - * Updates the UI appropriately after a failed theme install. - * - * @since 4.6.0 - * - * @param {object} response Response from the server. - * @param {string} response.slug Slug of the theme to be installed. - * @param {string} response.errorCode Error code for the error that occurred. - * @param {string} response.errorMessage The error that occurred. - */ - wp.updates.installThemeError = function( response ) { - var $card, $button, - errorMessage = wp.updates.l10n.installFailed.replace( '%s', response.errorMessage ), - $message = wp.updates.adminNotice( { - className: 'update-message notice-error notice-alt', - message: errorMessage - } ); - - if ( ! wp.updates.isValidResponse( response, 'install' ) ) { - return; - } - - if ( wp.updates.maybeHandleCredentialError( response, 'install-theme' ) ) { - return; - } - - if ( 'customize' === pagenow ) { - if ( $document.find( 'body' ).hasClass( 'modal-open' ) ) { - $button = $( '.theme-install[data-slug="' + response.slug + '"]' ); - $card = $( '.theme-overlay .theme-info' ).prepend( $message ); - } else { - $button = $( '.theme-install[data-slug="' + response.slug + '"]' ); - $card = $button.closest( '.theme' ).addClass( 'theme-install-failed' ).append( $message ); - } - wp.customize.notifications.remove( 'theme_installing' ); - } else { - if ( $document.find( 'body' ).hasClass( 'full-overlay-active' ) ) { - $button = $( '.theme-install[data-slug="' + response.slug + '"]' ); - $card = $( '.install-theme-info' ).prepend( $message ); - } else { - $card = $( '[data-slug="' + response.slug + '"]' ).removeClass( 'focus' ).addClass( 'theme-install-failed' ).append( $message ); - $button = $card.find( '.theme-install' ); - } - } - - $button - .removeClass( 'updating-message' ) - .attr( 'aria-label', wp.updates.l10n.themeInstallFailedLabel.replace( '%s', $button.data( 'name' ) ) ) - .text( wp.updates.l10n.installFailedShort ); - - wp.a11y.speak( errorMessage, 'assertive' ); - - $document.trigger( 'wp-theme-install-error', response ); - }; - - /** - * Sends an Ajax request to the server to delete a theme. - * - * @since 4.6.0 - * - * @param {object} args - * @param {string} args.slug Theme stylesheet. - * @param {deleteThemeSuccess=} args.success Optional. Success callback. Default: wp.updates.deleteThemeSuccess - * @param {deleteThemeError=} args.error Optional. Error callback. Default: wp.updates.deleteThemeError - * @return {$.promise} A jQuery promise that represents the request, - * decorated with an abort() method. - */ - wp.updates.deleteTheme = function( args ) { - var $button; - - if ( 'themes' === pagenow ) { - $button = $( '.theme-actions .delete-theme' ); - } else if ( 'themes-network' === pagenow ) { - $button = $( '[data-slug="' + args.slug + '"]' ).find( '.row-actions a.delete' ); - } - - args = _.extend( { - success: wp.updates.deleteThemeSuccess, - error: wp.updates.deleteThemeError - }, args ); - - if ( $button && $button.html() !== wp.updates.l10n.deleting ) { - $button - .data( 'originaltext', $button.html() ) - .text( wp.updates.l10n.deleting ); - } - - wp.a11y.speak( wp.updates.l10n.deleting, 'polite' ); - - // Remove previous error messages, if any. - $( '.theme-info .update-message' ).remove(); - - $document.trigger( 'wp-theme-deleting', args ); - - return wp.updates.ajax( 'delete-theme', args ); - }; - - /** - * Updates the UI appropriately after a successful theme deletion. - * - * @since 4.6.0 - * - * @param {object} response Response from the server. - * @param {string} response.slug Slug of the theme that was deleted. - */ - wp.updates.deleteThemeSuccess = function( response ) { - var $themeRows = $( '[data-slug="' + response.slug + '"]' ); - - if ( 'themes-network' === pagenow ) { - - // Removes the theme and updates rows. - $themeRows.css( { backgroundColor: '#faafaa' } ).fadeOut( 350, function() { - var $views = $( '.subsubsub' ), - $themeRow = $( this ), - totals = settings.themes, - deletedRow = wp.template( 'item-deleted-row' ); - - if ( ! $themeRow.hasClass( 'plugin-update-tr' ) ) { - $themeRow.after( - deletedRow( { - slug: response.slug, - colspan: $( '#bulk-action-form' ).find( 'thead th:not(.hidden), thead td' ).length, - name: $themeRow.find( '.theme-title strong' ).text() - } ) - ); - } - - $themeRow.remove(); - - // Remove theme from update count. - if ( $themeRow.hasClass( 'update' ) ) { - totals.upgrade--; - wp.updates.decrementCount( 'theme' ); - } - - // Remove from views. - if ( $themeRow.hasClass( 'inactive' ) ) { - totals.disabled--; - if ( totals.disabled ) { - $views.find( '.disabled .count' ).text( '(' + totals.disabled + ')' ); - } else { - $views.find( '.disabled' ).remove(); - } - } - - // There is always at least one theme available. - $views.find( '.all .count' ).text( '(' + --totals.all + ')' ); - } ); - } - - wp.a11y.speak( wp.updates.l10n.themeDeleted, 'polite' ); - - $document.trigger( 'wp-theme-delete-success', response ); - }; - - /** - * Updates the UI appropriately after a failed theme deletion. - * - * @since 4.6.0 - * - * @param {object} response Response from the server. - * @param {string} response.slug Slug of the theme to be deleted. - * @param {string} response.errorCode Error code for the error that occurred. - * @param {string} response.errorMessage The error that occurred. - */ - wp.updates.deleteThemeError = function( response ) { - var $themeRow = $( 'tr.inactive[data-slug="' + response.slug + '"]' ), - $button = $( '.theme-actions .delete-theme' ), - updateRow = wp.template( 'item-update-row' ), - $updateRow = $themeRow.siblings( '#' + response.slug + '-update' ), - errorMessage = wp.updates.l10n.deleteFailed.replace( '%s', response.errorMessage ), - $message = wp.updates.adminNotice( { - className: 'update-message notice-error notice-alt', - message: errorMessage - } ); - - if ( wp.updates.maybeHandleCredentialError( response, 'delete-theme' ) ) { - return; - } - - if ( 'themes-network' === pagenow ) { - if ( ! $updateRow.length ) { - $themeRow.addClass( 'update' ).after( - updateRow( { - slug: response.slug, - colspan: $( '#bulk-action-form' ).find( 'thead th:not(.hidden), thead td' ).length, - content: $message - } ) - ); - } else { - // Remove previous error messages, if any. - $updateRow.find( '.notice-error' ).remove(); - $updateRow.find( '.plugin-update' ).append( $message ); - } - } else { - $( '.theme-info .theme-description' ).before( $message ); - } - - $button.html( $button.data( 'originaltext' ) ); - - wp.a11y.speak( errorMessage, 'assertive' ); - - $document.trigger( 'wp-theme-delete-error', response ); - }; - - /** - * Adds the appropriate callback based on the type of action and the current page. - * - * @since 4.6.0 - * @private - * - * @param {object} data AJAX payload. - * @param {string} action The type of request to perform. - * @return {object} The AJAX payload with the appropriate callbacks. - */ - wp.updates._addCallbacks = function( data, action ) { - if ( 'import' === pagenow && 'install-plugin' === action ) { - data.success = wp.updates.installImporterSuccess; - data.error = wp.updates.installImporterError; - } - - return data; - }; - - /** - * Pulls available jobs from the queue and runs them. - * - * @since 4.2.0 - * @since 4.6.0 Can handle multiple job types. - */ - wp.updates.queueChecker = function() { - var job; - - if ( wp.updates.ajaxLocked || ! wp.updates.queue.length ) { - return; - } - - job = wp.updates.queue.shift(); - - // Handle a queue job. - switch ( job.action ) { - case 'install-plugin': - wp.updates.installPlugin( job.data ); - break; - - case 'update-plugin': - wp.updates.updatePlugin( job.data ); - break; - - case 'delete-plugin': - wp.updates.deletePlugin( job.data ); - break; - - case 'install-theme': - wp.updates.installTheme( job.data ); - break; - - case 'update-theme': - wp.updates.updateTheme( job.data ); - break; - - case 'delete-theme': - wp.updates.deleteTheme( job.data ); - break; - - default: - break; - } - }; - - /** - * Requests the users filesystem credentials if they aren't already known. - * - * @since 4.2.0 - * - * @param {Event=} event Optional. Event interface. - */ - wp.updates.requestFilesystemCredentials = function( event ) { - if ( false === wp.updates.filesystemCredentials.available ) { - /* - * After exiting the credentials request modal, - * return the focus to the element triggering the request. - */ - if ( event && ! wp.updates.$elToReturnFocusToFromCredentialsModal ) { - wp.updates.$elToReturnFocusToFromCredentialsModal = $( event.target ); - } - - wp.updates.ajaxLocked = true; - wp.updates.requestForCredentialsModalOpen(); - } - }; - - /** - * Requests the users filesystem credentials if needed and there is no lock. - * - * @since 4.6.0 - * - * @param {Event=} event Optional. Event interface. - */ - wp.updates.maybeRequestFilesystemCredentials = function( event ) { - if ( wp.updates.shouldRequestFilesystemCredentials && ! wp.updates.ajaxLocked ) { - wp.updates.requestFilesystemCredentials( event ); - } - }; - - /** - * Keydown handler for the request for credentials modal. - * - * Closes the modal when the escape key is pressed and - * constrains keyboard navigation to inside the modal. - * - * @since 4.2.0 - * - * @param {Event} event Event interface. - */ - wp.updates.keydown = function( event ) { - if ( 27 === event.keyCode ) { - wp.updates.requestForCredentialsModalCancel(); - } else if ( 9 === event.keyCode ) { - - // #upgrade button must always be the last focus-able element in the dialog. - if ( 'upgrade' === event.target.id && ! event.shiftKey ) { - $( '#hostname' ).focus(); - - event.preventDefault(); - } else if ( 'hostname' === event.target.id && event.shiftKey ) { - $( '#upgrade' ).focus(); - - event.preventDefault(); - } - } - }; - - /** - * Opens the request for credentials modal. - * - * @since 4.2.0 - */ - wp.updates.requestForCredentialsModalOpen = function() { - var $modal = $( '#request-filesystem-credentials-dialog' ); - - $( 'body' ).addClass( 'modal-open' ); - $modal.show(); - $modal.find( 'input:enabled:first' ).focus(); - $modal.on( 'keydown', wp.updates.keydown ); - }; - - /** - * Closes the request for credentials modal. - * - * @since 4.2.0 - */ - wp.updates.requestForCredentialsModalClose = function() { - $( '#request-filesystem-credentials-dialog' ).hide(); - $( 'body' ).removeClass( 'modal-open' ); - - if ( wp.updates.$elToReturnFocusToFromCredentialsModal ) { - wp.updates.$elToReturnFocusToFromCredentialsModal.focus(); - } - }; - - /** - * Takes care of the steps that need to happen when the modal is canceled out. - * - * @since 4.2.0 - * @since 4.6.0 Triggers an event for callbacks to listen to and add their actions. - */ - wp.updates.requestForCredentialsModalCancel = function() { - - // Not ajaxLocked and no queue means we already have cleared things up. - if ( ! wp.updates.ajaxLocked && ! wp.updates.queue.length ) { - return; - } - - _.each( wp.updates.queue, function( job ) { - $document.trigger( 'credential-modal-cancel', job ); - } ); - - // Remove the lock, and clear the queue. - wp.updates.ajaxLocked = false; - wp.updates.queue = []; - - wp.updates.requestForCredentialsModalClose(); - }; - - /** - * Displays an error message in the request for credentials form. - * - * @since 4.2.0 - * - * @param {string} message Error message. - */ - wp.updates.showErrorInCredentialsForm = function( message ) { - var $filesystemForm = $( '#request-filesystem-credentials-form' ); - - // Remove any existing error. - $filesystemForm.find( '.notice' ).remove(); - $filesystemForm.find( '#request-filesystem-credentials-title' ).after( '<div class="notice notice-alt notice-error"><p>' + message + '</p></div>' ); - }; - - /** - * Handles credential errors and runs events that need to happen in that case. - * - * @since 4.2.0 - * - * @param {object} response Ajax response. - * @param {string} action The type of request to perform. - */ - wp.updates.credentialError = function( response, action ) { - - // Restore callbacks. - response = wp.updates._addCallbacks( response, action ); - - wp.updates.queue.unshift( { - action: action, - - /* - * Not cool that we're depending on response for this data. - * This would feel more whole in a view all tied together. - */ - data: response - } ); - - wp.updates.filesystemCredentials.available = false; - wp.updates.showErrorInCredentialsForm( response.errorMessage ); - wp.updates.requestFilesystemCredentials(); - }; - - /** - * Handles credentials errors if it could not connect to the filesystem. - * - * @since 4.6.0 - * - * @param {object} response Response from the server. - * @param {string} response.errorCode Error code for the error that occurred. - * @param {string} response.errorMessage The error that occurred. - * @param {string} action The type of request to perform. - * @returns {boolean} Whether there is an error that needs to be handled or not. - */ - wp.updates.maybeHandleCredentialError = function( response, action ) { - if ( wp.updates.shouldRequestFilesystemCredentials && response.errorCode && 'unable_to_connect_to_filesystem' === response.errorCode ) { - wp.updates.credentialError( response, action ); - return true; - } - - return false; - }; - - /** - * Validates an AJAX response to ensure it's a proper object. - * - * If the response deems to be invalid, an admin notice is being displayed. - * - * @param {(object|string)} response Response from the server. - * @param {function=} response.always Optional. Callback for when the Deferred is resolved or rejected. - * @param {string=} response.statusText Optional. Status message corresponding to the status code. - * @param {string=} response.responseText Optional. Request response as text. - * @param {string} action Type of action the response is referring to. Can be 'delete', - * 'update' or 'install'. - */ - wp.updates.isValidResponse = function( response, action ) { - var error = wp.updates.l10n.unknownError, - errorMessage; - - // Make sure the response is a valid data object and not a Promise object. - if ( _.isObject( response ) && ! _.isFunction( response.always ) ) { - return true; - } - - if ( _.isString( response ) && '-1' === response ) { - error = wp.updates.l10n.nonceError; - } else if ( _.isString( response ) ) { - error = response; - } else if ( 'undefined' !== typeof response.readyState && 0 === response.readyState ) { - error = wp.updates.l10n.connectionError; - } else if ( _.isString( response.responseText ) && '' !== response.responseText ) { - error = response.responseText; - } else if ( _.isString( response.statusText ) ) { - error = response.statusText; - } - - switch ( action ) { - case 'update': - errorMessage = wp.updates.l10n.updateFailed; - break; - - case 'install': - errorMessage = wp.updates.l10n.installFailed; - break; - - case 'delete': - errorMessage = wp.updates.l10n.deleteFailed; - break; - } - - // Messages are escaped, remove HTML tags to make them more readable. - error = error.replace( /<[\/a-z][^<>]*>/gi, '' ); - errorMessage = errorMessage.replace( '%s', error ); - - // Add admin notice. - wp.updates.addAdminNotice( { - id: 'unknown_error', - className: 'notice-error is-dismissible', - message: _.escape( errorMessage ) - } ); - - // Remove the lock, and clear the queue. - wp.updates.ajaxLocked = false; - wp.updates.queue = []; - - // Change buttons of all running updates. - $( '.button.updating-message' ) - .removeClass( 'updating-message' ) - .removeAttr( 'aria-label' ) - .prop( 'disabled', true ) - .text( wp.updates.l10n.updateFailedShort ); - - $( '.updating-message:not(.button):not(.thickbox)' ) - .removeClass( 'updating-message notice-warning' ) - .addClass( 'notice-error' ) - .find( 'p' ) - .removeAttr( 'aria-label' ) - .text( errorMessage ); - - wp.a11y.speak( errorMessage, 'assertive' ); - - return false; - }; - - /** - * Potentially adds an AYS to a user attempting to leave the page. - * - * If an update is on-going and a user attempts to leave the page, - * opens an "Are you sure?" alert. - * - * @since 4.2.0 - */ - wp.updates.beforeunload = function() { - if ( wp.updates.ajaxLocked ) { - return wp.updates.l10n.beforeunload; - } - }; - - $( function() { - var $pluginFilter = $( '#plugin-filter' ), - $bulkActionForm = $( '#bulk-action-form' ), - $filesystemForm = $( '#request-filesystem-credentials-form' ), - $filesystemModal = $( '#request-filesystem-credentials-dialog' ), - $pluginSearch = $( '.plugins-php .wp-filter-search' ), - $pluginInstallSearch = $( '.plugin-install-php .wp-filter-search' ); - - settings = _.extend( settings, window._wpUpdatesItemCounts || {} ); - - if ( settings.totals ) { - wp.updates.refreshCount(); - } - - /* - * Whether a user needs to submit filesystem credentials. - * - * This is based on whether the form was output on the page server-side. - * - * @see {wp_print_request_filesystem_credentials_modal() in PHP} - */ - wp.updates.shouldRequestFilesystemCredentials = $filesystemModal.length > 0; - - /** - * File system credentials form submit noop-er / handler. - * - * @since 4.2.0 - */ - $filesystemModal.on( 'submit', 'form', function( event ) { - event.preventDefault(); - - // Persist the credentials input by the user for the duration of the page load. - wp.updates.filesystemCredentials.ftp.hostname = $( '#hostname' ).val(); - wp.updates.filesystemCredentials.ftp.username = $( '#username' ).val(); - wp.updates.filesystemCredentials.ftp.password = $( '#password' ).val(); - wp.updates.filesystemCredentials.ftp.connectionType = $( 'input[name="connection_type"]:checked' ).val(); - wp.updates.filesystemCredentials.ssh.publicKey = $( '#public_key' ).val(); - wp.updates.filesystemCredentials.ssh.privateKey = $( '#private_key' ).val(); - wp.updates.filesystemCredentials.fsNonce = $( '#_fs_nonce' ).val(); - wp.updates.filesystemCredentials.available = true; - - // Unlock and invoke the queue. - wp.updates.ajaxLocked = false; - wp.updates.queueChecker(); - - wp.updates.requestForCredentialsModalClose(); - } ); - - /** - * Closes the request credentials modal when clicking the 'Cancel' button or outside of the modal. - * - * @since 4.2.0 - */ - $filesystemModal.on( 'click', '[data-js-action="close"], .notification-dialog-background', wp.updates.requestForCredentialsModalCancel ); - - /** - * Hide SSH fields when not selected. - * - * @since 4.2.0 - */ - $filesystemForm.on( 'change', 'input[name="connection_type"]', function() { - $( '#ssh-keys' ).toggleClass( 'hidden', ( 'ssh' !== $( this ).val() ) ); - } ).change(); - - /** - * Handles events after the credential modal was closed. - * - * @since 4.6.0 - * - * @param {Event} event Event interface. - * @param {string} job The install/update.delete request. - */ - $document.on( 'credential-modal-cancel', function( event, job ) { - var $updatingMessage = $( '.updating-message' ), - $message, originalText; - - if ( 'import' === pagenow ) { - $updatingMessage.removeClass( 'updating-message' ); - } else if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) { - if ( 'update-plugin' === job.action ) { - $message = $( 'tr[data-plugin="' + job.data.plugin + '"]' ).find( '.update-message' ); - } else if ( 'delete-plugin' === job.action ) { - $message = $( '[data-plugin="' + job.data.plugin + '"]' ).find( '.row-actions a.delete' ); - } - } else if ( 'themes' === pagenow || 'themes-network' === pagenow ) { - if ( 'update-theme' === job.action ) { - $message = $( '[data-slug="' + job.data.slug + '"]' ).find( '.update-message' ); - } else if ( 'delete-theme' === job.action && 'themes-network' === pagenow ) { - $message = $( '[data-slug="' + job.data.slug + '"]' ).find( '.row-actions a.delete' ); - } else if ( 'delete-theme' === job.action && 'themes' === pagenow ) { - $message = $( '.theme-actions .delete-theme' ); - } - } else { - $message = $updatingMessage; - } - - if ( $message && $message.hasClass( 'updating-message' ) ) { - originalText = $message.data( 'originaltext' ); - - if ( 'undefined' === typeof originalText ) { - originalText = $( '<p>' ).html( $message.find( 'p' ).data( 'originaltext' ) ); - } - - $message - .removeClass( 'updating-message' ) - .html( originalText ); - - if ( 'plugin-install' === pagenow || 'plugin-install-network' === pagenow ) { - if ( 'update-plugin' === job.action ) { - $message.attr( 'aria-label', wp.updates.l10n.pluginUpdateNowLabel.replace( '%s', $message.data( 'name' ) ) ); - } else if ( 'install-plugin' === job.action ) { - $message.attr( 'aria-label', wp.updates.l10n.pluginInstallNowLabel.replace( '%s', $message.data( 'name' ) ) ); - } - } - } - - wp.a11y.speak( wp.updates.l10n.updateCancel, 'polite' ); - } ); - - /** - * Click handler for plugin updates in List Table view. - * - * @since 4.2.0 - * - * @param {Event} event Event interface. - */ - $bulkActionForm.on( 'click', '[data-plugin] .update-link', function( event ) { - var $message = $( event.target ), - $pluginRow = $message.parents( 'tr' ); - - event.preventDefault(); - - if ( $message.hasClass( 'updating-message' ) || $message.hasClass( 'button-disabled' ) ) { - return; - } - - wp.updates.maybeRequestFilesystemCredentials( event ); - - // Return the user to the input box of the plugin's table row after closing the modal. - wp.updates.$elToReturnFocusToFromCredentialsModal = $pluginRow.find( '.check-column input' ); - wp.updates.updatePlugin( { - plugin: $pluginRow.data( 'plugin' ), - slug: $pluginRow.data( 'slug' ) - } ); - } ); - - /** - * Click handler for plugin updates in plugin install view. - * - * @since 4.2.0 - * - * @param {Event} event Event interface. - */ - $pluginFilter.on( 'click', '.update-now', function( event ) { - var $button = $( event.target ); - event.preventDefault(); - - if ( $button.hasClass( 'updating-message' ) || $button.hasClass( 'button-disabled' ) ) { - return; - } - - wp.updates.maybeRequestFilesystemCredentials( event ); - - wp.updates.updatePlugin( { - plugin: $button.data( 'plugin' ), - slug: $button.data( 'slug' ) - } ); - } ); - - /** - * Click handler for plugin installs in plugin install view. - * - * @since 4.6.0 - * - * @param {Event} event Event interface. - */ - $pluginFilter.on( 'click', '.install-now', function( event ) { - var $button = $( event.target ); - event.preventDefault(); - - if ( $button.hasClass( 'updating-message' ) || $button.hasClass( 'button-disabled' ) ) { - return; - } - - if ( wp.updates.shouldRequestFilesystemCredentials && ! wp.updates.ajaxLocked ) { - wp.updates.requestFilesystemCredentials( event ); - - $document.on( 'credential-modal-cancel', function() { - var $message = $( '.install-now.updating-message' ); - - $message - .removeClass( 'updating-message' ) - .text( wp.updates.l10n.installNow ); - - wp.a11y.speak( wp.updates.l10n.updateCancel, 'polite' ); - } ); - } - - wp.updates.installPlugin( { - slug: $button.data( 'slug' ) - } ); - } ); - - /** - * Click handler for importer plugins installs in the Import screen. - * - * @since 4.6.0 - * - * @param {Event} event Event interface. - */ - $document.on( 'click', '.importer-item .install-now', function( event ) { - var $button = $( event.target ), - pluginName = $( this ).data( 'name' ); - - event.preventDefault(); - - if ( $button.hasClass( 'updating-message' ) ) { - return; - } - - if ( wp.updates.shouldRequestFilesystemCredentials && ! wp.updates.ajaxLocked ) { - wp.updates.requestFilesystemCredentials( event ); - - $document.on( 'credential-modal-cancel', function() { - - $button - .removeClass( 'updating-message' ) - .text( wp.updates.l10n.installNow ) - .attr( 'aria-label', wp.updates.l10n.pluginInstallNowLabel.replace( '%s', pluginName ) ); - - wp.a11y.speak( wp.updates.l10n.updateCancel, 'polite' ); - } ); - } - - wp.updates.installPlugin( { - slug: $button.data( 'slug' ), - pagenow: pagenow, - success: wp.updates.installImporterSuccess, - error: wp.updates.installImporterError - } ); - } ); - - /** - * Click handler for plugin deletions. - * - * @since 4.6.0 - * - * @param {Event} event Event interface. - */ - $bulkActionForm.on( 'click', '[data-plugin] a.delete', function( event ) { - var $pluginRow = $( event.target ).parents( 'tr' ); - - event.preventDefault(); - - if ( ! window.confirm( wp.updates.l10n.aysDeleteUninstall.replace( '%s', $pluginRow.find( '.plugin-title strong' ).text() ) ) ) { - return; - } - - wp.updates.maybeRequestFilesystemCredentials( event ); - - wp.updates.deletePlugin( { - plugin: $pluginRow.data( 'plugin' ), - slug: $pluginRow.data( 'slug' ) - } ); - - } ); - - /** - * Click handler for theme updates. - * - * @since 4.6.0 - * - * @param {Event} event Event interface. - */ - $document.on( 'click', '.themes-php.network-admin .update-link', function( event ) { - var $message = $( event.target ), - $themeRow = $message.parents( 'tr' ); - - event.preventDefault(); - - if ( $message.hasClass( 'updating-message' ) || $message.hasClass( 'button-disabled' ) ) { - return; - } - - wp.updates.maybeRequestFilesystemCredentials( event ); - - // Return the user to the input box of the theme's table row after closing the modal. - wp.updates.$elToReturnFocusToFromCredentialsModal = $themeRow.find( '.check-column input' ); - wp.updates.updateTheme( { - slug: $themeRow.data( 'slug' ) - } ); - } ); - - /** - * Click handler for theme deletions. - * - * @since 4.6.0 - * - * @param {Event} event Event interface. - */ - $document.on( 'click', '.themes-php.network-admin a.delete', function( event ) { - var $themeRow = $( event.target ).parents( 'tr' ); - - event.preventDefault(); - - if ( ! window.confirm( wp.updates.l10n.aysDelete.replace( '%s', $themeRow.find( '.theme-title strong' ).text() ) ) ) { - return; - } - - wp.updates.maybeRequestFilesystemCredentials( event ); - - wp.updates.deleteTheme( { - slug: $themeRow.data( 'slug' ) - } ); - } ); - - /** - * Bulk action handler for plugins and themes. - * - * Handles both deletions and updates. - * - * @since 4.6.0 - * - * @param {Event} event Event interface. - */ - $bulkActionForm.on( 'click', '[type="submit"]:not([name="clear-recent-list"])', function( event ) { - var bulkAction = $( event.target ).siblings( 'select' ).val(), - itemsSelected = $bulkActionForm.find( 'input[name="checked[]"]:checked' ), - success = 0, - error = 0, - errorMessages = [], - type, action; - - // Determine which type of item we're dealing with. - switch ( pagenow ) { - case 'plugins': - case 'plugins-network': - type = 'plugin'; - break; - - case 'themes-network': - type = 'theme'; - break; - - default: - return; - } - - // Bail if there were no items selected. - if ( ! itemsSelected.length ) { - event.preventDefault(); - $( 'html, body' ).animate( { scrollTop: 0 } ); - - return wp.updates.addAdminNotice( { - id: 'no-items-selected', - className: 'notice-error is-dismissible', - message: wp.updates.l10n.noItemsSelected - } ); - } - - // Determine the type of request we're dealing with. - switch ( bulkAction ) { - case 'update-selected': - action = bulkAction.replace( 'selected', type ); - break; - - case 'delete-selected': - if ( ! window.confirm( 'plugin' === type ? wp.updates.l10n.aysBulkDelete : wp.updates.l10n.aysBulkDeleteThemes ) ) { - event.preventDefault(); - return; - } - - action = bulkAction.replace( 'selected', type ); - break; - - default: - return; - } - - wp.updates.maybeRequestFilesystemCredentials( event ); - - event.preventDefault(); - - // Un-check the bulk checkboxes. - $bulkActionForm.find( '.manage-column [type="checkbox"]' ).prop( 'checked', false ); - - $document.trigger( 'wp-' + type + '-bulk-' + bulkAction, itemsSelected ); - - // Find all the checkboxes which have been checked. - itemsSelected.each( function( index, element ) { - var $checkbox = $( element ), - $itemRow = $checkbox.parents( 'tr' ); - - // Only add update-able items to the update queue. - if ( 'update-selected' === bulkAction && ( ! $itemRow.hasClass( 'update' ) || $itemRow.find( 'notice-error' ).length ) ) { - - // Un-check the box. - $checkbox.prop( 'checked', false ); - return; - } - - // Add it to the queue. - wp.updates.queue.push( { - action: action, - data: { - plugin: $itemRow.data( 'plugin' ), - slug: $itemRow.data( 'slug' ) - } - } ); - } ); - - // Display bulk notification for updates of any kind. - $document.on( 'wp-plugin-update-success wp-plugin-update-error wp-theme-update-success wp-theme-update-error', function( event, response ) { - var $itemRow = $( '[data-slug="' + response.slug + '"]' ), - $bulkActionNotice, itemName; - - if ( 'wp-' + response.update + '-update-success' === event.type ) { - success++; - } else { - itemName = response.pluginName ? response.pluginName : $itemRow.find( '.column-primary strong' ).text(); - - error++; - errorMessages.push( itemName + ': ' + response.errorMessage ); - } - - $itemRow.find( 'input[name="checked[]"]:checked' ).prop( 'checked', false ); - - wp.updates.adminNotice = wp.template( 'wp-bulk-updates-admin-notice' ); - - wp.updates.addAdminNotice( { - id: 'bulk-action-notice', - className: 'bulk-action-notice', - successes: success, - errors: error, - errorMessages: errorMessages, - type: response.update - } ); - - $bulkActionNotice = $( '#bulk-action-notice' ).on( 'click', 'button', function() { - // $( this ) is the clicked button, no need to get it again. - $( this ) - .toggleClass( 'bulk-action-errors-collapsed' ) - .attr( 'aria-expanded', ! $( this ).hasClass( 'bulk-action-errors-collapsed' ) ); - // Show the errors list. - $bulkActionNotice.find( '.bulk-action-errors' ).toggleClass( 'hidden' ); - } ); - - if ( error > 0 && ! wp.updates.queue.length ) { - $( 'html, body' ).animate( { scrollTop: 0 } ); - } - } ); - - // Reset admin notice template after #bulk-action-notice was added. - $document.on( 'wp-updates-notice-added', function() { - wp.updates.adminNotice = wp.template( 'wp-updates-admin-notice' ); - } ); - - // Check the queue, now that the event handlers have been added. - wp.updates.queueChecker(); - } ); - - if ( $pluginInstallSearch.length ) { - $pluginInstallSearch.attr( 'aria-describedby', 'live-search-desc' ); - } - - /** - * Handles changes to the plugin search box on the new-plugin page, - * searching the repository dynamically. - * - * @since 4.6.0 - */ - $pluginInstallSearch.on( 'keyup input', _.debounce( function( event, eventtype ) { - var $searchTab = $( '.plugin-install-search' ), data, searchLocation; - - data = { - _ajax_nonce: wp.updates.ajaxNonce, - s: event.target.value, - tab: 'search', - type: $( '#typeselector' ).val(), - pagenow: pagenow - }; - searchLocation = location.href.split( '?' )[ 0 ] + '?' + $.param( _.omit( data, [ '_ajax_nonce', 'pagenow' ] ) ); - - // Clear on escape. - if ( 'keyup' === event.type && 27 === event.which ) { - event.target.value = ''; - } - - if ( wp.updates.searchTerm === data.s && 'typechange' !== eventtype ) { - return; - } else { - $pluginFilter.empty(); - wp.updates.searchTerm = data.s; - } - - if ( window.history && window.history.replaceState ) { - window.history.replaceState( null, '', searchLocation ); - } - - if ( ! $searchTab.length ) { - $searchTab = $( '<li class="plugin-install-search" />' ) - .append( $( '<a />', { - 'class': 'current', - 'href': searchLocation, - 'text': wp.updates.l10n.searchResultsLabel - } ) ); - - $( '.wp-filter .filter-links .current' ) - .removeClass( 'current' ) - .parents( '.filter-links' ) - .prepend( $searchTab ); - - $pluginFilter.prev( 'p' ).remove(); - $( '.plugins-popular-tags-wrapper' ).remove(); - } - - if ( 'undefined' !== typeof wp.updates.searchRequest ) { - wp.updates.searchRequest.abort(); - } - $( 'body' ).addClass( 'loading-content' ); - - wp.updates.searchRequest = wp.ajax.post( 'search-install-plugins', data ).done( function( response ) { - $( 'body' ).removeClass( 'loading-content' ); - $pluginFilter.append( response.items ); - delete wp.updates.searchRequest; - - if ( 0 === response.count ) { - wp.a11y.speak( wp.updates.l10n.noPluginsFound ); - } else { - wp.a11y.speak( wp.updates.l10n.pluginsFound.replace( '%d', response.count ) ); - } - } ); - }, 1000 ) ); - - if ( $pluginSearch.length ) { - $pluginSearch.attr( 'aria-describedby', 'live-search-desc' ); - } - - /** - * Handles changes to the plugin search box on the Installed Plugins screen, - * searching the plugin list dynamically. - * - * @since 4.6.0 - */ - $pluginSearch.on( 'keyup input', _.debounce( function( event ) { - var data = { - _ajax_nonce: wp.updates.ajaxNonce, - s: event.target.value, - pagenow: pagenow, - plugin_status: 'all' - }, - queryArgs; - - // Clear on escape. - if ( 'keyup' === event.type && 27 === event.which ) { - event.target.value = ''; - } - - if ( wp.updates.searchTerm === data.s ) { - return; - } else { - wp.updates.searchTerm = data.s; - } - - queryArgs = _.object( _.compact( _.map( location.search.slice( 1 ).split( '&' ), function( item ) { - if ( item ) return item.split( '=' ); - } ) ) ); - - data.plugin_status = queryArgs.plugin_status || 'all'; - - if ( window.history && window.history.replaceState ) { - window.history.replaceState( null, '', location.href.split( '?' )[ 0 ] + '?s=' + data.s + '&plugin_status=' + data.plugin_status ); - } - - if ( 'undefined' !== typeof wp.updates.searchRequest ) { - wp.updates.searchRequest.abort(); - } - - $bulkActionForm.empty(); - $( 'body' ).addClass( 'loading-content' ); - $( '.subsubsub .current' ).removeClass( 'current' ); - - wp.updates.searchRequest = wp.ajax.post( 'search-plugins', data ).done( function( response ) { - - // Can we just ditch this whole subtitle business? - var $subTitle = $( '<span />' ).addClass( 'subtitle' ).html( wp.updates.l10n.searchResults.replace( '%s', _.escape( data.s ) ) ), - $oldSubTitle = $( '.wrap .subtitle' ); - - if ( ! data.s.length ) { - $oldSubTitle.remove(); - $( '.subsubsub .' + data.plugin_status + ' a' ).addClass( 'current' ); - } else if ( $oldSubTitle.length ) { - $oldSubTitle.replaceWith( $subTitle ); - } else { - $( '.wp-header-end' ).before( $subTitle ); - } - - $( 'body' ).removeClass( 'loading-content' ); - $bulkActionForm.append( response.items ); - delete wp.updates.searchRequest; - - if ( 0 === response.count ) { - wp.a11y.speak( wp.updates.l10n.noPluginsFound ); - } else { - wp.a11y.speak( wp.updates.l10n.pluginsFound.replace( '%d', response.count ) ); - } - } ); - }, 500 ) ); - - /** - * Trigger a search event when the search form gets submitted. - * - * @since 4.6.0 - */ - $document.on( 'submit', '.search-plugins', function( event ) { - event.preventDefault(); - - $( 'input.wp-filter-search' ).trigger( 'input' ); - } ); - - /** - * Trigger a search event when the "Try Again" button is clicked. - * - * @since 4.9.0 - */ - $document.on( 'click', '.try-again', function( event ) { - event.preventDefault(); - $pluginInstallSearch.trigger( 'input' ); - } ); - - /** - * Trigger a search event when the search type gets changed. - * - * @since 4.6.0 - */ - $( '#typeselector' ).on( 'change', function() { - var $search = $( 'input[name="s"]' ); - - if ( $search.val().length ) { - $search.trigger( 'input', 'typechange' ); - } - } ); - - /** - * Click handler for updating a plugin from the details modal on `plugin-install.php`. - * - * @since 4.2.0 - * - * @param {Event} event Event interface. - */ - $( '#plugin_update_from_iframe' ).on( 'click', function( event ) { - var target = window.parent === window ? null : window.parent, - update; - - $.support.postMessage = !! window.postMessage; - - if ( false === $.support.postMessage || null === target || -1 !== window.parent.location.pathname.indexOf( 'update-core.php' ) ) { - return; - } - - event.preventDefault(); - - update = { - action: 'update-plugin', - data: { - plugin: $( this ).data( 'plugin' ), - slug: $( this ).data( 'slug' ) - } - }; - - target.postMessage( JSON.stringify( update ), window.location.origin ); - } ); - - /** - * Click handler for installing a plugin from the details modal on `plugin-install.php`. - * - * @since 4.6.0 - * - * @param {Event} event Event interface. - */ - $( '#plugin_install_from_iframe' ).on( 'click', function( event ) { - var target = window.parent === window ? null : window.parent, - install; - - $.support.postMessage = !! window.postMessage; - - if ( false === $.support.postMessage || null === target || -1 !== window.parent.location.pathname.indexOf( 'index.php' ) ) { - return; - } - - event.preventDefault(); - - install = { - action: 'install-plugin', - data: { - slug: $( this ).data( 'slug' ) - } - }; - - target.postMessage( JSON.stringify( install ), window.location.origin ); - } ); - - /** - * Handles postMessage events. - * - * @since 4.2.0 - * @since 4.6.0 Switched `update-plugin` action to use the queue. - * - * @param {Event} event Event interface. - */ - $( window ).on( 'message', function( event ) { - var originalEvent = event.originalEvent, - expectedOrigin = document.location.protocol + '//' + document.location.host, - message; - - if ( originalEvent.origin !== expectedOrigin ) { - return; - } - - try { - message = $.parseJSON( originalEvent.data ); - } catch ( e ) { - return; - } - - if ( ! message || 'undefined' === typeof message.action ) { - return; - } - - switch ( message.action ) { - - // Called from `wp-admin/includes/class-wp-upgrader-skins.php`. - case 'decrementUpdateCount': - /** @property {string} message.upgradeType */ - wp.updates.decrementCount( message.upgradeType ); - break; - - case 'install-plugin': - case 'update-plugin': - /* jscs:disable requireCamelCaseOrUpperCaseIdentifiers */ - window.tb_remove(); - /* jscs:enable */ - - message.data = wp.updates._addCallbacks( message.data, message.action ); - - wp.updates.queue.push( message ); - wp.updates.queueChecker(); - break; - } - } ); - - /** - * Adds a callback to display a warning before leaving the page. - * - * @since 4.2.0 - */ - $( window ).on( 'beforeunload', wp.updates.beforeunload ); - } ); -})( jQuery, window.wp, window._wpUpdatesSettings ); diff --git a/srcs/wordpress/wp-admin/js/updates.min.js b/srcs/wordpress/wp-admin/js/updates.min.js deleted file mode 100644 index b9a7089..0000000 --- a/srcs/wordpress/wp-admin/js/updates.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(o,p,d){var c=o(document);(p=p||{}).updates={},p.updates.ajaxNonce=d.ajax_nonce,p.updates.l10n=d.l10n,p.updates.searchTerm="",p.updates.shouldRequestFilesystemCredentials=!1,p.updates.filesystemCredentials={ftp:{host:"",username:"",password:"",connectionType:""},ssh:{publicKey:"",privateKey:""},fsNonce:"",available:!1},p.updates.ajaxLocked=!1,p.updates.adminNotice=p.template("wp-updates-admin-notice"),p.updates.queue=[],p.updates.$elToReturnFocusToFromCredentialsModal=void 0,p.updates.addAdminNotice=function(e){var t,a=o(e.selector),s=o(".wp-header-end");delete e.selector,t=p.updates.adminNotice(e),a.length||(a=o("#"+e.id)),a.length?a.replaceWith(t):s.length?s.after(t):"customize"===pagenow?o(".customize-themes-notifications").append(t):o(".wrap").find("> h1").after(t),c.trigger("wp-updates-notice-added")},p.updates.ajax=function(e,t){var a={};return p.updates.ajaxLocked?(p.updates.queue.push({action:e,data:t}),o.Deferred()):(p.updates.ajaxLocked=!0,t.success&&(a.success=t.success,delete t.success),t.error&&(a.error=t.error,delete t.error),a.data=_.extend(t,{action:e,_ajax_nonce:p.updates.ajaxNonce,_fs_nonce:p.updates.filesystemCredentials.fsNonce,username:p.updates.filesystemCredentials.ftp.username,password:p.updates.filesystemCredentials.ftp.password,hostname:p.updates.filesystemCredentials.ftp.hostname,connection_type:p.updates.filesystemCredentials.ftp.connectionType,public_key:p.updates.filesystemCredentials.ssh.publicKey,private_key:p.updates.filesystemCredentials.ssh.privateKey}),p.ajax.send(a).always(p.updates.ajaxAlways))},p.updates.ajaxAlways=function(e){e.errorCode&&"unable_to_connect_to_filesystem"===e.errorCode||(p.updates.ajaxLocked=!1,p.updates.queueChecker()),void 0!==e.debug&&window.console&&window.console.log&&_.map(e.debug,function(e){window.console.log(p.sanitize.stripTagsAndEncodeText(e))})},p.updates.refreshCount=function(){var e,t=o("#wp-admin-bar-updates"),a=o('a[href="update-core.php"] .update-plugins'),s=o('a[href="plugins.php"] .update-plugins'),n=o('a[href="themes.php"] .update-plugins');t.find(".ab-item").removeAttr("title"),t.find(".ab-label").text(d.totals.counts.total),0===d.totals.counts.total&&t.find(".ab-label").parents("li").remove(),a.each(function(e,t){t.className=t.className.replace(/count-\d+/,"count-"+d.totals.counts.total)}),0<d.totals.counts.total?a.find(".update-count").text(d.totals.counts.total):a.remove(),s.each(function(e,t){t.className=t.className.replace(/count-\d+/,"count-"+d.totals.counts.plugins)}),0<d.totals.counts.total?s.find(".plugin-count").text(d.totals.counts.plugins):s.remove(),n.each(function(e,t){t.className=t.className.replace(/count-\d+/,"count-"+d.totals.counts.themes)}),0<d.totals.counts.total?n.find(".theme-count").text(d.totals.counts.themes):n.remove(),"plugins"===pagenow||"plugins-network"===pagenow?e=d.totals.counts.plugins:"themes"!==pagenow&&"themes-network"!==pagenow||(e=d.totals.counts.themes),0<e?o(".subsubsub .upgrade .count").text("("+e+")"):(o(".subsubsub .upgrade").remove(),o(".subsubsub li:last").html(function(){return o(this).children()}))},p.updates.decrementCount=function(e){d.totals.counts.total=Math.max(--d.totals.counts.total,0),"plugin"===e?d.totals.counts.plugins=Math.max(--d.totals.counts.plugins,0):"theme"===e&&(d.totals.counts.themes=Math.max(--d.totals.counts.themes,0)),p.updates.refreshCount(e)},p.updates.updatePlugin=function(e){var t,a,s,n;return e=_.extend({success:p.updates.updatePluginSuccess,error:p.updates.updatePluginError},e),"plugins"===pagenow||"plugins-network"===pagenow?(s=(t=o('tr[data-plugin="'+e.plugin+'"]')).find(".update-message").removeClass("notice-error").addClass("updating-message notice-warning").find("p"),n=p.updates.l10n.pluginUpdatingLabel.replace("%s",t.find(".plugin-title strong").text())):"plugin-install"!==pagenow&&"plugin-install-network"!==pagenow||(s=(a=o(".plugin-card-"+e.slug)).find(".update-now").addClass("updating-message"),n=p.updates.l10n.pluginUpdatingLabel.replace("%s",s.data("name")),a.removeClass("plugin-card-update-failed").find(".notice.notice-error").remove()),s.html()!==p.updates.l10n.updating&&s.data("originaltext",s.html()),s.attr("aria-label",n).text(p.updates.l10n.updating),c.trigger("wp-plugin-updating",e),p.updates.ajax("update-plugin",e)},p.updates.updatePluginSuccess=function(e){var t,a,s;"plugins"===pagenow||"plugins-network"===pagenow?(a=(t=o('tr[data-plugin="'+e.plugin+'"]').removeClass("update").addClass("updated")).find(".update-message").removeClass("updating-message notice-warning").addClass("updated-message notice-success").find("p"),s=t.find(".plugin-version-author-uri").html().replace(e.oldVersion,e.newVersion),t.find(".plugin-version-author-uri").html(s)):"plugin-install"!==pagenow&&"plugin-install-network"!==pagenow||(a=o(".plugin-card-"+e.slug).find(".update-now").removeClass("updating-message").addClass("button-disabled updated-message")),a.attr("aria-label",p.updates.l10n.pluginUpdatedLabel.replace("%s",e.pluginName)).text(p.updates.l10n.pluginUpdated),p.a11y.speak(p.updates.l10n.updatedMsg,"polite"),p.updates.decrementCount("plugin"),c.trigger("wp-plugin-update-success",e)},p.updates.updatePluginError=function(e){var t,a,s;p.updates.isValidResponse(e,"update")&&(p.updates.maybeHandleCredentialError(e,"update-plugin")||(s=p.updates.l10n.updateFailed.replace("%s",e.errorMessage),"plugins"===pagenow||"plugins-network"===pagenow?((a=e.plugin?o('tr[data-plugin="'+e.plugin+'"]').find(".update-message"):o('tr[data-slug="'+e.slug+'"]').find(".update-message")).removeClass("updating-message notice-warning").addClass("notice-error").find("p").html(s),e.pluginName?a.find("p").attr("aria-label",p.updates.l10n.pluginUpdateFailedLabel.replace("%s",e.pluginName)):a.find("p").removeAttr("aria-label")):"plugin-install"!==pagenow&&"plugin-install-network"!==pagenow||((t=o(".plugin-card-"+e.slug).addClass("plugin-card-update-failed").append(p.updates.adminNotice({className:"update-message notice-error notice-alt is-dismissible",message:s}))).find(".update-now").text(p.updates.l10n.updateFailedShort).removeClass("updating-message"),e.pluginName?t.find(".update-now").attr("aria-label",p.updates.l10n.pluginUpdateFailedLabel.replace("%s",e.pluginName)):t.find(".update-now").removeAttr("aria-label"),t.on("click",".notice.is-dismissible .notice-dismiss",function(){setTimeout(function(){t.removeClass("plugin-card-update-failed").find(".column-name a").focus(),t.find(".update-now").attr("aria-label",!1).text(p.updates.l10n.updateNow)},200)})),p.a11y.speak(s,"assertive"),c.trigger("wp-plugin-update-error",e)))},p.updates.installPlugin=function(e){var t=o(".plugin-card-"+e.slug),a=t.find(".install-now");return e=_.extend({success:p.updates.installPluginSuccess,error:p.updates.installPluginError},e),"import"===pagenow&&(a=o('[data-slug="'+e.slug+'"]')),a.html()!==p.updates.l10n.installing&&a.data("originaltext",a.html()),a.addClass("updating-message").attr("aria-label",p.updates.l10n.pluginInstallingLabel.replace("%s",a.data("name"))).text(p.updates.l10n.installing),p.a11y.speak(p.updates.l10n.installingMsg,"polite"),t.removeClass("plugin-card-install-failed").find(".notice.notice-error").remove(),c.trigger("wp-plugin-installing",e),p.updates.ajax("install-plugin",e)},p.updates.installPluginSuccess=function(e){var t=o(".plugin-card-"+e.slug).find(".install-now");t.removeClass("updating-message").addClass("updated-message installed button-disabled").attr("aria-label",p.updates.l10n.pluginInstalledLabel.replace("%s",e.pluginName)).text(p.updates.l10n.pluginInstalled),p.a11y.speak(p.updates.l10n.installedMsg,"polite"),c.trigger("wp-plugin-install-success",e),e.activateUrl&&setTimeout(function(){t.removeClass("install-now installed button-disabled updated-message").addClass("activate-now button-primary").attr("href",e.activateUrl).attr("aria-label",p.updates.l10n.activatePluginLabel.replace("%s",e.pluginName)).text(p.updates.l10n.activatePlugin)},1e3)},p.updates.installPluginError=function(e){var t,a=o(".plugin-card-"+e.slug),s=a.find(".install-now");p.updates.isValidResponse(e,"install")&&(p.updates.maybeHandleCredentialError(e,"install-plugin")||(t=p.updates.l10n.installFailed.replace("%s",e.errorMessage),a.addClass("plugin-card-update-failed").append('<div class="notice notice-error notice-alt is-dismissible"><p>'+t+"</p></div>"),a.on("click",".notice.is-dismissible .notice-dismiss",function(){setTimeout(function(){a.removeClass("plugin-card-update-failed").find(".column-name a").focus()},200)}),s.removeClass("updating-message").addClass("button-disabled").attr("aria-label",p.updates.l10n.pluginInstallFailedLabel.replace("%s",s.data("name"))).text(p.updates.l10n.installFailedShort),p.a11y.speak(t,"assertive"),c.trigger("wp-plugin-install-error",e)))},p.updates.installImporterSuccess=function(e){p.updates.addAdminNotice({id:"install-success",className:"notice-success is-dismissible",message:p.updates.l10n.importerInstalledMsg.replace("%s",e.activateUrl+"&from=import")}),o('[data-slug="'+e.slug+'"]').removeClass("install-now updating-message").addClass("activate-now").attr({href:e.activateUrl+"&from=import","aria-label":p.updates.l10n.activateImporterLabel.replace("%s",e.pluginName)}).text(p.updates.l10n.activateImporter),p.a11y.speak(p.updates.l10n.installedMsg,"polite"),c.trigger("wp-importer-install-success",e)},p.updates.installImporterError=function(e){var t=p.updates.l10n.installFailed.replace("%s",e.errorMessage),a=o('[data-slug="'+e.slug+'"]'),s=a.data("name");p.updates.isValidResponse(e,"install")&&(p.updates.maybeHandleCredentialError(e,"install-plugin")||(p.updates.addAdminNotice({id:e.errorCode,className:"notice-error is-dismissible",message:t}),a.removeClass("updating-message").text(p.updates.l10n.installNow).attr("aria-label",p.updates.l10n.pluginInstallNowLabel.replace("%s",s)),p.a11y.speak(t,"assertive"),c.trigger("wp-importer-install-error",e)))},p.updates.deletePlugin=function(e){var t=o('[data-plugin="'+e.plugin+'"]').find(".row-actions a.delete");return e=_.extend({success:p.updates.deletePluginSuccess,error:p.updates.deletePluginError},e),t.html()!==p.updates.l10n.deleting&&t.data("originaltext",t.html()).text(p.updates.l10n.deleting),p.a11y.speak(p.updates.l10n.deleting,"polite"),c.trigger("wp-plugin-deleting",e),p.updates.ajax("delete-plugin",e)},p.updates.deletePluginSuccess=function(i){o('[data-plugin="'+i.plugin+'"]').css({backgroundColor:"#faafaa"}).fadeOut(350,function(){var e=o("#bulk-action-form"),t=o(".subsubsub"),a=o(this),s=e.find("thead th:not(.hidden), thead td").length,n=p.template("item-deleted-row"),l=d.plugins;a.hasClass("plugin-update-tr")||a.after(n({slug:i.slug,plugin:i.plugin,colspan:s,name:i.pluginName})),a.remove(),-1!==_.indexOf(l.upgrade,i.plugin)&&(l.upgrade=_.without(l.upgrade,i.plugin),p.updates.decrementCount("plugin")),-1!==_.indexOf(l.inactive,i.plugin)&&(l.inactive=_.without(l.inactive,i.plugin),l.inactive.length?t.find(".inactive .count").text("("+l.inactive.length+")"):t.find(".inactive").remove()),-1!==_.indexOf(l.active,i.plugin)&&(l.active=_.without(l.active,i.plugin),l.active.length?t.find(".active .count").text("("+l.active.length+")"):t.find(".active").remove()),-1!==_.indexOf(l.recently_activated,i.plugin)&&(l.recently_activated=_.without(l.recently_activated,i.plugin),l.recently_activated.length?t.find(".recently_activated .count").text("("+l.recently_activated.length+")"):t.find(".recently_activated").remove()),l.all=_.without(l.all,i.plugin),l.all.length?t.find(".all .count").text("("+l.all.length+")"):(e.find(".tablenav").css({visibility:"hidden"}),t.find(".all").remove(),e.find("tr.no-items").length||e.find("#the-list").append('<tr class="no-items"><td class="colspanchange" colspan="'+s+'">'+p.updates.l10n.noPlugins+"</td></tr>"))}),p.a11y.speak(p.updates.l10n.pluginDeleted,"polite"),c.trigger("wp-plugin-delete-success",i)},p.updates.deletePluginError=function(e){var t,a,s=p.template("item-update-row"),n=p.updates.adminNotice({className:"update-message notice-error notice-alt",message:e.errorMessage});a=e.plugin?(t=o('tr.inactive[data-plugin="'+e.plugin+'"]')).siblings('[data-plugin="'+e.plugin+'"]'):(t=o('tr.inactive[data-slug="'+e.slug+'"]')).siblings('[data-slug="'+e.slug+'"]'),p.updates.isValidResponse(e,"delete")&&(p.updates.maybeHandleCredentialError(e,"delete-plugin")||(a.length?(a.find(".notice-error").remove(),a.find(".plugin-update").append(n)):t.addClass("update").after(s({slug:e.slug,plugin:e.plugin||e.slug,colspan:o("#bulk-action-form").find("thead th:not(.hidden), thead td").length,content:n})),c.trigger("wp-plugin-delete-error",e)))},p.updates.updateTheme=function(e){var t;return e=_.extend({success:p.updates.updateThemeSuccess,error:p.updates.updateThemeError},e),(t="themes-network"===pagenow?o('[data-slug="'+e.slug+'"]').find(".update-message").removeClass("notice-error").addClass("updating-message notice-warning").find("p"):"customize"===pagenow?((t=o('[data-slug="'+e.slug+'"].notice').removeClass("notice-large")).find("h3").remove(),(t=t.add(o("#customize-control-installed_theme_"+e.slug).find(".update-message"))).addClass("updating-message").find("p")):((t=o("#update-theme").closest(".notice").removeClass("notice-large")).find("h3").remove(),(t=t.add(o('[data-slug="'+e.slug+'"]').find(".update-message"))).addClass("updating-message").find("p"))).html()!==p.updates.l10n.updating&&t.data("originaltext",t.html()),p.a11y.speak(p.updates.l10n.updatingMsg,"polite"),t.text(p.updates.l10n.updating),c.trigger("wp-theme-updating",e),p.updates.ajax("update-theme",e)},p.updates.updateThemeSuccess=function(e){var t,a,s=o("body.modal-open").length,n=o('[data-slug="'+e.slug+'"]'),l={className:"updated-message notice-success notice-alt",message:p.updates.l10n.themeUpdated};"customize"===pagenow?((n=o(".updating-message").siblings(".theme-name")).length&&(a=n.html().replace(e.oldVersion,e.newVersion),n.html(a)),t=o(".theme-info .notice").add(p.customize.control("installed_theme_"+e.slug).container.find(".theme").find(".update-message"))):"themes-network"===pagenow?(t=n.find(".update-message"),a=n.find(".theme-version-author-uri").html().replace(e.oldVersion,e.newVersion),n.find(".theme-version-author-uri").html(a)):(t=o(".theme-info .notice").add(n.find(".update-message")),s?o(".load-customize:visible").focus():n.find(".load-customize").focus()),p.updates.addAdminNotice(_.extend({selector:t},l)),p.a11y.speak(p.updates.l10n.updatedMsg,"polite"),p.updates.decrementCount("theme"),c.trigger("wp-theme-update-success",e),s&&"customize"!==pagenow&&o(".theme-info .theme-author").after(p.updates.adminNotice(l))},p.updates.updateThemeError=function(e){var t,a=o('[data-slug="'+e.slug+'"]'),s=p.updates.l10n.updateFailed.replace("%s",e.errorMessage);p.updates.isValidResponse(e,"update")&&(p.updates.maybeHandleCredentialError(e,"update-theme")||("customize"===pagenow&&(a=p.customize.control("installed_theme_"+e.slug).container.find(".theme")),"themes-network"===pagenow?t=a.find(".update-message "):(t=o(".theme-info .notice").add(a.find(".notice")),o("body.modal-open").length?o(".load-customize:visible").focus():a.find(".load-customize").focus()),p.updates.addAdminNotice({selector:t,className:"update-message notice-error notice-alt is-dismissible",message:s}),p.a11y.speak(s,"polite"),c.trigger("wp-theme-update-error",e)))},p.updates.installTheme=function(e){var t=o('.theme-install[data-slug="'+e.slug+'"]');return e=_.extend({success:p.updates.installThemeSuccess,error:p.updates.installThemeError},e),t.addClass("updating-message"),t.parents(".theme").addClass("focus"),t.html()!==p.updates.l10n.installing&&t.data("originaltext",t.html()),t.text(p.updates.l10n.installing).attr("aria-label",p.updates.l10n.themeInstallingLabel.replace("%s",t.data("name"))),p.a11y.speak(p.updates.l10n.installingMsg,"polite"),o('.install-theme-info, [data-slug="'+e.slug+'"]').removeClass("theme-install-failed").find(".notice.notice-error").remove(),c.trigger("wp-theme-installing",e),p.updates.ajax("install-theme",e)},p.updates.installThemeSuccess=function(e){var t,a=o(".wp-full-overlay-header, [data-slug="+e.slug+"]");c.trigger("wp-theme-install-success",e),t=a.find(".button-primary").removeClass("updating-message").addClass("updated-message disabled").attr("aria-label",p.updates.l10n.themeInstalledLabel.replace("%s",e.themeName)).text(p.updates.l10n.themeInstalled),p.a11y.speak(p.updates.l10n.installedMsg,"polite"),setTimeout(function(){e.activateUrl&&t.attr("href",e.activateUrl).removeClass("theme-install updated-message disabled").addClass("activate").attr("aria-label",p.updates.l10n.activateThemeLabel.replace("%s",e.themeName)).text(p.updates.l10n.activateTheme),e.customizeUrl&&t.siblings(".preview").replaceWith(function(){return o("<a>").attr("href",e.customizeUrl).addClass("button load-customize").text(p.updates.l10n.livePreview)})},1e3)},p.updates.installThemeError=function(e){var t,a=p.updates.l10n.installFailed.replace("%s",e.errorMessage),s=p.updates.adminNotice({className:"update-message notice-error notice-alt",message:a});p.updates.isValidResponse(e,"install")&&(p.updates.maybeHandleCredentialError(e,"install-theme")||("customize"===pagenow?(c.find("body").hasClass("modal-open")?(t=o('.theme-install[data-slug="'+e.slug+'"]'),o(".theme-overlay .theme-info").prepend(s)):(t=o('.theme-install[data-slug="'+e.slug+'"]')).closest(".theme").addClass("theme-install-failed").append(s),p.customize.notifications.remove("theme_installing")):c.find("body").hasClass("full-overlay-active")?(t=o('.theme-install[data-slug="'+e.slug+'"]'),o(".install-theme-info").prepend(s)):t=o('[data-slug="'+e.slug+'"]').removeClass("focus").addClass("theme-install-failed").append(s).find(".theme-install"),t.removeClass("updating-message").attr("aria-label",p.updates.l10n.themeInstallFailedLabel.replace("%s",t.data("name"))).text(p.updates.l10n.installFailedShort),p.a11y.speak(a,"assertive"),c.trigger("wp-theme-install-error",e)))},p.updates.deleteTheme=function(e){var t;return"themes"===pagenow?t=o(".theme-actions .delete-theme"):"themes-network"===pagenow&&(t=o('[data-slug="'+e.slug+'"]').find(".row-actions a.delete")),e=_.extend({success:p.updates.deleteThemeSuccess,error:p.updates.deleteThemeError},e),t&&t.html()!==p.updates.l10n.deleting&&t.data("originaltext",t.html()).text(p.updates.l10n.deleting),p.a11y.speak(p.updates.l10n.deleting,"polite"),o(".theme-info .update-message").remove(),c.trigger("wp-theme-deleting",e),p.updates.ajax("delete-theme",e)},p.updates.deleteThemeSuccess=function(n){var e=o('[data-slug="'+n.slug+'"]');"themes-network"===pagenow&&e.css({backgroundColor:"#faafaa"}).fadeOut(350,function(){var e=o(".subsubsub"),t=o(this),a=d.themes,s=p.template("item-deleted-row");t.hasClass("plugin-update-tr")||t.after(s({slug:n.slug,colspan:o("#bulk-action-form").find("thead th:not(.hidden), thead td").length,name:t.find(".theme-title strong").text()})),t.remove(),t.hasClass("update")&&(a.upgrade--,p.updates.decrementCount("theme")),t.hasClass("inactive")&&(a.disabled--,a.disabled?e.find(".disabled .count").text("("+a.disabled+")"):e.find(".disabled").remove()),e.find(".all .count").text("("+--a.all+")")}),p.a11y.speak(p.updates.l10n.themeDeleted,"polite"),c.trigger("wp-theme-delete-success",n)},p.updates.deleteThemeError=function(e){var t=o('tr.inactive[data-slug="'+e.slug+'"]'),a=o(".theme-actions .delete-theme"),s=p.template("item-update-row"),n=t.siblings("#"+e.slug+"-update"),l=p.updates.l10n.deleteFailed.replace("%s",e.errorMessage),i=p.updates.adminNotice({className:"update-message notice-error notice-alt",message:l});p.updates.maybeHandleCredentialError(e,"delete-theme")||("themes-network"===pagenow?n.length?(n.find(".notice-error").remove(),n.find(".plugin-update").append(i)):t.addClass("update").after(s({slug:e.slug,colspan:o("#bulk-action-form").find("thead th:not(.hidden), thead td").length,content:i})):o(".theme-info .theme-description").before(i),a.html(a.data("originaltext")),p.a11y.speak(l,"assertive"),c.trigger("wp-theme-delete-error",e))},p.updates._addCallbacks=function(e,t){return"import"===pagenow&&"install-plugin"===t&&(e.success=p.updates.installImporterSuccess,e.error=p.updates.installImporterError),e},p.updates.queueChecker=function(){var e;if(!p.updates.ajaxLocked&&p.updates.queue.length)switch((e=p.updates.queue.shift()).action){case"install-plugin":p.updates.installPlugin(e.data);break;case"update-plugin":p.updates.updatePlugin(e.data);break;case"delete-plugin":p.updates.deletePlugin(e.data);break;case"install-theme":p.updates.installTheme(e.data);break;case"update-theme":p.updates.updateTheme(e.data);break;case"delete-theme":p.updates.deleteTheme(e.data)}},p.updates.requestFilesystemCredentials=function(e){!1===p.updates.filesystemCredentials.available&&(e&&!p.updates.$elToReturnFocusToFromCredentialsModal&&(p.updates.$elToReturnFocusToFromCredentialsModal=o(e.target)),p.updates.ajaxLocked=!0,p.updates.requestForCredentialsModalOpen())},p.updates.maybeRequestFilesystemCredentials=function(e){p.updates.shouldRequestFilesystemCredentials&&!p.updates.ajaxLocked&&p.updates.requestFilesystemCredentials(e)},p.updates.keydown=function(e){27===e.keyCode?p.updates.requestForCredentialsModalCancel():9===e.keyCode&&("upgrade"!==e.target.id||e.shiftKey?"hostname"===e.target.id&&e.shiftKey&&(o("#upgrade").focus(),e.preventDefault()):(o("#hostname").focus(),e.preventDefault()))},p.updates.requestForCredentialsModalOpen=function(){var e=o("#request-filesystem-credentials-dialog");o("body").addClass("modal-open"),e.show(),e.find("input:enabled:first").focus(),e.on("keydown",p.updates.keydown)},p.updates.requestForCredentialsModalClose=function(){o("#request-filesystem-credentials-dialog").hide(),o("body").removeClass("modal-open"),p.updates.$elToReturnFocusToFromCredentialsModal&&p.updates.$elToReturnFocusToFromCredentialsModal.focus()},p.updates.requestForCredentialsModalCancel=function(){(p.updates.ajaxLocked||p.updates.queue.length)&&(_.each(p.updates.queue,function(e){c.trigger("credential-modal-cancel",e)}),p.updates.ajaxLocked=!1,p.updates.queue=[],p.updates.requestForCredentialsModalClose())},p.updates.showErrorInCredentialsForm=function(e){var t=o("#request-filesystem-credentials-form");t.find(".notice").remove(),t.find("#request-filesystem-credentials-title").after('<div class="notice notice-alt notice-error"><p>'+e+"</p></div>")},p.updates.credentialError=function(e,t){e=p.updates._addCallbacks(e,t),p.updates.queue.unshift({action:t,data:e}),p.updates.filesystemCredentials.available=!1,p.updates.showErrorInCredentialsForm(e.errorMessage),p.updates.requestFilesystemCredentials()},p.updates.maybeHandleCredentialError=function(e,t){return!(!p.updates.shouldRequestFilesystemCredentials||!e.errorCode||"unable_to_connect_to_filesystem"!==e.errorCode)&&(p.updates.credentialError(e,t),!0)},p.updates.isValidResponse=function(e,t){var a,s=p.updates.l10n.unknownError;if(_.isObject(e)&&!_.isFunction(e.always))return!0;switch(_.isString(e)&&"-1"===e?s=p.updates.l10n.nonceError:_.isString(e)?s=e:void 0!==e.readyState&&0===e.readyState?s=p.updates.l10n.connectionError:_.isString(e.responseText)&&""!==e.responseText?s=e.responseText:_.isString(e.statusText)&&(s=e.statusText),t){case"update":a=p.updates.l10n.updateFailed;break;case"install":a=p.updates.l10n.installFailed;break;case"delete":a=p.updates.l10n.deleteFailed}return s=s.replace(/<[\/a-z][^<>]*>/gi,""),a=a.replace("%s",s),p.updates.addAdminNotice({id:"unknown_error",className:"notice-error is-dismissible",message:_.escape(a)}),p.updates.ajaxLocked=!1,p.updates.queue=[],o(".button.updating-message").removeClass("updating-message").removeAttr("aria-label").prop("disabled",!0).text(p.updates.l10n.updateFailedShort),o(".updating-message:not(.button):not(.thickbox)").removeClass("updating-message notice-warning").addClass("notice-error").find("p").removeAttr("aria-label").text(a),p.a11y.speak(a,"assertive"),!1},p.updates.beforeunload=function(){if(p.updates.ajaxLocked)return p.updates.l10n.beforeunload},o(function(){var l=o("#plugin-filter"),r=o("#bulk-action-form"),e=o("#request-filesystem-credentials-form"),t=o("#request-filesystem-credentials-dialog"),a=o(".plugins-php .wp-filter-search"),s=o(".plugin-install-php .wp-filter-search");(d=_.extend(d,window._wpUpdatesItemCounts||{})).totals&&p.updates.refreshCount(),p.updates.shouldRequestFilesystemCredentials=0<t.length,t.on("submit","form",function(e){e.preventDefault(),p.updates.filesystemCredentials.ftp.hostname=o("#hostname").val(),p.updates.filesystemCredentials.ftp.username=o("#username").val(),p.updates.filesystemCredentials.ftp.password=o("#password").val(),p.updates.filesystemCredentials.ftp.connectionType=o('input[name="connection_type"]:checked').val(),p.updates.filesystemCredentials.ssh.publicKey=o("#public_key").val(),p.updates.filesystemCredentials.ssh.privateKey=o("#private_key").val(),p.updates.filesystemCredentials.fsNonce=o("#_fs_nonce").val(),p.updates.filesystemCredentials.available=!0,p.updates.ajaxLocked=!1,p.updates.queueChecker(),p.updates.requestForCredentialsModalClose()}),t.on("click",'[data-js-action="close"], .notification-dialog-background',p.updates.requestForCredentialsModalCancel),e.on("change",'input[name="connection_type"]',function(){o("#ssh-keys").toggleClass("hidden","ssh"!==o(this).val())}).change(),c.on("credential-modal-cancel",function(e,t){var a,s,n=o(".updating-message");"import"===pagenow?n.removeClass("updating-message"):"plugins"===pagenow||"plugins-network"===pagenow?"update-plugin"===t.action?a=o('tr[data-plugin="'+t.data.plugin+'"]').find(".update-message"):"delete-plugin"===t.action&&(a=o('[data-plugin="'+t.data.plugin+'"]').find(".row-actions a.delete")):"themes"===pagenow||"themes-network"===pagenow?"update-theme"===t.action?a=o('[data-slug="'+t.data.slug+'"]').find(".update-message"):"delete-theme"===t.action&&"themes-network"===pagenow?a=o('[data-slug="'+t.data.slug+'"]').find(".row-actions a.delete"):"delete-theme"===t.action&&"themes"===pagenow&&(a=o(".theme-actions .delete-theme")):a=n,a&&a.hasClass("updating-message")&&(void 0===(s=a.data("originaltext"))&&(s=o("<p>").html(a.find("p").data("originaltext"))),a.removeClass("updating-message").html(s),"plugin-install"!==pagenow&&"plugin-install-network"!==pagenow||("update-plugin"===t.action?a.attr("aria-label",p.updates.l10n.pluginUpdateNowLabel.replace("%s",a.data("name"))):"install-plugin"===t.action&&a.attr("aria-label",p.updates.l10n.pluginInstallNowLabel.replace("%s",a.data("name"))))),p.a11y.speak(p.updates.l10n.updateCancel,"polite")}),r.on("click","[data-plugin] .update-link",function(e){var t=o(e.target),a=t.parents("tr");e.preventDefault(),t.hasClass("updating-message")||t.hasClass("button-disabled")||(p.updates.maybeRequestFilesystemCredentials(e),p.updates.$elToReturnFocusToFromCredentialsModal=a.find(".check-column input"),p.updates.updatePlugin({plugin:a.data("plugin"),slug:a.data("slug")}))}),l.on("click",".update-now",function(e){var t=o(e.target);e.preventDefault(),t.hasClass("updating-message")||t.hasClass("button-disabled")||(p.updates.maybeRequestFilesystemCredentials(e),p.updates.updatePlugin({plugin:t.data("plugin"),slug:t.data("slug")}))}),l.on("click",".install-now",function(e){var t=o(e.target);e.preventDefault(),t.hasClass("updating-message")||t.hasClass("button-disabled")||(p.updates.shouldRequestFilesystemCredentials&&!p.updates.ajaxLocked&&(p.updates.requestFilesystemCredentials(e),c.on("credential-modal-cancel",function(){o(".install-now.updating-message").removeClass("updating-message").text(p.updates.l10n.installNow),p.a11y.speak(p.updates.l10n.updateCancel,"polite")})),p.updates.installPlugin({slug:t.data("slug")}))}),c.on("click",".importer-item .install-now",function(e){var t=o(e.target),a=o(this).data("name");e.preventDefault(),t.hasClass("updating-message")||(p.updates.shouldRequestFilesystemCredentials&&!p.updates.ajaxLocked&&(p.updates.requestFilesystemCredentials(e),c.on("credential-modal-cancel",function(){t.removeClass("updating-message").text(p.updates.l10n.installNow).attr("aria-label",p.updates.l10n.pluginInstallNowLabel.replace("%s",a)),p.a11y.speak(p.updates.l10n.updateCancel,"polite")})),p.updates.installPlugin({slug:t.data("slug"),pagenow:pagenow,success:p.updates.installImporterSuccess,error:p.updates.installImporterError}))}),r.on("click","[data-plugin] a.delete",function(e){var t=o(e.target).parents("tr");e.preventDefault(),window.confirm(p.updates.l10n.aysDeleteUninstall.replace("%s",t.find(".plugin-title strong").text()))&&(p.updates.maybeRequestFilesystemCredentials(e),p.updates.deletePlugin({plugin:t.data("plugin"),slug:t.data("slug")}))}),c.on("click",".themes-php.network-admin .update-link",function(e){var t=o(e.target),a=t.parents("tr");e.preventDefault(),t.hasClass("updating-message")||t.hasClass("button-disabled")||(p.updates.maybeRequestFilesystemCredentials(e),p.updates.$elToReturnFocusToFromCredentialsModal=a.find(".check-column input"),p.updates.updateTheme({slug:a.data("slug")}))}),c.on("click",".themes-php.network-admin a.delete",function(e){var t=o(e.target).parents("tr");e.preventDefault(),window.confirm(p.updates.l10n.aysDelete.replace("%s",t.find(".theme-title strong").text()))&&(p.updates.maybeRequestFilesystemCredentials(e),p.updates.deleteTheme({slug:t.data("slug")}))}),r.on("click",'[type="submit"]:not([name="clear-recent-list"])',function(e){var t,n,l=o(e.target).siblings("select").val(),a=r.find('input[name="checked[]"]:checked'),i=0,d=0,u=[];switch(pagenow){case"plugins":case"plugins-network":t="plugin";break;case"themes-network":t="theme";break;default:return}if(!a.length)return e.preventDefault(),o("html, body").animate({scrollTop:0}),p.updates.addAdminNotice({id:"no-items-selected",className:"notice-error is-dismissible",message:p.updates.l10n.noItemsSelected});switch(l){case"update-selected":n=l.replace("selected",t);break;case"delete-selected":if(!window.confirm("plugin"===t?p.updates.l10n.aysBulkDelete:p.updates.l10n.aysBulkDeleteThemes))return void e.preventDefault();n=l.replace("selected",t);break;default:return}p.updates.maybeRequestFilesystemCredentials(e),e.preventDefault(),r.find('.manage-column [type="checkbox"]').prop("checked",!1),c.trigger("wp-"+t+"-bulk-"+l,a),a.each(function(e,t){var a=o(t),s=a.parents("tr");"update-selected"!==l||s.hasClass("update")&&!s.find("notice-error").length?p.updates.queue.push({action:n,data:{plugin:s.data("plugin"),slug:s.data("slug")}}):a.prop("checked",!1)}),c.on("wp-plugin-update-success wp-plugin-update-error wp-theme-update-success wp-theme-update-error",function(e,t){var a,s,n=o('[data-slug="'+t.slug+'"]');"wp-"+t.update+"-update-success"===e.type?i++:(s=t.pluginName?t.pluginName:n.find(".column-primary strong").text(),d++,u.push(s+": "+t.errorMessage)),n.find('input[name="checked[]"]:checked').prop("checked",!1),p.updates.adminNotice=p.template("wp-bulk-updates-admin-notice"),p.updates.addAdminNotice({id:"bulk-action-notice",className:"bulk-action-notice",successes:i,errors:d,errorMessages:u,type:t.update}),a=o("#bulk-action-notice").on("click","button",function(){o(this).toggleClass("bulk-action-errors-collapsed").attr("aria-expanded",!o(this).hasClass("bulk-action-errors-collapsed")),a.find(".bulk-action-errors").toggleClass("hidden")}),0<d&&!p.updates.queue.length&&o("html, body").animate({scrollTop:0})}),c.on("wp-updates-notice-added",function(){p.updates.adminNotice=p.template("wp-updates-admin-notice")}),p.updates.queueChecker()}),s.length&&s.attr("aria-describedby","live-search-desc"),s.on("keyup input",_.debounce(function(e,t){var a,s,n=o(".plugin-install-search");a={_ajax_nonce:p.updates.ajaxNonce,s:e.target.value,tab:"search",type:o("#typeselector").val(),pagenow:pagenow},s=location.href.split("?")[0]+"?"+o.param(_.omit(a,["_ajax_nonce","pagenow"])),"keyup"===e.type&&27===e.which&&(e.target.value=""),p.updates.searchTerm===a.s&&"typechange"!==t||(l.empty(),p.updates.searchTerm=a.s,window.history&&window.history.replaceState&&window.history.replaceState(null,"",s),n.length||(n=o('<li class="plugin-install-search" />').append(o("<a />",{class:"current",href:s,text:p.updates.l10n.searchResultsLabel})),o(".wp-filter .filter-links .current").removeClass("current").parents(".filter-links").prepend(n),l.prev("p").remove(),o(".plugins-popular-tags-wrapper").remove()),void 0!==p.updates.searchRequest&&p.updates.searchRequest.abort(),o("body").addClass("loading-content"),p.updates.searchRequest=p.ajax.post("search-install-plugins",a).done(function(e){o("body").removeClass("loading-content"),l.append(e.items),delete p.updates.searchRequest,0===e.count?p.a11y.speak(p.updates.l10n.noPluginsFound):p.a11y.speak(p.updates.l10n.pluginsFound.replace("%d",e.count))}))},1e3)),a.length&&a.attr("aria-describedby","live-search-desc"),a.on("keyup input",_.debounce(function(e){var t,s={_ajax_nonce:p.updates.ajaxNonce,s:e.target.value,pagenow:pagenow,plugin_status:"all"};"keyup"===e.type&&27===e.which&&(e.target.value=""),p.updates.searchTerm!==s.s&&(p.updates.searchTerm=s.s,t=_.object(_.compact(_.map(location.search.slice(1).split("&"),function(e){if(e)return e.split("=")}))),s.plugin_status=t.plugin_status||"all",window.history&&window.history.replaceState&&window.history.replaceState(null,"",location.href.split("?")[0]+"?s="+s.s+"&plugin_status="+s.plugin_status),void 0!==p.updates.searchRequest&&p.updates.searchRequest.abort(),r.empty(),o("body").addClass("loading-content"),o(".subsubsub .current").removeClass("current"),p.updates.searchRequest=p.ajax.post("search-plugins",s).done(function(e){var t=o("<span />").addClass("subtitle").html(p.updates.l10n.searchResults.replace("%s",_.escape(s.s))),a=o(".wrap .subtitle");s.s.length?a.length?a.replaceWith(t):o(".wp-header-end").before(t):(a.remove(),o(".subsubsub ."+s.plugin_status+" a").addClass("current")),o("body").removeClass("loading-content"),r.append(e.items),delete p.updates.searchRequest,0===e.count?p.a11y.speak(p.updates.l10n.noPluginsFound):p.a11y.speak(p.updates.l10n.pluginsFound.replace("%d",e.count))}))},500)),c.on("submit",".search-plugins",function(e){e.preventDefault(),o("input.wp-filter-search").trigger("input")}),c.on("click",".try-again",function(e){e.preventDefault(),s.trigger("input")}),o("#typeselector").on("change",function(){var e=o('input[name="s"]');e.val().length&&e.trigger("input","typechange")}),o("#plugin_update_from_iframe").on("click",function(e){var t,a=window.parent===window?null:window.parent;o.support.postMessage=!!window.postMessage,!1!==o.support.postMessage&&null!==a&&-1===window.parent.location.pathname.indexOf("update-core.php")&&(e.preventDefault(),t={action:"update-plugin",data:{plugin:o(this).data("plugin"),slug:o(this).data("slug")}},a.postMessage(JSON.stringify(t),window.location.origin))}),o("#plugin_install_from_iframe").on("click",function(e){var t,a=window.parent===window?null:window.parent;o.support.postMessage=!!window.postMessage,!1!==o.support.postMessage&&null!==a&&-1===window.parent.location.pathname.indexOf("index.php")&&(e.preventDefault(),t={action:"install-plugin",data:{slug:o(this).data("slug")}},a.postMessage(JSON.stringify(t),window.location.origin))}),o(window).on("message",function(e){var t,a=e.originalEvent,s=document.location.protocol+"//"+document.location.host;if(a.origin===s){try{t=o.parseJSON(a.data)}catch(e){return}if(t&&void 0!==t.action)switch(t.action){case"decrementUpdateCount":p.updates.decrementCount(t.upgradeType);break;case"install-plugin":case"update-plugin":window.tb_remove(),t.data=p.updates._addCallbacks(t.data,t.action),p.updates.queue.push(t),p.updates.queueChecker()}}}),o(window).on("beforeunload",p.updates.beforeunload)})}(jQuery,window.wp,window._wpUpdatesSettings);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/user-profile.js b/srcs/wordpress/wp-admin/js/user-profile.js deleted file mode 100644 index f737dde..0000000 --- a/srcs/wordpress/wp-admin/js/user-profile.js +++ /dev/null @@ -1,409 +0,0 @@ -/** - * @output wp-admin/js/user-profile.js - */ - -/* global ajaxurl, pwsL10n, userProfileL10n */ -(function($) { - var updateLock = false, - - $pass1Row, - $pass1, - $pass2, - $weakRow, - $weakCheckbox, - $toggleButton, - $submitButtons, - $submitButton, - currentPass; - - function generatePassword() { - if ( typeof zxcvbn !== 'function' ) { - setTimeout( generatePassword, 50 ); - return; - } else if ( ! $pass1.val() ) { - // zxcvbn loaded before user entered password. - $pass1.val( $pass1.data( 'pw' ) ); - $pass1.trigger( 'pwupdate' ); - showOrHideWeakPasswordCheckbox(); - } - else { - // zxcvbn loaded after the user entered password, check strength. - check_pass_strength(); - showOrHideWeakPasswordCheckbox(); - } - - if ( 1 !== parseInt( $toggleButton.data( 'start-masked' ), 10 ) ) { - $pass1.attr( 'type', 'text' ); - } else { - $toggleButton.trigger( 'click' ); - } - - // Once zxcvbn loads, passwords strength is known. - $( '#pw-weak-text-label' ).html( userProfileL10n.warnWeak ); - } - - function bindPass1() { - currentPass = $pass1.val(); - - if ( 1 === parseInt( $pass1.data( 'reveal' ), 10 ) ) { - generatePassword(); - } - - $pass1.on( 'input' + ' pwupdate', function () { - if ( $pass1.val() === currentPass ) { - return; - } - - currentPass = $pass1.val(); - - $pass1.removeClass( 'short bad good strong' ); - showOrHideWeakPasswordCheckbox(); - } ); - } - - function resetToggle( show ) { - $toggleButton - .attr({ - 'aria-label': show ? userProfileL10n.ariaShow : userProfileL10n.ariaHide - }) - .find( '.text' ) - .text( show ? userProfileL10n.show : userProfileL10n.hide ) - .end() - .find( '.dashicons' ) - .removeClass( show ? 'dashicons-hidden' : 'dashicons-visibility' ) - .addClass( show ? 'dashicons-visibility' : 'dashicons-hidden' ); - } - - function bindToggleButton() { - $toggleButton = $pass1Row.find('.wp-hide-pw'); - $toggleButton.show().on( 'click', function () { - if ( 'password' === $pass1.attr( 'type' ) ) { - $pass1.attr( 'type', 'text' ); - resetToggle( false ); - } else { - $pass1.attr( 'type', 'password' ); - resetToggle( true ); - } - - $pass1.focus(); - - if ( ! _.isUndefined( $pass1[0].setSelectionRange ) ) { - $pass1[0].setSelectionRange( 0, 100 ); - } - }); - } - - function bindPasswordForm() { - var $passwordWrapper, - $generateButton, - $cancelButton; - - $pass1Row = $( '.user-pass1-wrap, .user-pass-wrap' ); - - // Hide the confirm password field when JavaScript support is enabled. - $('.user-pass2-wrap').hide(); - - $submitButton = $( '#submit, #wp-submit' ).on( 'click', function () { - updateLock = false; - }); - - $submitButtons = $submitButton.add( ' #createusersub' ); - - $weakRow = $( '.pw-weak' ); - $weakCheckbox = $weakRow.find( '.pw-checkbox' ); - $weakCheckbox.change( function() { - $submitButtons.prop( 'disabled', ! $weakCheckbox.prop( 'checked' ) ); - } ); - - $pass1 = $('#pass1'); - if ( $pass1.length ) { - bindPass1(); - } else { - // Password field for the login form. - $pass1 = $( '#user_pass' ); - } - - /** - * Fix a LastPass mismatch issue, LastPass only changes pass2. - * - * This fixes the issue by copying any changes from the hidden - * pass2 field to the pass1 field, then running check_pass_strength. - */ - $pass2 = $( '#pass2' ).on( 'input', function () { - if ( $pass2.val().length > 0 ) { - $pass1.val( $pass2.val() ); - $pass2.val(''); - currentPass = ''; - $pass1.trigger( 'pwupdate' ); - } - } ); - - // Disable hidden inputs to prevent autofill and submission. - if ( $pass1.is( ':hidden' ) ) { - $pass1.prop( 'disabled', true ); - $pass2.prop( 'disabled', true ); - } - - $passwordWrapper = $pass1Row.find( '.wp-pwd' ); - $generateButton = $pass1Row.find( 'button.wp-generate-pw' ); - - bindToggleButton(); - - if ( $generateButton.length ) { - $passwordWrapper.hide(); - } - - $generateButton.show(); - $generateButton.on( 'click', function () { - updateLock = true; - - $generateButton.hide(); - $passwordWrapper.show(); - - // Enable the inputs when showing. - $pass1.attr( 'disabled', false ); - $pass2.attr( 'disabled', false ); - - if ( $pass1.val().length === 0 ) { - generatePassword(); - } - } ); - - $cancelButton = $pass1Row.find( 'button.wp-cancel-pw' ); - $cancelButton.on( 'click', function () { - updateLock = false; - - // Clear any entered password. - $pass1.val( '' ); - - // Generate a new password. - wp.ajax.post( 'generate-password' ) - .done( function( data ) { - $pass1.data( 'pw', data ); - } ); - - $generateButton.show().focus(); - $passwordWrapper.hide(); - - $weakRow.hide( 0, function () { - $weakCheckbox.removeProp( 'checked' ); - } ); - - // Disable the inputs when hiding to prevent autofill and submission. - $pass1.prop( 'disabled', true ); - $pass2.prop( 'disabled', true ); - - resetToggle( false ); - - if ( $pass1Row.closest( 'form' ).is( '#your-profile' ) ) { - // Clear password field to prevent update - $pass1.val( '' ).trigger( 'pwupdate' ); - $submitButtons.prop( 'disabled', false ); - } - } ); - - $pass1Row.closest( 'form' ).on( 'submit', function () { - updateLock = false; - - $pass1.prop( 'disabled', false ); - $pass2.prop( 'disabled', false ); - $pass2.val( $pass1.val() ); - }); - } - - function check_pass_strength() { - var pass1 = $('#pass1').val(), strength; - - $('#pass-strength-result').removeClass('short bad good strong empty'); - if ( ! pass1 ) { - $( '#pass-strength-result' ).addClass( 'empty' ).html( ' ' ); - return; - } - - strength = wp.passwordStrength.meter( pass1, wp.passwordStrength.userInputBlacklist(), pass1 ); - - switch ( strength ) { - case -1: - $( '#pass-strength-result' ).addClass( 'bad' ).html( pwsL10n.unknown ); - break; - case 2: - $('#pass-strength-result').addClass('bad').html( pwsL10n.bad ); - break; - case 3: - $('#pass-strength-result').addClass('good').html( pwsL10n.good ); - break; - case 4: - $('#pass-strength-result').addClass('strong').html( pwsL10n.strong ); - break; - case 5: - $('#pass-strength-result').addClass('short').html( pwsL10n.mismatch ); - break; - default: - $('#pass-strength-result').addClass('short').html( pwsL10n['short'] ); - } - } - - function showOrHideWeakPasswordCheckbox() { - var passStrength = $('#pass-strength-result')[0]; - - if ( passStrength.className ) { - $pass1.addClass( passStrength.className ); - if ( $( passStrength ).is( '.short, .bad' ) ) { - if ( ! $weakCheckbox.prop( 'checked' ) ) { - $submitButtons.prop( 'disabled', true ); - } - $weakRow.show(); - } else { - if ( $( passStrength ).is( '.empty' ) ) { - $submitButtons.prop( 'disabled', true ); - $weakCheckbox.prop( 'checked', false ); - } else { - $submitButtons.prop( 'disabled', false ); - } - $weakRow.hide(); - } - } - } - - $(document).ready( function() { - var $colorpicker, $stylesheet, user_id, current_user_id, - select = $( '#display_name' ), - current_name = select.val(), - greeting = $( '#wp-admin-bar-my-account' ).find( '.display-name' ); - - $( '#pass1' ).val( '' ).on( 'input' + ' pwupdate', check_pass_strength ); - $('#pass-strength-result').show(); - $('.color-palette').click( function() { - $(this).siblings('input[name="admin_color"]').prop('checked', true); - }); - - if ( select.length ) { - $('#first_name, #last_name, #nickname').bind( 'blur.user_profile', function() { - var dub = [], - inputs = { - display_nickname : $('#nickname').val() || '', - display_username : $('#user_login').val() || '', - display_firstname : $('#first_name').val() || '', - display_lastname : $('#last_name').val() || '' - }; - - if ( inputs.display_firstname && inputs.display_lastname ) { - inputs.display_firstlast = inputs.display_firstname + ' ' + inputs.display_lastname; - inputs.display_lastfirst = inputs.display_lastname + ' ' + inputs.display_firstname; - } - - $.each( $('option', select), function( i, el ){ - dub.push( el.value ); - }); - - $.each(inputs, function( id, value ) { - if ( ! value ) { - return; - } - - var val = value.replace(/<\/?[a-z][^>]*>/gi, ''); - - if ( inputs[id].length && $.inArray( val, dub ) === -1 ) { - dub.push(val); - $('<option />', { - 'text': val - }).appendTo( select ); - } - }); - }); - - /** - * Replaces "Howdy, *" in the admin toolbar whenever the display name dropdown is updated for one's own profile. - */ - select.on( 'change', function() { - if ( user_id !== current_user_id ) { - return; - } - - var display_name = $.trim( this.value ) || current_name; - - greeting.text( display_name ); - } ); - } - - $colorpicker = $( '#color-picker' ); - $stylesheet = $( '#colors-css' ); - user_id = $( 'input#user_id' ).val(); - current_user_id = $( 'input[name="checkuser_id"]' ).val(); - - $colorpicker.on( 'click.colorpicker', '.color-option', function() { - var colors, - $this = $(this); - - if ( $this.hasClass( 'selected' ) ) { - return; - } - - $this.siblings( '.selected' ).removeClass( 'selected' ); - $this.addClass( 'selected' ).find( 'input[type="radio"]' ).prop( 'checked', true ); - - // Set color scheme - if ( user_id === current_user_id ) { - // Load the colors stylesheet. - // The default color scheme won't have one, so we'll need to create an element. - if ( 0 === $stylesheet.length ) { - $stylesheet = $( '<link rel="stylesheet" />' ).appendTo( 'head' ); - } - $stylesheet.attr( 'href', $this.children( '.css_url' ).val() ); - - // repaint icons - if ( typeof wp !== 'undefined' && wp.svgPainter ) { - try { - colors = $.parseJSON( $this.children( '.icon_colors' ).val() ); - } catch ( error ) {} - - if ( colors ) { - wp.svgPainter.setColors( colors ); - wp.svgPainter.paint(); - } - } - - // update user option - $.post( ajaxurl, { - action: 'save-user-color-scheme', - color_scheme: $this.children( 'input[name="admin_color"]' ).val(), - nonce: $('#color-nonce').val() - }).done( function( response ) { - if ( response.success ) { - $( 'body' ).removeClass( response.data.previousScheme ).addClass( response.data.currentScheme ); - } - }); - } - }); - - bindPasswordForm(); - }); - - $( '#destroy-sessions' ).on( 'click', function( e ) { - var $this = $(this); - - wp.ajax.post( 'destroy-sessions', { - nonce: $( '#_wpnonce' ).val(), - user_id: $( '#user_id' ).val() - }).done( function( response ) { - $this.prop( 'disabled', true ); - $this.siblings( '.notice' ).remove(); - $this.before( '<div class="notice notice-success inline"><p>' + response.message + '</p></div>' ); - }).fail( function( response ) { - $this.siblings( '.notice' ).remove(); - $this.before( '<div class="notice notice-error inline"><p>' + response.message + '</p></div>' ); - }); - - e.preventDefault(); - }); - - window.generatePassword = generatePassword; - - /* Warn the user if password was generated but not saved */ - $( window ).on( 'beforeunload', function () { - if ( true === updateLock ) { - return userProfileL10n.warn; - } - } ); - -})(jQuery); diff --git a/srcs/wordpress/wp-admin/js/user-profile.min.js b/srcs/wordpress/wp-admin/js/user-profile.min.js deleted file mode 100644 index a2d5e1e..0000000 --- a/srcs/wordpress/wp-admin/js/user-profile.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(o){var a,t,n,i,r,l,d,p,c,u=!1;function h(){"function"==typeof zxcvbn?(t.val()?v():(t.val(t.data("pw")),t.trigger("pwupdate")),w(),1!==parseInt(l.data("start-masked"),10)?t.attr("type","text"):l.trigger("click"),o("#pw-weak-text-label").html(userProfileL10n.warnWeak)):setTimeout(h,50)}function f(e){l.attr({"aria-label":e?userProfileL10n.ariaShow:userProfileL10n.ariaHide}).find(".text").text(e?userProfileL10n.show:userProfileL10n.hide).end().find(".dashicons").removeClass(e?"dashicons-hidden":"dashicons-visibility").addClass(e?"dashicons-visibility":"dashicons-hidden")}function m(){var e,s;a=o(".user-pass1-wrap, .user-pass-wrap"),o(".user-pass2-wrap").hide(),p=o("#submit, #wp-submit").on("click",function(){u=!1}),d=p.add(" #createusersub"),i=o(".pw-weak"),(r=i.find(".pw-checkbox")).change(function(){d.prop("disabled",!r.prop("checked"))}),(t=o("#pass1")).length?(c=t.val(),1===parseInt(t.data("reveal"),10)&&h(),t.on("input pwupdate",function(){t.val()!==c&&(c=t.val(),t.removeClass("short bad good strong"),w())})):t=o("#user_pass"),n=o("#pass2").on("input",function(){0<n.val().length&&(t.val(n.val()),n.val(""),c="",t.trigger("pwupdate"))}),t.is(":hidden")&&(t.prop("disabled",!0),n.prop("disabled",!0)),e=a.find(".wp-pwd"),s=a.find("button.wp-generate-pw"),(l=a.find(".wp-hide-pw")).show().on("click",function(){"password"===t.attr("type")?(t.attr("type","text"),f(!1)):(t.attr("type","password"),f(!0)),t.focus(),_.isUndefined(t[0].setSelectionRange)||t[0].setSelectionRange(0,100)}),s.length&&e.hide(),s.show(),s.on("click",function(){u=!0,s.hide(),e.show(),t.attr("disabled",!1),n.attr("disabled",!1),0===t.val().length&&h()}),a.find("button.wp-cancel-pw").on("click",function(){u=!1,t.val(""),wp.ajax.post("generate-password").done(function(e){t.data("pw",e)}),s.show().focus(),e.hide(),i.hide(0,function(){r.removeProp("checked")}),t.prop("disabled",!0),n.prop("disabled",!0),f(!1),a.closest("form").is("#your-profile")&&(t.val("").trigger("pwupdate"),d.prop("disabled",!1))}),a.closest("form").on("submit",function(){u=!1,t.prop("disabled",!1),n.prop("disabled",!1),n.val(t.val())})}function v(){var e=o("#pass1").val();if(o("#pass-strength-result").removeClass("short bad good strong empty"),e)switch(wp.passwordStrength.meter(e,wp.passwordStrength.userInputBlacklist(),e)){case-1:o("#pass-strength-result").addClass("bad").html(pwsL10n.unknown);break;case 2:o("#pass-strength-result").addClass("bad").html(pwsL10n.bad);break;case 3:o("#pass-strength-result").addClass("good").html(pwsL10n.good);break;case 4:o("#pass-strength-result").addClass("strong").html(pwsL10n.strong);break;case 5:o("#pass-strength-result").addClass("short").html(pwsL10n.mismatch);break;default:o("#pass-strength-result").addClass("short").html(pwsL10n.short)}else o("#pass-strength-result").addClass("empty").html(" ")}function w(){var e=o("#pass-strength-result")[0];e.className&&(t.addClass(e.className),o(e).is(".short, .bad")?(r.prop("checked")||d.prop("disabled",!0),i.show()):(o(e).is(".empty")?(d.prop("disabled",!0),r.prop("checked",!1)):d.prop("disabled",!1),i.hide()))}o(document).ready(function(){var e,a,t,n,i=o("#display_name"),s=i.val(),r=o("#wp-admin-bar-my-account").find(".display-name");o("#pass1").val("").on("input pwupdate",v),o("#pass-strength-result").show(),o(".color-palette").click(function(){o(this).siblings('input[name="admin_color"]').prop("checked",!0)}),i.length&&(o("#first_name, #last_name, #nickname").bind("blur.user_profile",function(){var t=[],n={display_nickname:o("#nickname").val()||"",display_username:o("#user_login").val()||"",display_firstname:o("#first_name").val()||"",display_lastname:o("#last_name").val()||""};n.display_firstname&&n.display_lastname&&(n.display_firstlast=n.display_firstname+" "+n.display_lastname,n.display_lastfirst=n.display_lastname+" "+n.display_firstname),o.each(o("option",i),function(e,s){t.push(s.value)}),o.each(n,function(e,s){if(s){var a=s.replace(/<\/?[a-z][^>]*>/gi,"");n[e].length&&-1===o.inArray(a,t)&&(t.push(a),o("<option />",{text:a}).appendTo(i))}})}),i.on("change",function(){if(t===n){var e=o.trim(this.value)||s;r.text(e)}})),e=o("#color-picker"),a=o("#colors-css"),t=o("input#user_id").val(),n=o('input[name="checkuser_id"]').val(),e.on("click.colorpicker",".color-option",function(){var e,s=o(this);if(!s.hasClass("selected")&&(s.siblings(".selected").removeClass("selected"),s.addClass("selected").find('input[type="radio"]').prop("checked",!0),t===n)){if(0===a.length&&(a=o('<link rel="stylesheet" />').appendTo("head")),a.attr("href",s.children(".css_url").val()),"undefined"!=typeof wp&&wp.svgPainter){try{e=o.parseJSON(s.children(".icon_colors").val())}catch(e){}e&&(wp.svgPainter.setColors(e),wp.svgPainter.paint())}o.post(ajaxurl,{action:"save-user-color-scheme",color_scheme:s.children('input[name="admin_color"]').val(),nonce:o("#color-nonce").val()}).done(function(e){e.success&&o("body").removeClass(e.data.previousScheme).addClass(e.data.currentScheme)})}}),m()}),o("#destroy-sessions").on("click",function(e){var s=o(this);wp.ajax.post("destroy-sessions",{nonce:o("#_wpnonce").val(),user_id:o("#user_id").val()}).done(function(e){s.prop("disabled",!0),s.siblings(".notice").remove(),s.before('<div class="notice notice-success inline"><p>'+e.message+"</p></div>")}).fail(function(e){s.siblings(".notice").remove(),s.before('<div class="notice notice-error inline"><p>'+e.message+"</p></div>")}),e.preventDefault()}),window.generatePassword=h,o(window).on("beforeunload",function(){if(!0===u)return userProfileL10n.warn})}(jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/user-suggest.js b/srcs/wordpress/wp-admin/js/user-suggest.js deleted file mode 100644 index 19770df..0000000 --- a/srcs/wordpress/wp-admin/js/user-suggest.js +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Suggests users in a multisite environment. - * - * For input fields where the admin can select a user based on email or - * username, this script shows an autocompletion menu for these inputs. Should - * only be used in a multisite environment. Only users in the currently active - * site are shown. - * - * @since 3.4.0 - * @output wp-admin/js/user-suggest.js - */ - -/* global ajaxurl, current_site_id, isRtl */ - -(function( $ ) { - var id = ( typeof current_site_id !== 'undefined' ) ? '&site_id=' + current_site_id : ''; - $(document).ready( function() { - var position = { offset: '0, -1' }; - if ( typeof isRtl !== 'undefined' && isRtl ) { - position.my = 'right top'; - position.at = 'right bottom'; - } - - /** - * Adds an autocomplete function to input fields marked with the class - * 'wp-suggest-user'. - * - * A minimum of two characters is required to trigger the suggestions. The - * autocompletion menu is shown at the left bottom of the input field. On - * RTL installations, it is shown at the right top. Adds the class 'open' to - * the input field when the autocompletion menu is shown. - * - * Does a backend call to retrieve the users. - * - * Optional data-attributes: - * - data-autocomplete-type (add, search) - * The action that is going to be performed: search for existing users - * or add a new one. Default: add - * - data-autocomplete-field (user_login, user_email) - * The field that is returned as the value for the suggestion. - * Default: user_login - * - * @see wp-admin/includes/admin-actions.php:wp_ajax_autocomplete_user() - */ - $( '.wp-suggest-user' ).each( function(){ - var $this = $( this ), - autocompleteType = ( typeof $this.data( 'autocompleteType' ) !== 'undefined' ) ? $this.data( 'autocompleteType' ) : 'add', - autocompleteField = ( typeof $this.data( 'autocompleteField' ) !== 'undefined' ) ? $this.data( 'autocompleteField' ) : 'user_login'; - - $this.autocomplete({ - source: ajaxurl + '?action=autocomplete-user&autocomplete_type=' + autocompleteType + '&autocomplete_field=' + autocompleteField + id, - delay: 500, - minLength: 2, - position: position, - open: function() { - $( this ).addClass( 'open' ); - }, - close: function() { - $( this ).removeClass( 'open' ); - } - }); - }); - }); -})( jQuery ); diff --git a/srcs/wordpress/wp-admin/js/user-suggest.min.js b/srcs/wordpress/wp-admin/js/user-suggest.min.js deleted file mode 100644 index 9d0da25..0000000 --- a/srcs/wordpress/wp-admin/js/user-suggest.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(i){var n="undefined"!=typeof current_site_id?"&site_id="+current_site_id:"";i(document).ready(function(){var a={offset:"0, -1"};"undefined"!=typeof isRtl&&isRtl&&(a.my="right top",a.at="right bottom"),i(".wp-suggest-user").each(function(){var e=i(this),t=void 0!==e.data("autocompleteType")?e.data("autocompleteType"):"add",o=void 0!==e.data("autocompleteField")?e.data("autocompleteField"):"user_login";e.autocomplete({source:ajaxurl+"?action=autocomplete-user&autocomplete_type="+t+"&autocomplete_field="+o+n,delay:500,minLength:2,position:a,open:function(){i(this).addClass("open")},close:function(){i(this).removeClass("open")}})})})}(jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/widgets.js b/srcs/wordpress/wp-admin/js/widgets.js deleted file mode 100644 index 00ae62d..0000000 --- a/srcs/wordpress/wp-admin/js/widgets.js +++ /dev/null @@ -1,761 +0,0 @@ -/** - * @output wp-admin/js/widgets.js - */ - -/* global ajaxurl, isRtl, wpWidgets */ - -(function($) { - var $document = $( document ); - -window.wpWidgets = { - /** - * A closed Sidebar that gets a Widget dragged over it. - * - * @var {element|null} - */ - hoveredSidebar: null, - - /** - * Translations. - * - * Exported from PHP in wp_default_scripts(). - * - * @var {object} - */ - l10n: { - save: '{save}', - saved: '{saved}', - saveAlert: '{saveAlert}', - widgetAdded: '{widgetAdded}' - }, - - /** - * Lookup of which widgets have had change events triggered. - * - * @var {object} - */ - dirtyWidgets: {}, - - init : function() { - var rem, the_id, - self = this, - chooser = $('.widgets-chooser'), - selectSidebar = chooser.find('.widgets-chooser-sidebars'), - sidebars = $('div.widgets-sortables'), - isRTL = !! ( 'undefined' !== typeof isRtl && isRtl ); - - // Handle the widgets containers in the right column. - $( '#widgets-right .sidebar-name' ) - /* - * Toggle the widgets containers when clicked and update the toggle - * button `aria-expanded` attribute value. - */ - .click( function() { - var $this = $( this ), - $wrap = $this.closest( '.widgets-holder-wrap '), - $toggle = $this.find( '.handlediv' ); - - if ( $wrap.hasClass( 'closed' ) ) { - $wrap.removeClass( 'closed' ); - $toggle.attr( 'aria-expanded', 'true' ); - // Refresh the jQuery UI sortable items. - $this.parent().sortable( 'refresh' ); - } else { - $wrap.addClass( 'closed' ); - $toggle.attr( 'aria-expanded', 'false' ); - } - - // Update the admin menu "sticky" state. - $document.triggerHandler( 'wp-pin-menu' ); - }) - /* - * Set the initial `aria-expanded` attribute value on the widgets - * containers toggle button. The first one is expanded by default. - */ - .find( '.handlediv' ).each( function( index ) { - if ( 0 === index ) { - // jQuery equivalent of `continue` within an `each()` loop. - return; - } - - $( this ).attr( 'aria-expanded', 'false' ); - }); - - // Show AYS dialog when there are unsaved widget changes. - $( window ).on( 'beforeunload.widgets', function( event ) { - var dirtyWidgetIds = [], unsavedWidgetsElements; - $.each( self.dirtyWidgets, function( widgetId, dirty ) { - if ( dirty ) { - dirtyWidgetIds.push( widgetId ); - } - }); - if ( 0 !== dirtyWidgetIds.length ) { - unsavedWidgetsElements = $( '#widgets-right' ).find( '.widget' ).filter( function() { - return -1 !== dirtyWidgetIds.indexOf( $( this ).prop( 'id' ).replace( /^widget-\d+_/, '' ) ); - }); - unsavedWidgetsElements.each( function() { - if ( ! $( this ).hasClass( 'open' ) ) { - $( this ).find( '.widget-title-action:first' ).click(); - } - }); - - // Bring the first unsaved widget into view and focus on the first tabbable field. - unsavedWidgetsElements.first().each( function() { - if ( this.scrollIntoViewIfNeeded ) { - this.scrollIntoViewIfNeeded(); - } else { - this.scrollIntoView(); - } - $( this ).find( '.widget-inside :tabbable:first' ).focus(); - } ); - - event.returnValue = wpWidgets.l10n.saveAlert; - return event.returnValue; - } - }); - - // Handle the widgets containers in the left column. - $( '#widgets-left .sidebar-name' ).click( function() { - var $wrap = $( this ).closest( '.widgets-holder-wrap' ); - - $wrap - .toggleClass( 'closed' ) - .find( '.handlediv' ).attr( 'aria-expanded', ! $wrap.hasClass( 'closed' ) ); - - // Update the admin menu "sticky" state. - $document.triggerHandler( 'wp-pin-menu' ); - }); - - $(document.body).bind('click.widgets-toggle', function(e) { - var target = $(e.target), - css = { 'z-index': 100 }, - widget, inside, targetWidth, widgetWidth, margin, saveButton, widgetId, - toggleBtn = target.closest( '.widget' ).find( '.widget-top button.widget-action' ); - - if ( target.parents('.widget-top').length && ! target.parents('#available-widgets').length ) { - widget = target.closest('div.widget'); - inside = widget.children('.widget-inside'); - targetWidth = parseInt( widget.find('input.widget-width').val(), 10 ); - widgetWidth = widget.parent().width(); - widgetId = inside.find( '.widget-id' ).val(); - - // Save button is initially disabled, but is enabled when a field is changed. - if ( ! widget.data( 'dirty-state-initialized' ) ) { - saveButton = inside.find( '.widget-control-save' ); - saveButton.prop( 'disabled', true ).val( wpWidgets.l10n.saved ); - inside.on( 'input change', function() { - self.dirtyWidgets[ widgetId ] = true; - widget.addClass( 'widget-dirty' ); - saveButton.prop( 'disabled', false ).val( wpWidgets.l10n.save ); - }); - widget.data( 'dirty-state-initialized', true ); - } - - if ( inside.is(':hidden') ) { - if ( targetWidth > 250 && ( targetWidth + 30 > widgetWidth ) && widget.closest('div.widgets-sortables').length ) { - if ( widget.closest('div.widget-liquid-right').length ) { - margin = isRTL ? 'margin-right' : 'margin-left'; - } else { - margin = isRTL ? 'margin-left' : 'margin-right'; - } - - css[ margin ] = widgetWidth - ( targetWidth + 30 ) + 'px'; - widget.css( css ); - } - /* - * Don't change the order of attributes changes and animation: - * it's important for screen readers, see ticket #31476. - */ - toggleBtn.attr( 'aria-expanded', 'true' ); - inside.slideDown( 'fast', function() { - widget.addClass( 'open' ); - }); - } else { - /* - * Don't change the order of attributes changes and animation: - * it's important for screen readers, see ticket #31476. - */ - toggleBtn.attr( 'aria-expanded', 'false' ); - inside.slideUp( 'fast', function() { - widget.attr( 'style', '' ); - widget.removeClass( 'open' ); - }); - } - } else if ( target.hasClass('widget-control-save') ) { - wpWidgets.save( target.closest('div.widget'), 0, 1, 0 ); - e.preventDefault(); - } else if ( target.hasClass('widget-control-remove') ) { - wpWidgets.save( target.closest('div.widget'), 1, 1, 0 ); - } else if ( target.hasClass('widget-control-close') ) { - widget = target.closest('div.widget'); - widget.removeClass( 'open' ); - toggleBtn.attr( 'aria-expanded', 'false' ); - wpWidgets.close( widget ); - } else if ( target.attr( 'id' ) === 'inactive-widgets-control-remove' ) { - wpWidgets.removeInactiveWidgets(); - e.preventDefault(); - } - }); - - sidebars.children('.widget').each( function() { - var $this = $(this); - - wpWidgets.appendTitle( this ); - - if ( $this.find( 'p.widget-error' ).length ) { - $this.find( '.widget-action' ).trigger( 'click' ).attr( 'aria-expanded', 'true' ); - } - }); - - $('#widget-list').children('.widget').draggable({ - connectToSortable: 'div.widgets-sortables', - handle: '> .widget-top > .widget-title', - distance: 2, - helper: 'clone', - zIndex: 100, - containment: '#wpwrap', - refreshPositions: true, - start: function( event, ui ) { - var chooser = $(this).find('.widgets-chooser'); - - ui.helper.find('div.widget-description').hide(); - the_id = this.id; - - if ( chooser.length ) { - // Hide the chooser and move it out of the widget - $( '#wpbody-content' ).append( chooser.hide() ); - // Delete the cloned chooser from the drag helper - ui.helper.find('.widgets-chooser').remove(); - self.clearWidgetSelection(); - } - }, - stop: function() { - if ( rem ) { - $(rem).hide(); - } - - rem = ''; - } - }); - - /** - * Opens and closes previously closed Sidebars when Widgets are dragged over/out of them. - */ - sidebars.droppable( { - tolerance: 'intersect', - - /** - * Open Sidebar when a Widget gets dragged over it. - * - * @ignore - * - * @param {object} event jQuery event object. - */ - over: function( event ) { - var $wrap = $( event.target ).parent(); - - if ( wpWidgets.hoveredSidebar && ! $wrap.is( wpWidgets.hoveredSidebar ) ) { - // Close the previous Sidebar as the Widget has been dragged onto another Sidebar. - wpWidgets.closeSidebar( event ); - } - - if ( $wrap.hasClass( 'closed' ) ) { - wpWidgets.hoveredSidebar = $wrap; - $wrap - .removeClass( 'closed' ) - .find( '.handlediv' ).attr( 'aria-expanded', 'true' ); - } - - $( this ).sortable( 'refresh' ); - }, - - /** - * Close Sidebar when the Widget gets dragged out of it. - * - * @ignore - * - * @param {object} event jQuery event object. - */ - out: function( event ) { - if ( wpWidgets.hoveredSidebar ) { - wpWidgets.closeSidebar( event ); - } - } - } ); - - sidebars.sortable({ - placeholder: 'widget-placeholder', - items: '> .widget', - handle: '> .widget-top > .widget-title', - cursor: 'move', - distance: 2, - containment: '#wpwrap', - tolerance: 'pointer', - refreshPositions: true, - start: function( event, ui ) { - var height, $this = $(this), - $wrap = $this.parent(), - inside = ui.item.children('.widget-inside'); - - if ( inside.css('display') === 'block' ) { - ui.item.removeClass('open'); - ui.item.find( '.widget-top button.widget-action' ).attr( 'aria-expanded', 'false' ); - inside.hide(); - $(this).sortable('refreshPositions'); - } - - if ( ! $wrap.hasClass('closed') ) { - // Lock all open sidebars min-height when starting to drag. - // Prevents jumping when dragging a widget from an open sidebar to a closed sidebar below. - height = ui.item.hasClass('ui-draggable') ? $this.height() : 1 + $this.height(); - $this.css( 'min-height', height + 'px' ); - } - }, - - stop: function( event, ui ) { - var addNew, widgetNumber, $sidebar, $children, child, item, - $widget = ui.item, - id = the_id; - - // Reset the var to hold a previously closed sidebar. - wpWidgets.hoveredSidebar = null; - - if ( $widget.hasClass('deleting') ) { - wpWidgets.save( $widget, 1, 0, 1 ); // delete widget - $widget.remove(); - return; - } - - addNew = $widget.find('input.add_new').val(); - widgetNumber = $widget.find('input.multi_number').val(); - - $widget.attr( 'style', '' ).removeClass('ui-draggable'); - the_id = ''; - - if ( addNew ) { - if ( 'multi' === addNew ) { - $widget.html( - $widget.html().replace( /<[^<>]+>/g, function( tag ) { - return tag.replace( /__i__|%i%/g, widgetNumber ); - }) - ); - - $widget.attr( 'id', id.replace( '__i__', widgetNumber ) ); - widgetNumber++; - - $( 'div#' + id ).find( 'input.multi_number' ).val( widgetNumber ); - } else if ( 'single' === addNew ) { - $widget.attr( 'id', 'new-' + id ); - rem = 'div#' + id; - } - - wpWidgets.save( $widget, 0, 0, 1 ); - $widget.find('input.add_new').val(''); - $document.trigger( 'widget-added', [ $widget ] ); - } - - $sidebar = $widget.parent(); - - if ( $sidebar.parent().hasClass('closed') ) { - $sidebar.parent() - .removeClass( 'closed' ) - .find( '.handlediv' ).attr( 'aria-expanded', 'true' ); - - $children = $sidebar.children('.widget'); - - // Make sure the dropped widget is at the top - if ( $children.length > 1 ) { - child = $children.get(0); - item = $widget.get(0); - - if ( child.id && item.id && child.id !== item.id ) { - $( child ).before( $widget ); - } - } - } - - if ( addNew ) { - $widget.find( '.widget-action' ).trigger( 'click' ); - } else { - wpWidgets.saveOrder( $sidebar.attr('id') ); - } - }, - - activate: function() { - $(this).parent().addClass( 'widget-hover' ); - }, - - deactivate: function() { - // Remove all min-height added on "start" - $(this).css( 'min-height', '' ).parent().removeClass( 'widget-hover' ); - }, - - receive: function( event, ui ) { - var $sender = $( ui.sender ); - - // Don't add more widgets to orphaned sidebars - if ( this.id.indexOf('orphaned_widgets') > -1 ) { - $sender.sortable('cancel'); - return; - } - - // If the last widget was moved out of an orphaned sidebar, close and remove it. - if ( $sender.attr('id').indexOf('orphaned_widgets') > -1 && ! $sender.children('.widget').length ) { - $sender.parents('.orphan-sidebar').slideUp( 400, function(){ $(this).remove(); } ); - } - } - }).sortable( 'option', 'connectWith', 'div.widgets-sortables' ); - - $('#available-widgets').droppable({ - tolerance: 'pointer', - accept: function(o){ - return $(o).parent().attr('id') !== 'widget-list'; - }, - drop: function(e,ui) { - ui.draggable.addClass('deleting'); - $('#removing-widget').hide().children('span').empty(); - }, - over: function(e,ui) { - ui.draggable.addClass('deleting'); - $('div.widget-placeholder').hide(); - - if ( ui.draggable.hasClass('ui-sortable-helper') ) { - $('#removing-widget').show().children('span') - .html( ui.draggable.find( 'div.widget-title' ).children( 'h3' ).html() ); - } - }, - out: function(e,ui) { - ui.draggable.removeClass('deleting'); - $('div.widget-placeholder').show(); - $('#removing-widget').hide().children('span').empty(); - } - }); - - // Area Chooser - $( '#widgets-right .widgets-holder-wrap' ).each( function( index, element ) { - var $element = $( element ), - name = $element.find( '.sidebar-name h2' ).text(), - ariaLabel = $element.find( '.sidebar-name' ).data( 'add-to' ), - id = $element.find( '.widgets-sortables' ).attr( 'id' ), - li = $( '<li>' ), - button = $( '<button>', { - type: 'button', - 'aria-pressed': 'false', - 'class': 'widgets-chooser-button', - 'aria-label': ariaLabel - } ).text( $.trim( name ) ); - - li.append( button ); - - if ( index === 0 ) { - li.addClass( 'widgets-chooser-selected' ); - button.attr( 'aria-pressed', 'true' ); - } - - selectSidebar.append( li ); - li.data( 'sidebarId', id ); - }); - - $( '#available-widgets .widget .widget-top' ).on( 'click.widgets-chooser', function() { - var $widget = $( this ).closest( '.widget' ), - toggleButton = $( this ).find( '.widget-action' ), - chooserButtons = selectSidebar.find( '.widgets-chooser-button' ); - - if ( $widget.hasClass( 'widget-in-question' ) || $( '#widgets-left' ).hasClass( 'chooser' ) ) { - toggleButton.attr( 'aria-expanded', 'false' ); - self.closeChooser(); - } else { - // Open the chooser - self.clearWidgetSelection(); - $( '#widgets-left' ).addClass( 'chooser' ); - // Add CSS class and insert the chooser after the widget description. - $widget.addClass( 'widget-in-question' ).children( '.widget-description' ).after( chooser ); - // Open the chooser with a slide down animation. - chooser.slideDown( 300, function() { - // Update the toggle button aria-expanded attribute after previous DOM manipulations. - toggleButton.attr( 'aria-expanded', 'true' ); - }); - - chooserButtons.on( 'click.widgets-chooser', function() { - selectSidebar.find( '.widgets-chooser-selected' ).removeClass( 'widgets-chooser-selected' ); - chooserButtons.attr( 'aria-pressed', 'false' ); - $( this ) - .attr( 'aria-pressed', 'true' ) - .closest( 'li' ).addClass( 'widgets-chooser-selected' ); - } ); - } - }); - - // Add event handlers - chooser.on( 'click.widgets-chooser', function( event ) { - var $target = $( event.target ); - - if ( $target.hasClass('button-primary') ) { - self.addWidget( chooser ); - self.closeChooser(); - } else if ( $target.hasClass( 'widgets-chooser-cancel' ) ) { - self.closeChooser(); - } - }).on( 'keyup.widgets-chooser', function( event ) { - if ( event.which === $.ui.keyCode.ESCAPE ) { - self.closeChooser(); - } - }); - }, - - saveOrder : function( sidebarId ) { - var data = { - action: 'widgets-order', - savewidgets: $('#_wpnonce_widgets').val(), - sidebars: [] - }; - - if ( sidebarId ) { - $( '#' + sidebarId ).find( '.spinner:first' ).addClass( 'is-active' ); - } - - $('div.widgets-sortables').each( function() { - if ( $(this).sortable ) { - data['sidebars[' + $(this).attr('id') + ']'] = $(this).sortable('toArray').join(','); - } - }); - - $.post( ajaxurl, data, function() { - $( '#inactive-widgets-control-remove' ).prop( 'disabled' , ! $( '#wp_inactive_widgets .widget' ).length ); - $( '.spinner' ).removeClass( 'is-active' ); - }); - }, - - save : function( widget, del, animate, order ) { - var self = this, data, a, - sidebarId = widget.closest( 'div.widgets-sortables' ).attr( 'id' ), - form = widget.find( 'form' ), - isAdd = widget.find( 'input.add_new' ).val(); - - if ( ! del && ! isAdd && form.prop( 'checkValidity' ) && ! form[0].checkValidity() ) { - return; - } - - data = form.serialize(); - - widget = $(widget); - $( '.spinner', widget ).addClass( 'is-active' ); - - a = { - action: 'save-widget', - savewidgets: $('#_wpnonce_widgets').val(), - sidebar: sidebarId - }; - - if ( del ) { - a.delete_widget = 1; - } - - data += '&' + $.param(a); - - $.post( ajaxurl, data, function(r) { - var id = $('input.widget-id', widget).val(); - - if ( del ) { - if ( ! $('input.widget_number', widget).val() ) { - $('#available-widgets').find('input.widget-id').each(function(){ - if ( $(this).val() === id ) { - $(this).closest('div.widget').show(); - } - }); - } - - if ( animate ) { - order = 0; - widget.slideUp( 'fast', function() { - $( this ).remove(); - wpWidgets.saveOrder(); - delete self.dirtyWidgets[ id ]; - }); - } else { - widget.remove(); - delete self.dirtyWidgets[ id ]; - - if ( sidebarId === 'wp_inactive_widgets' ) { - $( '#inactive-widgets-control-remove' ).prop( 'disabled' , ! $( '#wp_inactive_widgets .widget' ).length ); - } - } - } else { - $( '.spinner' ).removeClass( 'is-active' ); - if ( r && r.length > 2 ) { - $( 'div.widget-content', widget ).html( r ); - wpWidgets.appendTitle( widget ); - - // Re-disable the save button. - widget.find( '.widget-control-save' ).prop( 'disabled', true ).val( wpWidgets.l10n.saved ); - - widget.removeClass( 'widget-dirty' ); - - // Clear the dirty flag from the widget. - delete self.dirtyWidgets[ id ]; - - $document.trigger( 'widget-updated', [ widget ] ); - - if ( sidebarId === 'wp_inactive_widgets' ) { - $( '#inactive-widgets-control-remove' ).prop( 'disabled' , ! $( '#wp_inactive_widgets .widget' ).length ); - } - } - } - - if ( order ) { - wpWidgets.saveOrder(); - } - }); - }, - - removeInactiveWidgets : function() { - var $element = $( '.remove-inactive-widgets' ), self = this, a, data; - - $( '.spinner', $element ).addClass( 'is-active' ); - - a = { - action : 'delete-inactive-widgets', - removeinactivewidgets : $( '#_wpnonce_remove_inactive_widgets' ).val() - }; - - data = $.param( a ); - - $.post( ajaxurl, data, function() { - $( '#wp_inactive_widgets .widget' ).each(function() { - var $widget = $( this ); - delete self.dirtyWidgets[ $widget.find( 'input.widget-id' ).val() ]; - $widget.remove(); - }); - $( '#inactive-widgets-control-remove' ).prop( 'disabled', true ); - $( '.spinner', $element ).removeClass( 'is-active' ); - } ); - }, - - appendTitle : function(widget) { - var title = $('input[id*="-title"]', widget).val() || ''; - - if ( title ) { - title = ': ' + title.replace(/<[^<>]+>/g, '').replace(/</g, '<').replace(/>/g, '>'); - } - - $(widget).children('.widget-top').children('.widget-title').children() - .children('.in-widget-title').html(title); - - }, - - close : function(widget) { - widget.children('.widget-inside').slideUp('fast', function() { - widget.attr( 'style', '' ) - .find( '.widget-top button.widget-action' ) - .attr( 'aria-expanded', 'false' ) - .focus(); - }); - }, - - addWidget: function( chooser ) { - var widget, widgetId, add, n, viewportTop, viewportBottom, sidebarBounds, - sidebarId = chooser.find( '.widgets-chooser-selected' ).data('sidebarId'), - sidebar = $( '#' + sidebarId ); - - widget = $('#available-widgets').find('.widget-in-question').clone(); - widgetId = widget.attr('id'); - add = widget.find( 'input.add_new' ).val(); - n = widget.find( 'input.multi_number' ).val(); - - // Remove the cloned chooser from the widget - widget.find('.widgets-chooser').remove(); - - if ( 'multi' === add ) { - widget.html( - widget.html().replace( /<[^<>]+>/g, function(m) { - return m.replace( /__i__|%i%/g, n ); - }) - ); - - widget.attr( 'id', widgetId.replace( '__i__', n ) ); - n++; - $( '#' + widgetId ).find('input.multi_number').val(n); - } else if ( 'single' === add ) { - widget.attr( 'id', 'new-' + widgetId ); - $( '#' + widgetId ).hide(); - } - - // Open the widgets container. - sidebar.closest( '.widgets-holder-wrap' ) - .removeClass( 'closed' ) - .find( '.handlediv' ).attr( 'aria-expanded', 'true' ); - - sidebar.append( widget ); - sidebar.sortable('refresh'); - - wpWidgets.save( widget, 0, 0, 1 ); - // No longer "new" widget - widget.find( 'input.add_new' ).val(''); - - $document.trigger( 'widget-added', [ widget ] ); - - /* - * Check if any part of the sidebar is visible in the viewport. If it is, don't scroll. - * Otherwise, scroll up to so the sidebar is in view. - * - * We do this by comparing the top and bottom, of the sidebar so see if they are within - * the bounds of the viewport. - */ - viewportTop = $(window).scrollTop(); - viewportBottom = viewportTop + $(window).height(); - sidebarBounds = sidebar.offset(); - - sidebarBounds.bottom = sidebarBounds.top + sidebar.outerHeight(); - - if ( viewportTop > sidebarBounds.bottom || viewportBottom < sidebarBounds.top ) { - $( 'html, body' ).animate({ - scrollTop: sidebarBounds.top - 130 - }, 200 ); - } - - window.setTimeout( function() { - // Cannot use a callback in the animation above as it fires twice, - // have to queue this "by hand". - widget.find( '.widget-title' ).trigger('click'); - // At the end of the animation, announce the widget has been added. - window.wp.a11y.speak( wpWidgets.l10n.widgetAdded, 'assertive' ); - }, 250 ); - }, - - closeChooser: function() { - var self = this, - widgetInQuestion = $( '#available-widgets .widget-in-question' ); - - $( '.widgets-chooser' ).slideUp( 200, function() { - $( '#wpbody-content' ).append( this ); - self.clearWidgetSelection(); - // Move focus back to the toggle button. - widgetInQuestion.find( '.widget-action' ).attr( 'aria-expanded', 'false' ).focus(); - }); - }, - - clearWidgetSelection: function() { - $( '#widgets-left' ).removeClass( 'chooser' ); - $( '.widget-in-question' ).removeClass( 'widget-in-question' ); - }, - - /** - * Closes a Sidebar that was previously closed, but opened by dragging a Widget over it. - * - * Used when a Widget gets dragged in/out of the Sidebar and never dropped. - * - * @param {object} event jQuery event object. - */ - closeSidebar: function( event ) { - this.hoveredSidebar - .addClass( 'closed' ) - .find( '.handlediv' ).attr( 'aria-expanded', 'false' ); - - $( event.target ).css( 'min-height', '' ); - this.hoveredSidebar = null; - } -}; - -$document.ready( function(){ wpWidgets.init(); } ); - -})(jQuery); diff --git a/srcs/wordpress/wp-admin/js/widgets.min.js b/srcs/wordpress/wp-admin/js/widgets.min.js deleted file mode 100644 index f8bdc29..0000000 --- a/srcs/wordpress/wp-admin/js/widgets.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(h){var v=h(document);window.wpWidgets={hoveredSidebar:null,l10n:{save:"{save}",saved:"{saved}",saveAlert:"{saveAlert}",widgetAdded:"{widgetAdded}"},dirtyWidgets:{},init:function(){var c,g,w=this,d=h(".widgets-chooser"),o=d.find(".widgets-chooser-sidebars"),e=h("div.widgets-sortables"),p=!("undefined"==typeof isRtl||!isRtl);h("#widgets-right .sidebar-name").click(function(){var e=h(this),i=e.closest(".widgets-holder-wrap "),t=e.find(".handlediv");i.hasClass("closed")?(i.removeClass("closed"),t.attr("aria-expanded","true"),e.parent().sortable("refresh")):(i.addClass("closed"),t.attr("aria-expanded","false")),v.triggerHandler("wp-pin-menu")}).find(".handlediv").each(function(e){0!==e&&h(this).attr("aria-expanded","false")}),h(window).on("beforeunload.widgets",function(e){var i,t=[];if(h.each(w.dirtyWidgets,function(e,i){i&&t.push(e)}),0!==t.length)return(i=h("#widgets-right").find(".widget").filter(function(){return-1!==t.indexOf(h(this).prop("id").replace(/^widget-\d+_/,""))})).each(function(){h(this).hasClass("open")||h(this).find(".widget-title-action:first").click()}),i.first().each(function(){this.scrollIntoViewIfNeeded?this.scrollIntoViewIfNeeded():this.scrollIntoView(),h(this).find(".widget-inside :tabbable:first").focus()}),e.returnValue=wpWidgets.l10n.saveAlert,e.returnValue}),h("#widgets-left .sidebar-name").click(function(){var e=h(this).closest(".widgets-holder-wrap");e.toggleClass("closed").find(".handlediv").attr("aria-expanded",!e.hasClass("closed")),v.triggerHandler("wp-pin-menu")}),h(document.body).bind("click.widgets-toggle",function(e){var i,t,d,s,a,n,r=h(e.target),o={"z-index":100},l=r.closest(".widget").find(".widget-top button.widget-action");r.parents(".widget-top").length&&!r.parents("#available-widgets").length?(t=(i=r.closest("div.widget")).children(".widget-inside"),d=parseInt(i.find("input.widget-width").val(),10),s=i.parent().width(),n=t.find(".widget-id").val(),i.data("dirty-state-initialized")||((a=t.find(".widget-control-save")).prop("disabled",!0).val(wpWidgets.l10n.saved),t.on("input change",function(){w.dirtyWidgets[n]=!0,i.addClass("widget-dirty"),a.prop("disabled",!1).val(wpWidgets.l10n.save)}),i.data("dirty-state-initialized",!0)),t.is(":hidden")?(250<d&&s<d+30&&i.closest("div.widgets-sortables").length&&(o[i.closest("div.widget-liquid-right").length?p?"margin-right":"margin-left":p?"margin-left":"margin-right"]=s-(d+30)+"px",i.css(o)),l.attr("aria-expanded","true"),t.slideDown("fast",function(){i.addClass("open")})):(l.attr("aria-expanded","false"),t.slideUp("fast",function(){i.attr("style",""),i.removeClass("open")}))):r.hasClass("widget-control-save")?(wpWidgets.save(r.closest("div.widget"),0,1,0),e.preventDefault()):r.hasClass("widget-control-remove")?wpWidgets.save(r.closest("div.widget"),1,1,0):r.hasClass("widget-control-close")?((i=r.closest("div.widget")).removeClass("open"),l.attr("aria-expanded","false"),wpWidgets.close(i)):"inactive-widgets-control-remove"===r.attr("id")&&(wpWidgets.removeInactiveWidgets(),e.preventDefault())}),e.children(".widget").each(function(){var e=h(this);wpWidgets.appendTitle(this),e.find("p.widget-error").length&&e.find(".widget-action").trigger("click").attr("aria-expanded","true")}),h("#widget-list").children(".widget").draggable({connectToSortable:"div.widgets-sortables",handle:"> .widget-top > .widget-title",distance:2,helper:"clone",zIndex:100,containment:"#wpwrap",refreshPositions:!0,start:function(e,i){var t=h(this).find(".widgets-chooser");i.helper.find("div.widget-description").hide(),g=this.id,t.length&&(h("#wpbody-content").append(t.hide()),i.helper.find(".widgets-chooser").remove(),w.clearWidgetSelection())},stop:function(){c&&h(c).hide(),c=""}}),e.droppable({tolerance:"intersect",over:function(e){var i=h(e.target).parent();wpWidgets.hoveredSidebar&&!i.is(wpWidgets.hoveredSidebar)&&wpWidgets.closeSidebar(e),i.hasClass("closed")&&(wpWidgets.hoveredSidebar=i).removeClass("closed").find(".handlediv").attr("aria-expanded","true"),h(this).sortable("refresh")},out:function(e){wpWidgets.hoveredSidebar&&wpWidgets.closeSidebar(e)}}),e.sortable({placeholder:"widget-placeholder",items:"> .widget",handle:"> .widget-top > .widget-title",cursor:"move",distance:2,containment:"#wpwrap",tolerance:"pointer",refreshPositions:!0,start:function(e,i){var t,d=h(this),s=d.parent(),a=i.item.children(".widget-inside");"block"===a.css("display")&&(i.item.removeClass("open"),i.item.find(".widget-top button.widget-action").attr("aria-expanded","false"),a.hide(),h(this).sortable("refreshPositions")),s.hasClass("closed")||(t=i.item.hasClass("ui-draggable")?d.height():1+d.height(),d.css("min-height",t+"px"))},stop:function(e,i){var t,d,s,a,n,r,o=i.item,l=g;if(wpWidgets.hoveredSidebar=null,o.hasClass("deleting"))return wpWidgets.save(o,1,0,1),void o.remove();t=o.find("input.add_new").val(),d=o.find("input.multi_number").val(),o.attr("style","").removeClass("ui-draggable"),g="",t&&("multi"===t?(o.html(o.html().replace(/<[^<>]+>/g,function(e){return e.replace(/__i__|%i%/g,d)})),o.attr("id",l.replace("__i__",d)),d++,h("div#"+l).find("input.multi_number").val(d)):"single"===t&&(o.attr("id","new-"+l),c="div#"+l),wpWidgets.save(o,0,0,1),o.find("input.add_new").val(""),v.trigger("widget-added",[o])),(s=o.parent()).parent().hasClass("closed")&&(s.parent().removeClass("closed").find(".handlediv").attr("aria-expanded","true"),1<(a=s.children(".widget")).length&&(n=a.get(0),r=o.get(0),n.id&&r.id&&n.id!==r.id&&h(n).before(o))),t?o.find(".widget-action").trigger("click"):wpWidgets.saveOrder(s.attr("id"))},activate:function(){h(this).parent().addClass("widget-hover")},deactivate:function(){h(this).css("min-height","").parent().removeClass("widget-hover")},receive:function(e,i){var t=h(i.sender);-1<this.id.indexOf("orphaned_widgets")?t.sortable("cancel"):-1<t.attr("id").indexOf("orphaned_widgets")&&!t.children(".widget").length&&t.parents(".orphan-sidebar").slideUp(400,function(){h(this).remove()})}}).sortable("option","connectWith","div.widgets-sortables"),h("#available-widgets").droppable({tolerance:"pointer",accept:function(e){return"widget-list"!==h(e).parent().attr("id")},drop:function(e,i){i.draggable.addClass("deleting"),h("#removing-widget").hide().children("span").empty()},over:function(e,i){i.draggable.addClass("deleting"),h("div.widget-placeholder").hide(),i.draggable.hasClass("ui-sortable-helper")&&h("#removing-widget").show().children("span").html(i.draggable.find("div.widget-title").children("h3").html())},out:function(e,i){i.draggable.removeClass("deleting"),h("div.widget-placeholder").show(),h("#removing-widget").hide().children("span").empty()}}),h("#widgets-right .widgets-holder-wrap").each(function(e,i){var t=h(i),d=t.find(".sidebar-name h2").text(),s=t.find(".sidebar-name").data("add-to"),a=t.find(".widgets-sortables").attr("id"),n=h("<li>"),r=h("<button>",{type:"button","aria-pressed":"false",class:"widgets-chooser-button","aria-label":s}).text(h.trim(d));n.append(r),0===e&&(n.addClass("widgets-chooser-selected"),r.attr("aria-pressed","true")),o.append(n),n.data("sidebarId",a)}),h("#available-widgets .widget .widget-top").on("click.widgets-chooser",function(){var e=h(this).closest(".widget"),i=h(this).find(".widget-action"),t=o.find(".widgets-chooser-button");e.hasClass("widget-in-question")||h("#widgets-left").hasClass("chooser")?(i.attr("aria-expanded","false"),w.closeChooser()):(w.clearWidgetSelection(),h("#widgets-left").addClass("chooser"),e.addClass("widget-in-question").children(".widget-description").after(d),d.slideDown(300,function(){i.attr("aria-expanded","true")}),t.on("click.widgets-chooser",function(){o.find(".widgets-chooser-selected").removeClass("widgets-chooser-selected"),t.attr("aria-pressed","false"),h(this).attr("aria-pressed","true").closest("li").addClass("widgets-chooser-selected")}))}),d.on("click.widgets-chooser",function(e){var i=h(e.target);i.hasClass("button-primary")?(w.addWidget(d),w.closeChooser()):i.hasClass("widgets-chooser-cancel")&&w.closeChooser()}).on("keyup.widgets-chooser",function(e){e.which===h.ui.keyCode.ESCAPE&&w.closeChooser()})},saveOrder:function(e){var i={action:"widgets-order",savewidgets:h("#_wpnonce_widgets").val(),sidebars:[]};e&&h("#"+e).find(".spinner:first").addClass("is-active"),h("div.widgets-sortables").each(function(){h(this).sortable&&(i["sidebars["+h(this).attr("id")+"]"]=h(this).sortable("toArray").join(","))}),h.post(ajaxurl,i,function(){h("#inactive-widgets-control-remove").prop("disabled",!h("#wp_inactive_widgets .widget").length),h(".spinner").removeClass("is-active")})},save:function(t,d,s,a){var e,i,n=this,r=t.closest("div.widgets-sortables").attr("id"),o=t.find("form"),l=t.find("input.add_new").val();(d||l||!o.prop("checkValidity")||o[0].checkValidity())&&(e=o.serialize(),t=h(t),h(".spinner",t).addClass("is-active"),i={action:"save-widget",savewidgets:h("#_wpnonce_widgets").val(),sidebar:r},d&&(i.delete_widget=1),e+="&"+h.param(i),h.post(ajaxurl,e,function(e){var i=h("input.widget-id",t).val();d?(h("input.widget_number",t).val()||h("#available-widgets").find("input.widget-id").each(function(){h(this).val()===i&&h(this).closest("div.widget").show()}),s?(a=0,t.slideUp("fast",function(){h(this).remove(),wpWidgets.saveOrder(),delete n.dirtyWidgets[i]})):(t.remove(),delete n.dirtyWidgets[i],"wp_inactive_widgets"===r&&h("#inactive-widgets-control-remove").prop("disabled",!h("#wp_inactive_widgets .widget").length))):(h(".spinner").removeClass("is-active"),e&&2<e.length&&(h("div.widget-content",t).html(e),wpWidgets.appendTitle(t),t.find(".widget-control-save").prop("disabled",!0).val(wpWidgets.l10n.saved),t.removeClass("widget-dirty"),delete n.dirtyWidgets[i],v.trigger("widget-updated",[t]),"wp_inactive_widgets"===r&&h("#inactive-widgets-control-remove").prop("disabled",!h("#wp_inactive_widgets .widget").length))),a&&wpWidgets.saveOrder()}))},removeInactiveWidgets:function(){var e,i,t=h(".remove-inactive-widgets"),d=this;h(".spinner",t).addClass("is-active"),e={action:"delete-inactive-widgets",removeinactivewidgets:h("#_wpnonce_remove_inactive_widgets").val()},i=h.param(e),h.post(ajaxurl,i,function(){h("#wp_inactive_widgets .widget").each(function(){var e=h(this);delete d.dirtyWidgets[e.find("input.widget-id").val()],e.remove()}),h("#inactive-widgets-control-remove").prop("disabled",!0),h(".spinner",t).removeClass("is-active")})},appendTitle:function(e){var i=h('input[id*="-title"]',e).val()||"";i=i&&": "+i.replace(/<[^<>]+>/g,"").replace(/</g,"<").replace(/>/g,">"),h(e).children(".widget-top").children(".widget-title").children().children(".in-widget-title").html(i)},close:function(e){e.children(".widget-inside").slideUp("fast",function(){e.attr("style","").find(".widget-top button.widget-action").attr("aria-expanded","false").focus()})},addWidget:function(e){var i,t,d,s,a,n,r,o=e.find(".widgets-chooser-selected").data("sidebarId"),l=h("#"+o);t=(i=h("#available-widgets").find(".widget-in-question").clone()).attr("id"),d=i.find("input.add_new").val(),s=i.find("input.multi_number").val(),i.find(".widgets-chooser").remove(),"multi"===d?(i.html(i.html().replace(/<[^<>]+>/g,function(e){return e.replace(/__i__|%i%/g,s)})),i.attr("id",t.replace("__i__",s)),s++,h("#"+t).find("input.multi_number").val(s)):"single"===d&&(i.attr("id","new-"+t),h("#"+t).hide()),l.closest(".widgets-holder-wrap").removeClass("closed").find(".handlediv").attr("aria-expanded","true"),l.append(i),l.sortable("refresh"),wpWidgets.save(i,0,0,1),i.find("input.add_new").val(""),v.trigger("widget-added",[i]),n=(a=h(window).scrollTop())+h(window).height(),(r=l.offset()).bottom=r.top+l.outerHeight(),(a>r.bottom||n<r.top)&&h("html, body").animate({scrollTop:r.top-130},200),window.setTimeout(function(){i.find(".widget-title").trigger("click"),window.wp.a11y.speak(wpWidgets.l10n.widgetAdded,"assertive")},250)},closeChooser:function(){var e=this,i=h("#available-widgets .widget-in-question");h(".widgets-chooser").slideUp(200,function(){h("#wpbody-content").append(this),e.clearWidgetSelection(),i.find(".widget-action").attr("aria-expanded","false").focus()})},clearWidgetSelection:function(){h("#widgets-left").removeClass("chooser"),h(".widget-in-question").removeClass("widget-in-question")},closeSidebar:function(e){this.hoveredSidebar.addClass("closed").find(".handlediv").attr("aria-expanded","false"),h(e.target).css("min-height",""),this.hoveredSidebar=null}},v.ready(function(){wpWidgets.init()})}(jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/widgets/custom-html-widgets.js b/srcs/wordpress/wp-admin/js/widgets/custom-html-widgets.js deleted file mode 100644 index 93aa901..0000000 --- a/srcs/wordpress/wp-admin/js/widgets/custom-html-widgets.js +++ /dev/null @@ -1,456 +0,0 @@ -/** - * @output wp-admin/js/widgets/custom-html-widgets.js - */ - -/* global wp */ -/* eslint consistent-this: [ "error", "control" ] */ -/* eslint no-magic-numbers: ["error", { "ignore": [0,1,-1] }] */ - -/** - * @namespace wp.customHtmlWidget - * @memberOf wp - */ -wp.customHtmlWidgets = ( function( $ ) { - 'use strict'; - - var component = { - idBases: [ 'custom_html' ], - codeEditorSettings: {}, - l10n: { - errorNotice: { - singular: '', - plural: '' - } - } - }; - - component.CustomHtmlWidgetControl = Backbone.View.extend(/** @lends wp.customHtmlWidgets.CustomHtmlWidgetControl.prototype */{ - - /** - * View events. - * - * @type {Object} - */ - events: {}, - - /** - * Text widget control. - * - * @constructs wp.customHtmlWidgets.CustomHtmlWidgetControl - * @augments Backbone.View - * @abstract - * - * @param {Object} options - Options. - * @param {jQuery} options.el - Control field container element. - * @param {jQuery} options.syncContainer - Container element where fields are synced for the server. - * - * @returns {void} - */ - initialize: function initialize( options ) { - var control = this; - - if ( ! options.el ) { - throw new Error( 'Missing options.el' ); - } - if ( ! options.syncContainer ) { - throw new Error( 'Missing options.syncContainer' ); - } - - Backbone.View.prototype.initialize.call( control, options ); - control.syncContainer = options.syncContainer; - control.widgetIdBase = control.syncContainer.parent().find( '.id_base' ).val(); - control.widgetNumber = control.syncContainer.parent().find( '.widget_number' ).val(); - control.customizeSettingId = 'widget_' + control.widgetIdBase + '[' + String( control.widgetNumber ) + ']'; - - control.$el.addClass( 'custom-html-widget-fields' ); - control.$el.html( wp.template( 'widget-custom-html-control-fields' )( { codeEditorDisabled: component.codeEditorSettings.disabled } ) ); - - control.errorNoticeContainer = control.$el.find( '.code-editor-error-container' ); - control.currentErrorAnnotations = []; - control.saveButton = control.syncContainer.add( control.syncContainer.parent().find( '.widget-control-actions' ) ).find( '.widget-control-save, #savewidget' ); - control.saveButton.addClass( 'custom-html-widget-save-button' ); // To facilitate style targeting. - - control.fields = { - title: control.$el.find( '.title' ), - content: control.$el.find( '.content' ) - }; - - // Sync input fields to hidden sync fields which actually get sent to the server. - _.each( control.fields, function( fieldInput, fieldName ) { - fieldInput.on( 'input change', function updateSyncField() { - var syncInput = control.syncContainer.find( '.sync-input.' + fieldName ); - if ( syncInput.val() !== fieldInput.val() ) { - syncInput.val( fieldInput.val() ); - syncInput.trigger( 'change' ); - } - }); - - // Note that syncInput cannot be re-used because it will be destroyed with each widget-updated event. - fieldInput.val( control.syncContainer.find( '.sync-input.' + fieldName ).val() ); - }); - }, - - /** - * Update input fields from the sync fields. - * - * This function is called at the widget-updated and widget-synced events. - * A field will only be updated if it is not currently focused, to avoid - * overwriting content that the user is entering. - * - * @returns {void} - */ - updateFields: function updateFields() { - var control = this, syncInput; - - if ( ! control.fields.title.is( document.activeElement ) ) { - syncInput = control.syncContainer.find( '.sync-input.title' ); - control.fields.title.val( syncInput.val() ); - } - - /* - * Prevent updating content when the editor is focused or if there are current error annotations, - * to prevent the editor's contents from getting sanitized as soon as a user removes focus from - * the editor. This is particularly important for users who cannot unfiltered_html. - */ - control.contentUpdateBypassed = control.fields.content.is( document.activeElement ) || control.editor && control.editor.codemirror.state.focused || 0 !== control.currentErrorAnnotations.length; - if ( ! control.contentUpdateBypassed ) { - syncInput = control.syncContainer.find( '.sync-input.content' ); - control.fields.content.val( syncInput.val() ); - } - }, - - /** - * Show linting error notice. - * - * @param {Array} errorAnnotations - Error annotations. - * @returns {void} - */ - updateErrorNotice: function( errorAnnotations ) { - var control = this, errorNotice, message = '', customizeSetting; - - if ( 1 === errorAnnotations.length ) { - message = component.l10n.errorNotice.singular.replace( '%d', '1' ); - } else if ( errorAnnotations.length > 1 ) { - message = component.l10n.errorNotice.plural.replace( '%d', String( errorAnnotations.length ) ); - } - - if ( control.fields.content[0].setCustomValidity ) { - control.fields.content[0].setCustomValidity( message ); - } - - if ( wp.customize && wp.customize.has( control.customizeSettingId ) ) { - customizeSetting = wp.customize( control.customizeSettingId ); - customizeSetting.notifications.remove( 'htmlhint_error' ); - if ( 0 !== errorAnnotations.length ) { - customizeSetting.notifications.add( 'htmlhint_error', new wp.customize.Notification( 'htmlhint_error', { - message: message, - type: 'error' - } ) ); - } - } else if ( 0 !== errorAnnotations.length ) { - errorNotice = $( '<div class="inline notice notice-error notice-alt"></div>' ); - errorNotice.append( $( '<p></p>', { - text: message - } ) ); - control.errorNoticeContainer.empty(); - control.errorNoticeContainer.append( errorNotice ); - control.errorNoticeContainer.slideDown( 'fast' ); - wp.a11y.speak( message ); - } else { - control.errorNoticeContainer.slideUp( 'fast' ); - } - }, - - /** - * Initialize editor. - * - * @returns {void} - */ - initializeEditor: function initializeEditor() { - var control = this, settings; - - if ( component.codeEditorSettings.disabled ) { - return; - } - - settings = _.extend( {}, component.codeEditorSettings, { - - /** - * Handle tabbing to the field before the editor. - * - * @ignore - * - * @returns {void} - */ - onTabPrevious: function onTabPrevious() { - control.fields.title.focus(); - }, - - /** - * Handle tabbing to the field after the editor. - * - * @ignore - * - * @returns {void} - */ - onTabNext: function onTabNext() { - var tabbables = control.syncContainer.add( control.syncContainer.parent().find( '.widget-position, .widget-control-actions' ) ).find( ':tabbable' ); - tabbables.first().focus(); - }, - - /** - * Disable save button and store linting errors for use in updateFields. - * - * @ignore - * - * @param {Array} errorAnnotations - Error notifications. - * @returns {void} - */ - onChangeLintingErrors: function onChangeLintingErrors( errorAnnotations ) { - control.currentErrorAnnotations = errorAnnotations; - }, - - /** - * Update error notice. - * - * @ignore - * - * @param {Array} errorAnnotations - Error annotations. - * @returns {void} - */ - onUpdateErrorNotice: function onUpdateErrorNotice( errorAnnotations ) { - control.saveButton.toggleClass( 'validation-blocked disabled', errorAnnotations.length > 0 ); - control.updateErrorNotice( errorAnnotations ); - } - }); - - control.editor = wp.codeEditor.initialize( control.fields.content, settings ); - - // Improve the editor accessibility. - $( control.editor.codemirror.display.lineDiv ) - .attr({ - role: 'textbox', - 'aria-multiline': 'true', - 'aria-labelledby': control.fields.content[0].id + '-label', - 'aria-describedby': 'editor-keyboard-trap-help-1 editor-keyboard-trap-help-2 editor-keyboard-trap-help-3 editor-keyboard-trap-help-4' - }); - - // Focus the editor when clicking on its label. - $( '#' + control.fields.content[0].id + '-label' ).on( 'click', function() { - control.editor.codemirror.focus(); - }); - - control.fields.content.on( 'change', function() { - if ( this.value !== control.editor.codemirror.getValue() ) { - control.editor.codemirror.setValue( this.value ); - } - }); - control.editor.codemirror.on( 'change', function() { - var value = control.editor.codemirror.getValue(); - if ( value !== control.fields.content.val() ) { - control.fields.content.val( value ).trigger( 'change' ); - } - }); - - // Make sure the editor gets updated if the content was updated on the server (sanitization) but not updated in the editor since it was focused. - control.editor.codemirror.on( 'blur', function() { - if ( control.contentUpdateBypassed ) { - control.syncContainer.find( '.sync-input.content' ).trigger( 'change' ); - } - }); - - // Prevent hitting Esc from collapsing the widget control. - if ( wp.customize ) { - control.editor.codemirror.on( 'keydown', function onKeydown( codemirror, event ) { - var escKeyCode = 27; - if ( escKeyCode === event.keyCode ) { - event.stopPropagation(); - } - }); - } - } - }); - - /** - * Mapping of widget ID to instances of CustomHtmlWidgetControl subclasses. - * - * @alias wp.customHtmlWidgets.widgetControls - * - * @type {Object.<string, wp.textWidgets.CustomHtmlWidgetControl>} - */ - component.widgetControls = {}; - - /** - * Handle widget being added or initialized for the first time at the widget-added event. - * - * @alias wp.customHtmlWidgets.handleWidgetAdded - * - * @param {jQuery.Event} event - Event. - * @param {jQuery} widgetContainer - Widget container element. - * - * @returns {void} - */ - component.handleWidgetAdded = function handleWidgetAdded( event, widgetContainer ) { - var widgetForm, idBase, widgetControl, widgetId, animatedCheckDelay = 50, renderWhenAnimationDone, fieldContainer, syncContainer; - widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' ); // Note: '.form' appears in the customizer, whereas 'form' on the widgets admin screen. - - idBase = widgetForm.find( '> .id_base' ).val(); - if ( -1 === component.idBases.indexOf( idBase ) ) { - return; - } - - // Prevent initializing already-added widgets. - widgetId = widgetForm.find( '.widget-id' ).val(); - if ( component.widgetControls[ widgetId ] ) { - return; - } - - /* - * Create a container element for the widget control fields. - * This is inserted into the DOM immediately before the the .widget-content - * element because the contents of this element are essentially "managed" - * by PHP, where each widget update cause the entire element to be emptied - * and replaced with the rendered output of WP_Widget::form() which is - * sent back in Ajax request made to save/update the widget instance. - * To prevent a "flash of replaced DOM elements and re-initialized JS - * components", the JS template is rendered outside of the normal form - * container. - */ - fieldContainer = $( '<div></div>' ); - syncContainer = widgetContainer.find( '.widget-content:first' ); - syncContainer.before( fieldContainer ); - - widgetControl = new component.CustomHtmlWidgetControl({ - el: fieldContainer, - syncContainer: syncContainer - }); - - component.widgetControls[ widgetId ] = widgetControl; - - /* - * Render the widget once the widget parent's container finishes animating, - * as the widget-added event fires with a slideDown of the container. - * This ensures that the textarea is visible and the editor can be initialized. - */ - renderWhenAnimationDone = function() { - if ( ! ( wp.customize ? widgetContainer.parent().hasClass( 'expanded' ) : widgetContainer.hasClass( 'open' ) ) ) { // Core merge: The wp.customize condition can be eliminated with this change being in core: https://github.com/xwp/wordpress-develop/pull/247/commits/5322387d - setTimeout( renderWhenAnimationDone, animatedCheckDelay ); - } else { - widgetControl.initializeEditor(); - } - }; - renderWhenAnimationDone(); - }; - - /** - * Setup widget in accessibility mode. - * - * @alias wp.customHtmlWidgets.setupAccessibleMode - * - * @returns {void} - */ - component.setupAccessibleMode = function setupAccessibleMode() { - var widgetForm, idBase, widgetControl, fieldContainer, syncContainer; - widgetForm = $( '.editwidget > form' ); - if ( 0 === widgetForm.length ) { - return; - } - - idBase = widgetForm.find( '> .widget-control-actions > .id_base' ).val(); - if ( -1 === component.idBases.indexOf( idBase ) ) { - return; - } - - fieldContainer = $( '<div></div>' ); - syncContainer = widgetForm.find( '> .widget-inside' ); - syncContainer.before( fieldContainer ); - - widgetControl = new component.CustomHtmlWidgetControl({ - el: fieldContainer, - syncContainer: syncContainer - }); - - widgetControl.initializeEditor(); - }; - - /** - * Sync widget instance data sanitized from server back onto widget model. - * - * This gets called via the 'widget-updated' event when saving a widget from - * the widgets admin screen and also via the 'widget-synced' event when making - * a change to a widget in the customizer. - * - * @alias wp.customHtmlWidgets.handleWidgetUpdated - * - * @param {jQuery.Event} event - Event. - * @param {jQuery} widgetContainer - Widget container element. - * @returns {void} - */ - component.handleWidgetUpdated = function handleWidgetUpdated( event, widgetContainer ) { - var widgetForm, widgetId, widgetControl, idBase; - widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' ); - - idBase = widgetForm.find( '> .id_base' ).val(); - if ( -1 === component.idBases.indexOf( idBase ) ) { - return; - } - - widgetId = widgetForm.find( '> .widget-id' ).val(); - widgetControl = component.widgetControls[ widgetId ]; - if ( ! widgetControl ) { - return; - } - - widgetControl.updateFields(); - }; - - /** - * Initialize functionality. - * - * This function exists to prevent the JS file from having to boot itself. - * When WordPress enqueues this script, it should have an inline script - * attached which calls wp.textWidgets.init(). - * - * @alias wp.customHtmlWidgets.init - * - * @param {object} settings - Options for code editor, exported from PHP. - * - * @returns {void} - */ - component.init = function init( settings ) { - var $document = $( document ); - _.extend( component.codeEditorSettings, settings ); - - $document.on( 'widget-added', component.handleWidgetAdded ); - $document.on( 'widget-synced widget-updated', component.handleWidgetUpdated ); - - /* - * Manually trigger widget-added events for media widgets on the admin - * screen once they are expanded. The widget-added event is not triggered - * for each pre-existing widget on the widgets admin screen like it is - * on the customizer. Likewise, the customizer only triggers widget-added - * when the widget is expanded to just-in-time construct the widget form - * when it is actually going to be displayed. So the following implements - * the same for the widgets admin screen, to invoke the widget-added - * handler when a pre-existing media widget is expanded. - */ - $( function initializeExistingWidgetContainers() { - var widgetContainers; - if ( 'widgets' !== window.pagenow ) { - return; - } - widgetContainers = $( '.widgets-holder-wrap:not(#available-widgets)' ).find( 'div.widget' ); - widgetContainers.one( 'click.toggle-widget-expanded', function toggleWidgetExpanded() { - var widgetContainer = $( this ); - component.handleWidgetAdded( new jQuery.Event( 'widget-added' ), widgetContainer ); - }); - - // Accessibility mode. - $( window ).on( 'load', function() { - component.setupAccessibleMode(); - }); - }); - }; - - return component; -})( jQuery ); diff --git a/srcs/wordpress/wp-admin/js/widgets/custom-html-widgets.min.js b/srcs/wordpress/wp-admin/js/widgets/custom-html-widgets.min.js deleted file mode 100644 index 4fcc0c0..0000000 --- a/srcs/wordpress/wp-admin/js/widgets/custom-html-widgets.min.js +++ /dev/null @@ -1 +0,0 @@ -wp.customHtmlWidgets=function(l){"use strict";var c={idBases:["custom_html"],codeEditorSettings:{},l10n:{errorNotice:{singular:"",plural:""}}};return c.CustomHtmlWidgetControl=Backbone.View.extend({events:{},initialize:function(e){var n=this;if(!e.el)throw new Error("Missing options.el");if(!e.syncContainer)throw new Error("Missing options.syncContainer");Backbone.View.prototype.initialize.call(n,e),n.syncContainer=e.syncContainer,n.widgetIdBase=n.syncContainer.parent().find(".id_base").val(),n.widgetNumber=n.syncContainer.parent().find(".widget_number").val(),n.customizeSettingId="widget_"+n.widgetIdBase+"["+String(n.widgetNumber)+"]",n.$el.addClass("custom-html-widget-fields"),n.$el.html(wp.template("widget-custom-html-control-fields")({codeEditorDisabled:c.codeEditorSettings.disabled})),n.errorNoticeContainer=n.$el.find(".code-editor-error-container"),n.currentErrorAnnotations=[],n.saveButton=n.syncContainer.add(n.syncContainer.parent().find(".widget-control-actions")).find(".widget-control-save, #savewidget"),n.saveButton.addClass("custom-html-widget-save-button"),n.fields={title:n.$el.find(".title"),content:n.$el.find(".content")},_.each(n.fields,function(t,i){t.on("input change",function(){var e=n.syncContainer.find(".sync-input."+i);e.val()!==t.val()&&(e.val(t.val()),e.trigger("change"))}),t.val(n.syncContainer.find(".sync-input."+i).val())})},updateFields:function(){var e,t=this;t.fields.title.is(document.activeElement)||(e=t.syncContainer.find(".sync-input.title"),t.fields.title.val(e.val())),t.contentUpdateBypassed=t.fields.content.is(document.activeElement)||t.editor&&t.editor.codemirror.state.focused||0!==t.currentErrorAnnotations.length,t.contentUpdateBypassed||(e=t.syncContainer.find(".sync-input.content"),t.fields.content.val(e.val()))},updateErrorNotice:function(e){var t,i,n=this,o="";1===e.length?o=c.l10n.errorNotice.singular.replace("%d","1"):1<e.length&&(o=c.l10n.errorNotice.plural.replace("%d",String(e.length))),n.fields.content[0].setCustomValidity&&n.fields.content[0].setCustomValidity(o),wp.customize&&wp.customize.has(n.customizeSettingId)?((i=wp.customize(n.customizeSettingId)).notifications.remove("htmlhint_error"),0!==e.length&&i.notifications.add("htmlhint_error",new wp.customize.Notification("htmlhint_error",{message:o,type:"error"}))):0!==e.length?((t=l('<div class="inline notice notice-error notice-alt"></div>')).append(l("<p></p>",{text:o})),n.errorNoticeContainer.empty(),n.errorNoticeContainer.append(t),n.errorNoticeContainer.slideDown("fast"),wp.a11y.speak(o)):n.errorNoticeContainer.slideUp("fast")},initializeEditor:function(){var e,t=this;c.codeEditorSettings.disabled||(e=_.extend({},c.codeEditorSettings,{onTabPrevious:function(){t.fields.title.focus()},onTabNext:function(){t.syncContainer.add(t.syncContainer.parent().find(".widget-position, .widget-control-actions")).find(":tabbable").first().focus()},onChangeLintingErrors:function(e){t.currentErrorAnnotations=e},onUpdateErrorNotice:function(e){t.saveButton.toggleClass("validation-blocked disabled",0<e.length),t.updateErrorNotice(e)}}),t.editor=wp.codeEditor.initialize(t.fields.content,e),l(t.editor.codemirror.display.lineDiv).attr({role:"textbox","aria-multiline":"true","aria-labelledby":t.fields.content[0].id+"-label","aria-describedby":"editor-keyboard-trap-help-1 editor-keyboard-trap-help-2 editor-keyboard-trap-help-3 editor-keyboard-trap-help-4"}),l("#"+t.fields.content[0].id+"-label").on("click",function(){t.editor.codemirror.focus()}),t.fields.content.on("change",function(){this.value!==t.editor.codemirror.getValue()&&t.editor.codemirror.setValue(this.value)}),t.editor.codemirror.on("change",function(){var e=t.editor.codemirror.getValue();e!==t.fields.content.val()&&t.fields.content.val(e).trigger("change")}),t.editor.codemirror.on("blur",function(){t.contentUpdateBypassed&&t.syncContainer.find(".sync-input.content").trigger("change")}),wp.customize&&t.editor.codemirror.on("keydown",function(e,t){27===t.keyCode&&t.stopPropagation()}))}}),c.widgetControls={},c.handleWidgetAdded=function(e,t){var i,n,o,d,r,a,s;n=(i=t.find("> .widget-inside > .form, > .widget-inside > form")).find("> .id_base").val(),-1!==c.idBases.indexOf(n)&&(d=i.find(".widget-id").val(),c.widgetControls[d]||(a=l("<div></div>"),(s=t.find(".widget-content:first")).before(a),o=new c.CustomHtmlWidgetControl({el:a,syncContainer:s}),c.widgetControls[d]=o,(r=function(){(wp.customize?t.parent().hasClass("expanded"):t.hasClass("open"))?o.initializeEditor():setTimeout(r,50)})()))},c.setupAccessibleMode=function(){var e,t,i,n;0!==(e=l(".editwidget > form")).length&&(t=e.find("> .widget-control-actions > .id_base").val(),-1!==c.idBases.indexOf(t)&&(i=l("<div></div>"),(n=e.find("> .widget-inside")).before(i),new c.CustomHtmlWidgetControl({el:i,syncContainer:n}).initializeEditor()))},c.handleWidgetUpdated=function(e,t){var i,n,o,d;d=(i=t.find("> .widget-inside > .form, > .widget-inside > form")).find("> .id_base").val(),-1!==c.idBases.indexOf(d)&&(n=i.find("> .widget-id").val(),(o=c.widgetControls[n])&&o.updateFields())},c.init=function(e){var t=l(document);_.extend(c.codeEditorSettings,e),t.on("widget-added",c.handleWidgetAdded),t.on("widget-synced widget-updated",c.handleWidgetUpdated),l(function(){"widgets"===window.pagenow&&(l(".widgets-holder-wrap:not(#available-widgets)").find("div.widget").one("click.toggle-widget-expanded",function(){var e=l(this);c.handleWidgetAdded(new jQuery.Event("widget-added"),e)}),l(window).on("load",function(){c.setupAccessibleMode()}))})},c}(jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/widgets/media-audio-widget.js b/srcs/wordpress/wp-admin/js/widgets/media-audio-widget.js deleted file mode 100644 index e050c30..0000000 --- a/srcs/wordpress/wp-admin/js/widgets/media-audio-widget.js +++ /dev/null @@ -1,154 +0,0 @@ -/** - * @output wp-admin/js/widgets/media-audio-widget.js - */ - -/* eslint consistent-this: [ "error", "control" ] */ -(function( component ) { - 'use strict'; - - var AudioWidgetModel, AudioWidgetControl, AudioDetailsMediaFrame; - - /** - * Custom audio details frame that removes the replace-audio state. - * - * @class wp.mediaWidgets.controlConstructors~AudioDetailsMediaFrame - * @augments wp.media.view.MediaFrame.AudioDetails - */ - AudioDetailsMediaFrame = wp.media.view.MediaFrame.AudioDetails.extend(/** @lends wp.mediaWidgets.controlConstructors~AudioDetailsMediaFrame.prototype */{ - - /** - * Create the default states. - * - * @returns {void} - */ - createStates: function createStates() { - this.states.add([ - new wp.media.controller.AudioDetails({ - media: this.media - }), - - new wp.media.controller.MediaLibrary({ - type: 'audio', - id: 'add-audio-source', - title: wp.media.view.l10n.audioAddSourceTitle, - toolbar: 'add-audio-source', - media: this.media, - menu: false - }) - ]); - } - }); - - /** - * Audio widget model. - * - * See WP_Widget_Audio::enqueue_admin_scripts() for amending prototype from PHP exports. - * - * @class wp.mediaWidgets.modelConstructors.media_audio - * @augments wp.mediaWidgets.MediaWidgetModel - */ - AudioWidgetModel = component.MediaWidgetModel.extend({}); - - /** - * Audio widget control. - * - * See WP_Widget_Audio::enqueue_admin_scripts() for amending prototype from PHP exports. - * - * @class wp.mediaWidgets.controlConstructors.media_audio - * @augments wp.mediaWidgets.MediaWidgetControl - */ - AudioWidgetControl = component.MediaWidgetControl.extend(/** @lends wp.mediaWidgets.controlConstructors.media_audio.prototype */{ - - /** - * Show display settings. - * - * @type {boolean} - */ - showDisplaySettings: false, - - /** - * Map model props to media frame props. - * - * @param {Object} modelProps - Model props. - * @returns {Object} Media frame props. - */ - mapModelToMediaFrameProps: function mapModelToMediaFrameProps( modelProps ) { - var control = this, mediaFrameProps; - mediaFrameProps = component.MediaWidgetControl.prototype.mapModelToMediaFrameProps.call( control, modelProps ); - mediaFrameProps.link = 'embed'; - return mediaFrameProps; - }, - - /** - * Render preview. - * - * @returns {void} - */ - renderPreview: function renderPreview() { - var control = this, previewContainer, previewTemplate, attachmentId, attachmentUrl; - attachmentId = control.model.get( 'attachment_id' ); - attachmentUrl = control.model.get( 'url' ); - - if ( ! attachmentId && ! attachmentUrl ) { - return; - } - - previewContainer = control.$el.find( '.media-widget-preview' ); - previewTemplate = wp.template( 'wp-media-widget-audio-preview' ); - - previewContainer.html( previewTemplate({ - model: { - attachment_id: control.model.get( 'attachment_id' ), - src: attachmentUrl - }, - error: control.model.get( 'error' ) - })); - wp.mediaelement.initialize(); - }, - - /** - * Open the media audio-edit frame to modify the selected item. - * - * @returns {void} - */ - editMedia: function editMedia() { - var control = this, mediaFrame, metadata, updateCallback; - - metadata = control.mapModelToMediaFrameProps( control.model.toJSON() ); - - // Set up the media frame. - mediaFrame = new AudioDetailsMediaFrame({ - frame: 'audio', - state: 'audio-details', - metadata: metadata - }); - wp.media.frame = mediaFrame; - mediaFrame.$el.addClass( 'media-widget' ); - - updateCallback = function( mediaFrameProps ) { - - // Update cached attachment object to avoid having to re-fetch. This also triggers re-rendering of preview. - control.selectedAttachment.set( mediaFrameProps ); - - control.model.set( _.extend( - control.model.defaults(), - control.mapMediaToModelProps( mediaFrameProps ), - { error: false } - ) ); - }; - - mediaFrame.state( 'audio-details' ).on( 'update', updateCallback ); - mediaFrame.state( 'replace-audio' ).on( 'replace', updateCallback ); - mediaFrame.on( 'close', function() { - mediaFrame.detach(); - }); - - mediaFrame.open(); - } - }); - - // Exports. - component.controlConstructors.media_audio = AudioWidgetControl; - component.modelConstructors.media_audio = AudioWidgetModel; - -})( wp.mediaWidgets ); diff --git a/srcs/wordpress/wp-admin/js/widgets/media-audio-widget.min.js b/srcs/wordpress/wp-admin/js/widgets/media-audio-widget.min.js deleted file mode 100644 index d1c44fc..0000000 --- a/srcs/wordpress/wp-admin/js/widgets/media-audio-widget.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(d){"use strict";var e,t,i;i=wp.media.view.MediaFrame.AudioDetails.extend({createStates:function(){this.states.add([new wp.media.controller.AudioDetails({media:this.media}),new wp.media.controller.MediaLibrary({type:"audio",id:"add-audio-source",title:wp.media.view.l10n.audioAddSourceTitle,toolbar:"add-audio-source",media:this.media,menu:!1})])}}),e=d.MediaWidgetModel.extend({}),t=d.MediaWidgetControl.extend({showDisplaySettings:!1,mapModelToMediaFrameProps:function(e){var t;return(t=d.MediaWidgetControl.prototype.mapModelToMediaFrameProps.call(this,e)).link="embed",t},renderPreview:function(){var e,t,d,a,i=this;d=i.model.get("attachment_id"),a=i.model.get("url"),(d||a)&&(e=i.$el.find(".media-widget-preview"),t=wp.template("wp-media-widget-audio-preview"),e.html(t({model:{attachment_id:i.model.get("attachment_id"),src:a},error:i.model.get("error")})),wp.mediaelement.initialize())},editMedia:function(){var e,t,d,a=this;t=a.mapModelToMediaFrameProps(a.model.toJSON()),e=new i({frame:"audio",state:"audio-details",metadata:t}),(wp.media.frame=e).$el.addClass("media-widget"),d=function(e){a.selectedAttachment.set(e),a.model.set(_.extend(a.model.defaults(),a.mapMediaToModelProps(e),{error:!1}))},e.state("audio-details").on("update",d),e.state("replace-audio").on("replace",d),e.on("close",function(){e.detach()}),e.open()}}),d.controlConstructors.media_audio=t,d.modelConstructors.media_audio=e}(wp.mediaWidgets);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/widgets/media-gallery-widget.js b/srcs/wordpress/wp-admin/js/widgets/media-gallery-widget.js deleted file mode 100644 index 45671e7..0000000 --- a/srcs/wordpress/wp-admin/js/widgets/media-gallery-widget.js +++ /dev/null @@ -1,341 +0,0 @@ -/** - * @output wp-admin/js/widgets/media-gallery-widget.js - */ - -/* eslint consistent-this: [ "error", "control" ] */ -(function( component ) { - 'use strict'; - - var GalleryWidgetModel, GalleryWidgetControl, GalleryDetailsMediaFrame; - - /** - * Custom gallery details frame. - * - * @since 4.9.0 - * @class wp.mediaWidgets~GalleryDetailsMediaFrame - * @augments wp.media.view.MediaFrame.Post - */ - GalleryDetailsMediaFrame = wp.media.view.MediaFrame.Post.extend(/** @lends wp.mediaWidgets~GalleryDetailsMediaFrame.prototype */{ - - /** - * Create the default states. - * - * @since 4.9.0 - * @returns {void} - */ - createStates: function createStates() { - this.states.add([ - new wp.media.controller.Library({ - id: 'gallery', - title: wp.media.view.l10n.createGalleryTitle, - priority: 40, - toolbar: 'main-gallery', - filterable: 'uploaded', - multiple: 'add', - editable: true, - - library: wp.media.query( _.defaults({ - type: 'image' - }, this.options.library ) ) - }), - - // Gallery states. - new wp.media.controller.GalleryEdit({ - library: this.options.selection, - editing: this.options.editing, - menu: 'gallery' - }), - - new wp.media.controller.GalleryAdd() - ]); - } - } ); - - /** - * Gallery widget model. - * - * See WP_Widget_Gallery::enqueue_admin_scripts() for amending prototype from PHP exports. - * - * @since 4.9.0 - * - * @class wp.mediaWidgets.modelConstructors.media_gallery - * @augments wp.mediaWidgets.MediaWidgetModel - */ - GalleryWidgetModel = component.MediaWidgetModel.extend(/** @lends wp.mediaWidgets.modelConstructors.media_gallery.prototype */{} ); - - GalleryWidgetControl = component.MediaWidgetControl.extend(/** @lends wp.mediaWidgets.controlConstructors.media_gallery.prototype */{ - - /** - * View events. - * - * @since 4.9.0 - * @type {object} - */ - events: _.extend( {}, component.MediaWidgetControl.prototype.events, { - 'click .media-widget-gallery-preview': 'editMedia' - } ), - - /** - * Gallery widget control. - * - * See WP_Widget_Gallery::enqueue_admin_scripts() for amending prototype from PHP exports. - * - * @constructs wp.mediaWidgets.controlConstructors.media_gallery - * @augments wp.mediaWidgets.MediaWidgetControl - * - * @since 4.9.0 - * @param {Object} options - Options. - * @param {Backbone.Model} options.model - Model. - * @param {jQuery} options.el - Control field container element. - * @param {jQuery} options.syncContainer - Container element where fields are synced for the server. - * @returns {void} - */ - initialize: function initialize( options ) { - var control = this; - - component.MediaWidgetControl.prototype.initialize.call( control, options ); - - _.bindAll( control, 'updateSelectedAttachments', 'handleAttachmentDestroy' ); - control.selectedAttachments = new wp.media.model.Attachments(); - control.model.on( 'change:ids', control.updateSelectedAttachments ); - control.selectedAttachments.on( 'change', control.renderPreview ); - control.selectedAttachments.on( 'reset', control.renderPreview ); - control.updateSelectedAttachments(); - - /* - * Refresh a Gallery widget partial when the user modifies one of the selected attachments. - * This ensures that when an attachment's caption is updated in the media modal the Gallery - * widget in the preview will then be refreshed to show the change. Normally doing this - * would not be necessary because all of the state should be contained inside the changeset, - * as everything done in the Customizer should not make a change to the site unless the - * changeset itself is published. Attachments are a current exception to this rule. - * For a proposal to include attachments in the customized state, see #37887. - */ - if ( wp.customize && wp.customize.previewer ) { - control.selectedAttachments.on( 'change', function() { - wp.customize.previewer.send( 'refresh-widget-partial', control.model.get( 'widget_id' ) ); - } ); - } - }, - - /** - * Update the selected attachments if necessary. - * - * @since 4.9.0 - * @returns {void} - */ - updateSelectedAttachments: function updateSelectedAttachments() { - var control = this, newIds, oldIds, removedIds, addedIds, addedQuery; - - newIds = control.model.get( 'ids' ); - oldIds = _.pluck( control.selectedAttachments.models, 'id' ); - - removedIds = _.difference( oldIds, newIds ); - _.each( removedIds, function( removedId ) { - control.selectedAttachments.remove( control.selectedAttachments.get( removedId ) ); - }); - - addedIds = _.difference( newIds, oldIds ); - if ( addedIds.length ) { - addedQuery = wp.media.query({ - order: 'ASC', - orderby: 'post__in', - perPage: -1, - post__in: newIds, - query: true, - type: 'image' - }); - addedQuery.more().done( function() { - control.selectedAttachments.reset( addedQuery.models ); - }); - } - }, - - /** - * Render preview. - * - * @since 4.9.0 - * @returns {void} - */ - renderPreview: function renderPreview() { - var control = this, previewContainer, previewTemplate, data; - - previewContainer = control.$el.find( '.media-widget-preview' ); - previewTemplate = wp.template( 'wp-media-widget-gallery-preview' ); - - data = control.previewTemplateProps.toJSON(); - data.attachments = {}; - control.selectedAttachments.each( function( attachment ) { - data.attachments[ attachment.id ] = attachment.toJSON(); - } ); - - previewContainer.html( previewTemplate( data ) ); - }, - - /** - * Determine whether there are selected attachments. - * - * @since 4.9.0 - * @returns {boolean} Selected. - */ - isSelected: function isSelected() { - var control = this; - - if ( control.model.get( 'error' ) ) { - return false; - } - - return control.model.get( 'ids' ).length > 0; - }, - - /** - * Open the media select frame to edit images. - * - * @since 4.9.0 - * @returns {void} - */ - editMedia: function editMedia() { - var control = this, selection, mediaFrame, mediaFrameProps; - - selection = new wp.media.model.Selection( control.selectedAttachments.models, { - multiple: true - }); - - mediaFrameProps = control.mapModelToMediaFrameProps( control.model.toJSON() ); - selection.gallery = new Backbone.Model( mediaFrameProps ); - if ( mediaFrameProps.size ) { - control.displaySettings.set( 'size', mediaFrameProps.size ); - } - mediaFrame = new GalleryDetailsMediaFrame({ - frame: 'manage', - text: control.l10n.add_to_widget, - selection: selection, - mimeType: control.mime_type, - selectedDisplaySettings: control.displaySettings, - showDisplaySettings: control.showDisplaySettings, - metadata: mediaFrameProps, - editing: true, - multiple: true, - state: 'gallery-edit' - }); - wp.media.frame = mediaFrame; // See wp.media(). - - // Handle selection of a media item. - mediaFrame.on( 'update', function onUpdate( newSelection ) { - var state = mediaFrame.state(), resultSelection; - - resultSelection = newSelection || state.get( 'selection' ); - if ( ! resultSelection ) { - return; - } - - // Copy orderby_random from gallery state. - if ( resultSelection.gallery ) { - control.model.set( control.mapMediaToModelProps( resultSelection.gallery.toJSON() ) ); - } - - // Directly update selectedAttachments to prevent needing to do additional request. - control.selectedAttachments.reset( resultSelection.models ); - - // Update models in the widget instance. - control.model.set( { - ids: _.pluck( resultSelection.models, 'id' ) - } ); - } ); - - mediaFrame.$el.addClass( 'media-widget' ); - mediaFrame.open(); - - if ( selection ) { - selection.on( 'destroy', control.handleAttachmentDestroy ); - } - }, - - /** - * Open the media select frame to chose an item. - * - * @since 4.9.0 - * @returns {void} - */ - selectMedia: function selectMedia() { - var control = this, selection, mediaFrame, mediaFrameProps; - selection = new wp.media.model.Selection( control.selectedAttachments.models, { - multiple: true - }); - - mediaFrameProps = control.mapModelToMediaFrameProps( control.model.toJSON() ); - if ( mediaFrameProps.size ) { - control.displaySettings.set( 'size', mediaFrameProps.size ); - } - mediaFrame = new GalleryDetailsMediaFrame({ - frame: 'select', - text: control.l10n.add_to_widget, - selection: selection, - mimeType: control.mime_type, - selectedDisplaySettings: control.displaySettings, - showDisplaySettings: control.showDisplaySettings, - metadata: mediaFrameProps, - state: 'gallery' - }); - wp.media.frame = mediaFrame; // See wp.media(). - - // Handle selection of a media item. - mediaFrame.on( 'update', function onUpdate( newSelection ) { - var state = mediaFrame.state(), resultSelection; - - resultSelection = newSelection || state.get( 'selection' ); - if ( ! resultSelection ) { - return; - } - - // Copy orderby_random from gallery state. - if ( resultSelection.gallery ) { - control.model.set( control.mapMediaToModelProps( resultSelection.gallery.toJSON() ) ); - } - - // Directly update selectedAttachments to prevent needing to do additional request. - control.selectedAttachments.reset( resultSelection.models ); - - // Update widget instance. - control.model.set( { - ids: _.pluck( resultSelection.models, 'id' ) - } ); - } ); - - mediaFrame.$el.addClass( 'media-widget' ); - mediaFrame.open(); - - if ( selection ) { - selection.on( 'destroy', control.handleAttachmentDestroy ); - } - - /* - * Make sure focus is set inside of modal so that hitting Esc will close - * the modal and not inadvertently cause the widget to collapse in the customizer. - */ - mediaFrame.$el.find( ':focusable:first' ).focus(); - }, - - /** - * Clear the selected attachment when it is deleted in the media select frame. - * - * @since 4.9.0 - * @param {wp.media.models.Attachment} attachment - Attachment. - * @returns {void} - */ - handleAttachmentDestroy: function handleAttachmentDestroy( attachment ) { - var control = this; - control.model.set( { - ids: _.difference( - control.model.get( 'ids' ), - [ attachment.id ] - ) - } ); - } - } ); - - // Exports. - component.controlConstructors.media_gallery = GalleryWidgetControl; - component.modelConstructors.media_gallery = GalleryWidgetModel; - -})( wp.mediaWidgets ); diff --git a/srcs/wordpress/wp-admin/js/widgets/media-gallery-widget.min.js b/srcs/wordpress/wp-admin/js/widgets/media-gallery-widget.min.js deleted file mode 100644 index 9ef0d05..0000000 --- a/srcs/wordpress/wp-admin/js/widgets/media-gallery-widget.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(i){"use strict";var e,t,l;l=wp.media.view.MediaFrame.Post.extend({createStates:function(){this.states.add([new wp.media.controller.Library({id:"gallery",title:wp.media.view.l10n.createGalleryTitle,priority:40,toolbar:"main-gallery",filterable:"uploaded",multiple:"add",editable:!0,library:wp.media.query(_.defaults({type:"image"},this.options.library))}),new wp.media.controller.GalleryEdit({library:this.options.selection,editing:this.options.editing,menu:"gallery"}),new wp.media.controller.GalleryAdd])}}),e=i.MediaWidgetModel.extend({}),t=i.MediaWidgetControl.extend({events:_.extend({},i.MediaWidgetControl.prototype.events,{"click .media-widget-gallery-preview":"editMedia"}),initialize:function(e){var t=this;i.MediaWidgetControl.prototype.initialize.call(t,e),_.bindAll(t,"updateSelectedAttachments","handleAttachmentDestroy"),t.selectedAttachments=new wp.media.model.Attachments,t.model.on("change:ids",t.updateSelectedAttachments),t.selectedAttachments.on("change",t.renderPreview),t.selectedAttachments.on("reset",t.renderPreview),t.updateSelectedAttachments(),wp.customize&&wp.customize.previewer&&t.selectedAttachments.on("change",function(){wp.customize.previewer.send("refresh-widget-partial",t.model.get("widget_id"))})},updateSelectedAttachments:function(){var e,t,i,d,a=this;e=a.model.get("ids"),t=_.pluck(a.selectedAttachments.models,"id"),i=_.difference(t,e),_.each(i,function(e){a.selectedAttachments.remove(a.selectedAttachments.get(e))}),_.difference(e,t).length&&(d=wp.media.query({order:"ASC",orderby:"post__in",perPage:-1,post__in:e,query:!0,type:"image"})).more().done(function(){a.selectedAttachments.reset(d.models)})},renderPreview:function(){var e,t,i,d=this;e=d.$el.find(".media-widget-preview"),t=wp.template("wp-media-widget-gallery-preview"),(i=d.previewTemplateProps.toJSON()).attachments={},d.selectedAttachments.each(function(e){i.attachments[e.id]=e.toJSON()}),e.html(t(i))},isSelected:function(){return!this.model.get("error")&&0<this.model.get("ids").length},editMedia:function(){var e,d,t,a=this;e=new wp.media.model.Selection(a.selectedAttachments.models,{multiple:!0}),t=a.mapModelToMediaFrameProps(a.model.toJSON()),e.gallery=new Backbone.Model(t),t.size&&a.displaySettings.set("size",t.size),d=new l({frame:"manage",text:a.l10n.add_to_widget,selection:e,mimeType:a.mime_type,selectedDisplaySettings:a.displaySettings,showDisplaySettings:a.showDisplaySettings,metadata:t,editing:!0,multiple:!0,state:"gallery-edit"}),(wp.media.frame=d).on("update",function(e){var t,i=d.state();(t=e||i.get("selection"))&&(t.gallery&&a.model.set(a.mapMediaToModelProps(t.gallery.toJSON())),a.selectedAttachments.reset(t.models),a.model.set({ids:_.pluck(t.models,"id")}))}),d.$el.addClass("media-widget"),d.open(),e&&e.on("destroy",a.handleAttachmentDestroy)},selectMedia:function(){var e,d,t,a=this;e=new wp.media.model.Selection(a.selectedAttachments.models,{multiple:!0}),(t=a.mapModelToMediaFrameProps(a.model.toJSON())).size&&a.displaySettings.set("size",t.size),d=new l({frame:"select",text:a.l10n.add_to_widget,selection:e,mimeType:a.mime_type,selectedDisplaySettings:a.displaySettings,showDisplaySettings:a.showDisplaySettings,metadata:t,state:"gallery"}),(wp.media.frame=d).on("update",function(e){var t,i=d.state();(t=e||i.get("selection"))&&(t.gallery&&a.model.set(a.mapMediaToModelProps(t.gallery.toJSON())),a.selectedAttachments.reset(t.models),a.model.set({ids:_.pluck(t.models,"id")}))}),d.$el.addClass("media-widget"),d.open(),e&&e.on("destroy",a.handleAttachmentDestroy),d.$el.find(":focusable:first").focus()},handleAttachmentDestroy:function(e){this.model.set({ids:_.difference(this.model.get("ids"),[e.id])})}}),i.controlConstructors.media_gallery=t,i.modelConstructors.media_gallery=e}(wp.mediaWidgets);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/widgets/media-image-widget.js b/srcs/wordpress/wp-admin/js/widgets/media-image-widget.js deleted file mode 100644 index 3ea4f9b..0000000 --- a/srcs/wordpress/wp-admin/js/widgets/media-image-widget.js +++ /dev/null @@ -1,170 +0,0 @@ -/** - * @output wp-admin/js/widgets/media-image-widget.js - */ - -/* eslint consistent-this: [ "error", "control" ] */ -(function( component, $ ) { - 'use strict'; - - var ImageWidgetModel, ImageWidgetControl; - - /** - * Image widget model. - * - * See WP_Widget_Media_Image::enqueue_admin_scripts() for amending prototype from PHP exports. - * - * @class wp.mediaWidgets.modelConstructors.media_image - * @augments wp.mediaWidgets.MediaWidgetModel - */ - ImageWidgetModel = component.MediaWidgetModel.extend({}); - - /** - * Image widget control. - * - * See WP_Widget_Media_Image::enqueue_admin_scripts() for amending prototype from PHP exports. - * - * @class wp.mediaWidgets.controlConstructors.media_audio - * @augments wp.mediaWidgets.MediaWidgetControl - */ - ImageWidgetControl = component.MediaWidgetControl.extend(/** @lends wp.mediaWidgets.controlConstructors.media_image.prototype */{ - - /** - * View events. - * - * @type {object} - */ - events: _.extend( {}, component.MediaWidgetControl.prototype.events, { - 'click .media-widget-preview.populated': 'editMedia' - } ), - - /** - * Render preview. - * - * @returns {void} - */ - renderPreview: function renderPreview() { - var control = this, previewContainer, previewTemplate, fieldsContainer, fieldsTemplate, linkInput; - if ( ! control.model.get( 'attachment_id' ) && ! control.model.get( 'url' ) ) { - return; - } - - previewContainer = control.$el.find( '.media-widget-preview' ); - previewTemplate = wp.template( 'wp-media-widget-image-preview' ); - previewContainer.html( previewTemplate( control.previewTemplateProps.toJSON() ) ); - previewContainer.addClass( 'populated' ); - - linkInput = control.$el.find( '.link' ); - if ( ! linkInput.is( document.activeElement ) ) { - fieldsContainer = control.$el.find( '.media-widget-fields' ); - fieldsTemplate = wp.template( 'wp-media-widget-image-fields' ); - fieldsContainer.html( fieldsTemplate( control.previewTemplateProps.toJSON() ) ); - } - }, - - /** - * Open the media image-edit frame to modify the selected item. - * - * @returns {void} - */ - editMedia: function editMedia() { - var control = this, mediaFrame, updateCallback, defaultSync, metadata; - - metadata = control.mapModelToMediaFrameProps( control.model.toJSON() ); - - // Needed or else none will not be selected if linkUrl is not also empty. - if ( 'none' === metadata.link ) { - metadata.linkUrl = ''; - } - - // Set up the media frame. - mediaFrame = wp.media({ - frame: 'image', - state: 'image-details', - metadata: metadata - }); - mediaFrame.$el.addClass( 'media-widget' ); - - updateCallback = function() { - var mediaProps, linkType; - - // Update cached attachment object to avoid having to re-fetch. This also triggers re-rendering of preview. - mediaProps = mediaFrame.state().attributes.image.toJSON(); - linkType = mediaProps.link; - mediaProps.link = mediaProps.linkUrl; - control.selectedAttachment.set( mediaProps ); - control.displaySettings.set( 'link', linkType ); - - control.model.set( _.extend( - control.mapMediaToModelProps( mediaProps ), - { error: false } - ) ); - }; - - mediaFrame.state( 'image-details' ).on( 'update', updateCallback ); - mediaFrame.state( 'replace-image' ).on( 'replace', updateCallback ); - - // Disable syncing of attachment changes back to server. See <https://core.trac.wordpress.org/ticket/40403>. - defaultSync = wp.media.model.Attachment.prototype.sync; - wp.media.model.Attachment.prototype.sync = function rejectedSync() { - return $.Deferred().rejectWith( this ).promise(); - }; - mediaFrame.on( 'close', function onClose() { - mediaFrame.detach(); - wp.media.model.Attachment.prototype.sync = defaultSync; - }); - - mediaFrame.open(); - }, - - /** - * Get props which are merged on top of the model when an embed is chosen (as opposed to an attachment). - * - * @returns {Object} Reset/override props. - */ - getEmbedResetProps: function getEmbedResetProps() { - return _.extend( - component.MediaWidgetControl.prototype.getEmbedResetProps.call( this ), - { - size: 'full', - width: 0, - height: 0 - } - ); - }, - - /** - * Get the instance props from the media selection frame. - * - * Prevent the image_title attribute from being initially set when adding an image from the media library. - * - * @param {wp.media.view.MediaFrame.Select} mediaFrame - Select frame. - * @returns {Object} Props. - */ - getModelPropsFromMediaFrame: function getModelPropsFromMediaFrame( mediaFrame ) { - var control = this; - return _.omit( - component.MediaWidgetControl.prototype.getModelPropsFromMediaFrame.call( control, mediaFrame ), - 'image_title' - ); - }, - - /** - * Map model props to preview template props. - * - * @returns {Object} Preview template props. - */ - mapModelToPreviewTemplateProps: function mapModelToPreviewTemplateProps() { - var control = this, previewTemplateProps, url; - url = control.model.get( 'url' ); - previewTemplateProps = component.MediaWidgetControl.prototype.mapModelToPreviewTemplateProps.call( control ); - previewTemplateProps.currentFilename = url ? url.replace( /\?.*$/, '' ).replace( /^.+\//, '' ) : ''; - previewTemplateProps.link_url = control.model.get( 'link_url' ); - return previewTemplateProps; - } - }); - - // Exports. - component.controlConstructors.media_image = ImageWidgetControl; - component.modelConstructors.media_image = ImageWidgetModel; - -})( wp.mediaWidgets, jQuery ); diff --git a/srcs/wordpress/wp-admin/js/widgets/media-image-widget.min.js b/srcs/wordpress/wp-admin/js/widgets/media-image-widget.min.js deleted file mode 100644 index c5165c3..0000000 --- a/srcs/wordpress/wp-admin/js/widgets/media-image-widget.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(a,d){"use strict";var e,t;e=a.MediaWidgetModel.extend({}),t=a.MediaWidgetControl.extend({events:_.extend({},a.MediaWidgetControl.prototype.events,{"click .media-widget-preview.populated":"editMedia"}),renderPreview:function(){var e,t,i,a,o=this;(o.model.get("attachment_id")||o.model.get("url"))&&(e=o.$el.find(".media-widget-preview"),t=wp.template("wp-media-widget-image-preview"),e.html(t(o.previewTemplateProps.toJSON())),e.addClass("populated"),o.$el.find(".link").is(document.activeElement)||(i=o.$el.find(".media-widget-fields"),a=wp.template("wp-media-widget-image-fields"),i.html(a(o.previewTemplateProps.toJSON()))))},editMedia:function(){var i,e,t,a,o=this;"none"===(a=o.mapModelToMediaFrameProps(o.model.toJSON())).link&&(a.linkUrl=""),(i=wp.media({frame:"image",state:"image-details",metadata:a})).$el.addClass("media-widget"),e=function(){var e,t;t=(e=i.state().attributes.image.toJSON()).link,e.link=e.linkUrl,o.selectedAttachment.set(e),o.displaySettings.set("link",t),o.model.set(_.extend(o.mapMediaToModelProps(e),{error:!1}))},i.state("image-details").on("update",e),i.state("replace-image").on("replace",e),t=wp.media.model.Attachment.prototype.sync,wp.media.model.Attachment.prototype.sync=function(){return d.Deferred().rejectWith(this).promise()},i.on("close",function(){i.detach(),wp.media.model.Attachment.prototype.sync=t}),i.open()},getEmbedResetProps:function(){return _.extend(a.MediaWidgetControl.prototype.getEmbedResetProps.call(this),{size:"full",width:0,height:0})},getModelPropsFromMediaFrame:function(e){return _.omit(a.MediaWidgetControl.prototype.getModelPropsFromMediaFrame.call(this,e),"image_title")},mapModelToPreviewTemplateProps:function(){var e,t,i=this;return t=i.model.get("url"),(e=a.MediaWidgetControl.prototype.mapModelToPreviewTemplateProps.call(i)).currentFilename=t?t.replace(/\?.*$/,"").replace(/^.+\//,""):"",e.link_url=i.model.get("link_url"),e}}),a.controlConstructors.media_image=t,a.modelConstructors.media_image=e}(wp.mediaWidgets,jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/widgets/media-video-widget.js b/srcs/wordpress/wp-admin/js/widgets/media-video-widget.js deleted file mode 100644 index b716cce..0000000 --- a/srcs/wordpress/wp-admin/js/widgets/media-video-widget.js +++ /dev/null @@ -1,256 +0,0 @@ -/** - * @output wp-admin/js/widgets/media-video-widget.js - */ - -/* eslint consistent-this: [ "error", "control" ] */ -(function( component ) { - 'use strict'; - - var VideoWidgetModel, VideoWidgetControl, VideoDetailsMediaFrame; - - /** - * Custom video details frame that removes the replace-video state. - * - * @class wp.mediaWidgets.controlConstructors~VideoDetailsMediaFrame - * @augments wp.media.view.MediaFrame.VideoDetails - * - * @private - */ - VideoDetailsMediaFrame = wp.media.view.MediaFrame.VideoDetails.extend(/** @lends wp.mediaWidgets.controlConstructors~VideoDetailsMediaFrame.prototype */{ - - /** - * Create the default states. - * - * @returns {void} - */ - createStates: function createStates() { - this.states.add([ - new wp.media.controller.VideoDetails({ - media: this.media - }), - - new wp.media.controller.MediaLibrary({ - type: 'video', - id: 'add-video-source', - title: wp.media.view.l10n.videoAddSourceTitle, - toolbar: 'add-video-source', - media: this.media, - menu: false - }), - - new wp.media.controller.MediaLibrary({ - type: 'text', - id: 'add-track', - title: wp.media.view.l10n.videoAddTrackTitle, - toolbar: 'add-track', - media: this.media, - menu: 'video-details' - }) - ]); - } - }); - - /** - * Video widget model. - * - * See WP_Widget_Video::enqueue_admin_scripts() for amending prototype from PHP exports. - * - * @class wp.mediaWidgets.modelConstructors.media_video - * @augments wp.mediaWidgets.MediaWidgetModel - */ - VideoWidgetModel = component.MediaWidgetModel.extend({}); - - /** - * Video widget control. - * - * See WP_Widget_Video::enqueue_admin_scripts() for amending prototype from PHP exports. - * - * @class wp.mediaWidgets.controlConstructors.media_video - * @augments wp.mediaWidgets.MediaWidgetControl - */ - VideoWidgetControl = component.MediaWidgetControl.extend(/** @lends wp.mediaWidgets.controlConstructors.media_video.prototype */{ - - /** - * Show display settings. - * - * @type {boolean} - */ - showDisplaySettings: false, - - /** - * Cache of oembed responses. - * - * @type {Object} - */ - oembedResponses: {}, - - /** - * Map model props to media frame props. - * - * @param {Object} modelProps - Model props. - * @returns {Object} Media frame props. - */ - mapModelToMediaFrameProps: function mapModelToMediaFrameProps( modelProps ) { - var control = this, mediaFrameProps; - mediaFrameProps = component.MediaWidgetControl.prototype.mapModelToMediaFrameProps.call( control, modelProps ); - mediaFrameProps.link = 'embed'; - return mediaFrameProps; - }, - - /** - * Fetches embed data for external videos. - * - * @returns {void} - */ - fetchEmbed: function fetchEmbed() { - var control = this, url; - url = control.model.get( 'url' ); - - // If we already have a local cache of the embed response, return. - if ( control.oembedResponses[ url ] ) { - return; - } - - // If there is an in-flight embed request, abort it. - if ( control.fetchEmbedDfd && 'pending' === control.fetchEmbedDfd.state() ) { - control.fetchEmbedDfd.abort(); - } - - control.fetchEmbedDfd = wp.apiRequest({ - url: wp.media.view.settings.oEmbedProxyUrl, - data: { - url: control.model.get( 'url' ), - maxwidth: control.model.get( 'width' ), - maxheight: control.model.get( 'height' ), - discover: false - }, - type: 'GET', - dataType: 'json', - context: control - }); - - control.fetchEmbedDfd.done( function( response ) { - control.oembedResponses[ url ] = response; - control.renderPreview(); - }); - - control.fetchEmbedDfd.fail( function() { - control.oembedResponses[ url ] = null; - }); - }, - - /** - * Whether a url is a supported external host. - * - * @deprecated since 4.9. - * - * @returns {boolean} Whether url is a supported video host. - */ - isHostedVideo: function isHostedVideo() { - return true; - }, - - /** - * Render preview. - * - * @returns {void} - */ - renderPreview: function renderPreview() { - var control = this, previewContainer, previewTemplate, attachmentId, attachmentUrl, poster, html = '', isOEmbed = false, mime, error, urlParser, matches; - attachmentId = control.model.get( 'attachment_id' ); - attachmentUrl = control.model.get( 'url' ); - error = control.model.get( 'error' ); - - if ( ! attachmentId && ! attachmentUrl ) { - return; - } - - // Verify the selected attachment mime is supported. - mime = control.selectedAttachment.get( 'mime' ); - if ( mime && attachmentId ) { - if ( ! _.contains( _.values( wp.media.view.settings.embedMimes ), mime ) ) { - error = 'unsupported_file_type'; - } - } else if ( ! attachmentId ) { - urlParser = document.createElement( 'a' ); - urlParser.href = attachmentUrl; - matches = urlParser.pathname.toLowerCase().match( /\.(\w+)$/ ); - if ( matches ) { - if ( ! _.contains( _.keys( wp.media.view.settings.embedMimes ), matches[1] ) ) { - error = 'unsupported_file_type'; - } - } else { - isOEmbed = true; - } - } - - if ( isOEmbed ) { - control.fetchEmbed(); - if ( control.oembedResponses[ attachmentUrl ] ) { - poster = control.oembedResponses[ attachmentUrl ].thumbnail_url; - html = control.oembedResponses[ attachmentUrl ].html.replace( /\swidth="\d+"/, ' width="100%"' ).replace( /\sheight="\d+"/, '' ); - } - } - - previewContainer = control.$el.find( '.media-widget-preview' ); - previewTemplate = wp.template( 'wp-media-widget-video-preview' ); - - previewContainer.html( previewTemplate({ - model: { - attachment_id: attachmentId, - html: html, - src: attachmentUrl, - poster: poster - }, - is_oembed: isOEmbed, - error: error - })); - wp.mediaelement.initialize(); - }, - - /** - * Open the media image-edit frame to modify the selected item. - * - * @returns {void} - */ - editMedia: function editMedia() { - var control = this, mediaFrame, metadata, updateCallback; - - metadata = control.mapModelToMediaFrameProps( control.model.toJSON() ); - - // Set up the media frame. - mediaFrame = new VideoDetailsMediaFrame({ - frame: 'video', - state: 'video-details', - metadata: metadata - }); - wp.media.frame = mediaFrame; - mediaFrame.$el.addClass( 'media-widget' ); - - updateCallback = function( mediaFrameProps ) { - - // Update cached attachment object to avoid having to re-fetch. This also triggers re-rendering of preview. - control.selectedAttachment.set( mediaFrameProps ); - - control.model.set( _.extend( - _.omit( control.model.defaults(), 'title' ), - control.mapMediaToModelProps( mediaFrameProps ), - { error: false } - ) ); - }; - - mediaFrame.state( 'video-details' ).on( 'update', updateCallback ); - mediaFrame.state( 'replace-video' ).on( 'replace', updateCallback ); - mediaFrame.on( 'close', function() { - mediaFrame.detach(); - }); - - mediaFrame.open(); - } - }); - - // Exports. - component.controlConstructors.media_video = VideoWidgetControl; - component.modelConstructors.media_video = VideoWidgetModel; - -})( wp.mediaWidgets ); diff --git a/srcs/wordpress/wp-admin/js/widgets/media-video-widget.min.js b/srcs/wordpress/wp-admin/js/widgets/media-video-widget.min.js deleted file mode 100644 index 9d3704c..0000000 --- a/srcs/wordpress/wp-admin/js/widgets/media-video-widget.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(d){"use strict";var e,t,o;o=wp.media.view.MediaFrame.VideoDetails.extend({createStates:function(){this.states.add([new wp.media.controller.VideoDetails({media:this.media}),new wp.media.controller.MediaLibrary({type:"video",id:"add-video-source",title:wp.media.view.l10n.videoAddSourceTitle,toolbar:"add-video-source",media:this.media,menu:!1}),new wp.media.controller.MediaLibrary({type:"text",id:"add-track",title:wp.media.view.l10n.videoAddTrackTitle,toolbar:"add-track",media:this.media,menu:"video-details"})])}}),e=d.MediaWidgetModel.extend({}),t=d.MediaWidgetControl.extend({showDisplaySettings:!1,oembedResponses:{},mapModelToMediaFrameProps:function(e){var t;return(t=d.MediaWidgetControl.prototype.mapModelToMediaFrameProps.call(this,e)).link="embed",t},fetchEmbed:function(){var t,d=this;t=d.model.get("url"),d.oembedResponses[t]||(d.fetchEmbedDfd&&"pending"===d.fetchEmbedDfd.state()&&d.fetchEmbedDfd.abort(),d.fetchEmbedDfd=wp.apiRequest({url:wp.media.view.settings.oEmbedProxyUrl,data:{url:d.model.get("url"),maxwidth:d.model.get("width"),maxheight:d.model.get("height"),discover:!1},type:"GET",dataType:"json",context:d}),d.fetchEmbedDfd.done(function(e){d.oembedResponses[t]=e,d.renderPreview()}),d.fetchEmbedDfd.fail(function(){d.oembedResponses[t]=null}))},isHostedVideo:function(){return!0},renderPreview:function(){var e,t,d,i,o,a,s,m,n,r=this,l="",p=!1;d=r.model.get("attachment_id"),i=r.model.get("url"),s=r.model.get("error"),(d||i)&&((a=r.selectedAttachment.get("mime"))&&d?_.contains(_.values(wp.media.view.settings.embedMimes),a)||(s="unsupported_file_type"):d||((m=document.createElement("a")).href=i,(n=m.pathname.toLowerCase().match(/\.(\w+)$/))?_.contains(_.keys(wp.media.view.settings.embedMimes),n[1])||(s="unsupported_file_type"):p=!0),p&&(r.fetchEmbed(),r.oembedResponses[i]&&(o=r.oembedResponses[i].thumbnail_url,l=r.oembedResponses[i].html.replace(/\swidth="\d+"/,' width="100%"').replace(/\sheight="\d+"/,""))),e=r.$el.find(".media-widget-preview"),t=wp.template("wp-media-widget-video-preview"),e.html(t({model:{attachment_id:d,html:l,src:i,poster:o},is_oembed:p,error:s})),wp.mediaelement.initialize())},editMedia:function(){var e,t,d,i=this;t=i.mapModelToMediaFrameProps(i.model.toJSON()),e=new o({frame:"video",state:"video-details",metadata:t}),(wp.media.frame=e).$el.addClass("media-widget"),d=function(e){i.selectedAttachment.set(e),i.model.set(_.extend(_.omit(i.model.defaults(),"title"),i.mapMediaToModelProps(e),{error:!1}))},e.state("video-details").on("update",d),e.state("replace-video").on("replace",d),e.on("close",function(){e.detach()}),e.open()}}),d.controlConstructors.media_video=t,d.modelConstructors.media_video=e}(wp.mediaWidgets);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/widgets/media-widgets.js b/srcs/wordpress/wp-admin/js/widgets/media-widgets.js deleted file mode 100644 index 9a243a9..0000000 --- a/srcs/wordpress/wp-admin/js/widgets/media-widgets.js +++ /dev/null @@ -1,1330 +0,0 @@ -/** - * @output wp-admin/js/widgets/media-widgets.js - */ - -/* eslint consistent-this: [ "error", "control" ] */ - -/** - * @namespace wp.mediaWidgets - * @memberOf wp - */ -wp.mediaWidgets = ( function( $ ) { - 'use strict'; - - var component = {}; - - /** - * Widget control (view) constructors, mapping widget id_base to subclass of MediaWidgetControl. - * - * Media widgets register themselves by assigning subclasses of MediaWidgetControl onto this object by widget ID base. - * - * @memberOf wp.mediaWidgets - * - * @type {Object.<string, wp.mediaWidgets.MediaWidgetModel>} - */ - component.controlConstructors = {}; - - /** - * Widget model constructors, mapping widget id_base to subclass of MediaWidgetModel. - * - * Media widgets register themselves by assigning subclasses of MediaWidgetControl onto this object by widget ID base. - * - * @memberOf wp.mediaWidgets - * - * @type {Object.<string, wp.mediaWidgets.MediaWidgetModel>} - */ - component.modelConstructors = {}; - - component.PersistentDisplaySettingsLibrary = wp.media.controller.Library.extend(/** @lends wp.mediaWidgets.PersistentDisplaySettingsLibrary.prototype */{ - - /** - * Library which persists the customized display settings across selections. - * - * @constructs wp.mediaWidgets.PersistentDisplaySettingsLibrary - * @augments wp.media.controller.Library - * - * @param {Object} options - Options. - * - * @returns {void} - */ - initialize: function initialize( options ) { - _.bindAll( this, 'handleDisplaySettingChange' ); - wp.media.controller.Library.prototype.initialize.call( this, options ); - }, - - /** - * Sync changes to the current display settings back into the current customized. - * - * @param {Backbone.Model} displaySettings - Modified display settings. - * @returns {void} - */ - handleDisplaySettingChange: function handleDisplaySettingChange( displaySettings ) { - this.get( 'selectedDisplaySettings' ).set( displaySettings.attributes ); - }, - - /** - * Get the display settings model. - * - * Model returned is updated with the current customized display settings, - * and an event listener is added so that changes made to the settings - * will sync back into the model storing the session's customized display - * settings. - * - * @param {Backbone.Model} model - Display settings model. - * @returns {Backbone.Model} Display settings model. - */ - display: function getDisplaySettingsModel( model ) { - var display, selectedDisplaySettings = this.get( 'selectedDisplaySettings' ); - display = wp.media.controller.Library.prototype.display.call( this, model ); - - display.off( 'change', this.handleDisplaySettingChange ); // Prevent duplicated event handlers. - display.set( selectedDisplaySettings.attributes ); - if ( 'custom' === selectedDisplaySettings.get( 'link_type' ) ) { - display.linkUrl = selectedDisplaySettings.get( 'link_url' ); - } - display.on( 'change', this.handleDisplaySettingChange ); - return display; - } - }); - - /** - * Extended view for managing the embed UI. - * - * @class wp.mediaWidgets.MediaEmbedView - * @augments wp.media.view.Embed - */ - component.MediaEmbedView = wp.media.view.Embed.extend(/** @lends wp.mediaWidgets.MediaEmbedView.prototype */{ - - /** - * Initialize. - * - * @since 4.9.0 - * - * @param {object} options - Options. - * @returns {void} - */ - initialize: function( options ) { - var view = this, embedController; // eslint-disable-line consistent-this - wp.media.view.Embed.prototype.initialize.call( view, options ); - if ( 'image' !== view.controller.options.mimeType ) { - embedController = view.controller.states.get( 'embed' ); - embedController.off( 'scan', embedController.scanImage, embedController ); - } - }, - - /** - * Refresh embed view. - * - * Forked override of {wp.media.view.Embed#refresh()} to suppress irrelevant "link text" field. - * - * @returns {void} - */ - refresh: function refresh() { - /** - * @class wp.mediaWidgets~Constructor - */ - var Constructor; - - if ( 'image' === this.controller.options.mimeType ) { - Constructor = wp.media.view.EmbedImage; - } else { - - // This should be eliminated once #40450 lands of when this is merged into core. - Constructor = wp.media.view.EmbedLink.extend(/** @lends wp.mediaWidgets~Constructor.prototype */{ - - /** - * Set the disabled state on the Add to Widget button. - * - * @param {boolean} disabled - Disabled. - * @returns {void} - */ - setAddToWidgetButtonDisabled: function setAddToWidgetButtonDisabled( disabled ) { - this.views.parent.views.parent.views.get( '.media-frame-toolbar' )[0].$el.find( '.media-button-select' ).prop( 'disabled', disabled ); - }, - - /** - * Set or clear an error notice. - * - * @param {string} notice - Notice. - * @returns {void} - */ - setErrorNotice: function setErrorNotice( notice ) { - var embedLinkView = this, noticeContainer; // eslint-disable-line consistent-this - - noticeContainer = embedLinkView.views.parent.$el.find( '> .notice:first-child' ); - if ( ! notice ) { - if ( noticeContainer.length ) { - noticeContainer.slideUp( 'fast' ); - } - } else { - if ( ! noticeContainer.length ) { - noticeContainer = $( '<div class="media-widget-embed-notice notice notice-error notice-alt"></div>' ); - noticeContainer.hide(); - embedLinkView.views.parent.$el.prepend( noticeContainer ); - } - noticeContainer.empty(); - noticeContainer.append( $( '<p>', { - html: notice - })); - noticeContainer.slideDown( 'fast' ); - } - }, - - /** - * Update oEmbed. - * - * @since 4.9.0 - * - * @returns {void} - */ - updateoEmbed: function() { - var embedLinkView = this, url; // eslint-disable-line consistent-this - - url = embedLinkView.model.get( 'url' ); - - // Abort if the URL field was emptied out. - if ( ! url ) { - embedLinkView.setErrorNotice( '' ); - embedLinkView.setAddToWidgetButtonDisabled( true ); - return; - } - - if ( ! url.match( /^(http|https):\/\/.+\// ) ) { - embedLinkView.controller.$el.find( '#embed-url-field' ).addClass( 'invalid' ); - embedLinkView.setAddToWidgetButtonDisabled( true ); - } - - wp.media.view.EmbedLink.prototype.updateoEmbed.call( embedLinkView ); - }, - - /** - * Fetch media. - * - * @returns {void} - */ - fetch: function() { - var embedLinkView = this, fetchSuccess, matches, fileExt, urlParser, url, re, youTubeEmbedMatch; // eslint-disable-line consistent-this - url = embedLinkView.model.get( 'url' ); - - if ( embedLinkView.dfd && 'pending' === embedLinkView.dfd.state() ) { - embedLinkView.dfd.abort(); - } - - fetchSuccess = function( response ) { - embedLinkView.renderoEmbed({ - data: { - body: response - } - }); - - embedLinkView.controller.$el.find( '#embed-url-field' ).removeClass( 'invalid' ); - embedLinkView.setErrorNotice( '' ); - embedLinkView.setAddToWidgetButtonDisabled( false ); - }; - - urlParser = document.createElement( 'a' ); - urlParser.href = url; - matches = urlParser.pathname.toLowerCase().match( /\.(\w+)$/ ); - if ( matches ) { - fileExt = matches[1]; - if ( ! wp.media.view.settings.embedMimes[ fileExt ] ) { - embedLinkView.renderFail(); - } else if ( 0 !== wp.media.view.settings.embedMimes[ fileExt ].indexOf( embedLinkView.controller.options.mimeType ) ) { - embedLinkView.renderFail(); - } else { - fetchSuccess( '<!--success-->' ); - } - return; - } - - // Support YouTube embed links. - re = /https?:\/\/www\.youtube\.com\/embed\/([^/]+)/; - youTubeEmbedMatch = re.exec( url ); - if ( youTubeEmbedMatch ) { - url = 'https://www.youtube.com/watch?v=' + youTubeEmbedMatch[ 1 ]; - // silently change url to proper oembed-able version. - embedLinkView.model.attributes.url = url; - } - - embedLinkView.dfd = wp.apiRequest({ - url: wp.media.view.settings.oEmbedProxyUrl, - data: { - url: url, - maxwidth: embedLinkView.model.get( 'width' ), - maxheight: embedLinkView.model.get( 'height' ), - discover: false - }, - type: 'GET', - dataType: 'json', - context: embedLinkView - }); - - embedLinkView.dfd.done( function( response ) { - if ( embedLinkView.controller.options.mimeType !== response.type ) { - embedLinkView.renderFail(); - return; - } - fetchSuccess( response.html ); - }); - embedLinkView.dfd.fail( _.bind( embedLinkView.renderFail, embedLinkView ) ); - }, - - /** - * Handle render failure. - * - * Overrides the {EmbedLink#renderFail()} method to prevent showing the "Link Text" field. - * The element is getting display:none in the stylesheet, but the underlying method uses - * uses {jQuery.fn.show()} which adds an inline style. This avoids the need for !important. - * - * @returns {void} - */ - renderFail: function renderFail() { - var embedLinkView = this; // eslint-disable-line consistent-this - embedLinkView.controller.$el.find( '#embed-url-field' ).addClass( 'invalid' ); - embedLinkView.setErrorNotice( embedLinkView.controller.options.invalidEmbedTypeError || 'ERROR' ); - embedLinkView.setAddToWidgetButtonDisabled( true ); - } - }); - } - - this.settings( new Constructor({ - controller: this.controller, - model: this.model.props, - priority: 40 - })); - } - }); - - /** - * Custom media frame for selecting uploaded media or providing media by URL. - * - * @class wp.mediaWidgets.MediaFrameSelect - * @augments wp.media.view.MediaFrame.Post - */ - component.MediaFrameSelect = wp.media.view.MediaFrame.Post.extend(/** @lends wp.mediaWidgets.MediaFrameSelect.prototype */{ - - /** - * Create the default states. - * - * @returns {void} - */ - createStates: function createStates() { - var mime = this.options.mimeType, specificMimes = []; - _.each( wp.media.view.settings.embedMimes, function( embedMime ) { - if ( 0 === embedMime.indexOf( mime ) ) { - specificMimes.push( embedMime ); - } - }); - if ( specificMimes.length > 0 ) { - mime = specificMimes; - } - - this.states.add([ - - // Main states. - new component.PersistentDisplaySettingsLibrary({ - id: 'insert', - title: this.options.title, - selection: this.options.selection, - priority: 20, - toolbar: 'main-insert', - filterable: 'dates', - library: wp.media.query({ - type: mime - }), - multiple: false, - editable: true, - - selectedDisplaySettings: this.options.selectedDisplaySettings, - displaySettings: _.isUndefined( this.options.showDisplaySettings ) ? true : this.options.showDisplaySettings, - displayUserSettings: false // We use the display settings from the current/default widget instance props. - }), - - new wp.media.controller.EditImage({ model: this.options.editImage }), - - // Embed states. - new wp.media.controller.Embed({ - metadata: this.options.metadata, - type: 'image' === this.options.mimeType ? 'image' : 'link', - invalidEmbedTypeError: this.options.invalidEmbedTypeError - }) - ]); - }, - - /** - * Main insert toolbar. - * - * Forked override of {wp.media.view.MediaFrame.Post#mainInsertToolbar()} to override text. - * - * @param {wp.Backbone.View} view - Toolbar view. - * @this {wp.media.controller.Library} - * @returns {void} - */ - mainInsertToolbar: function mainInsertToolbar( view ) { - var controller = this; // eslint-disable-line consistent-this - view.set( 'insert', { - style: 'primary', - priority: 80, - text: controller.options.text, // The whole reason for the fork. - requires: { selection: true }, - - /** - * Handle click. - * - * @ignore - * - * @fires wp.media.controller.State#insert() - * @returns {void} - */ - click: function onClick() { - var state = controller.state(), - selection = state.get( 'selection' ); - - controller.close(); - state.trigger( 'insert', selection ).reset(); - } - }); - }, - - /** - * Main embed toolbar. - * - * Forked override of {wp.media.view.MediaFrame.Post#mainEmbedToolbar()} to override text. - * - * @param {wp.Backbone.View} toolbar - Toolbar view. - * @this {wp.media.controller.Library} - * @returns {void} - */ - mainEmbedToolbar: function mainEmbedToolbar( toolbar ) { - toolbar.view = new wp.media.view.Toolbar.Embed({ - controller: this, - text: this.options.text, - event: 'insert' - }); - }, - - /** - * Embed content. - * - * Forked override of {wp.media.view.MediaFrame.Post#embedContent()} to suppress irrelevant "link text" field. - * - * @returns {void} - */ - embedContent: function embedContent() { - var view = new component.MediaEmbedView({ - controller: this, - model: this.state() - }).render(); - - this.content.set( view ); - } - }); - - component.MediaWidgetControl = Backbone.View.extend(/** @lends wp.mediaWidgets.MediaWidgetControl.prototype */{ - - /** - * Translation strings. - * - * The mapping of translation strings is handled by media widget subclasses, - * exported from PHP to JS such as is done in WP_Widget_Media_Image::enqueue_admin_scripts(). - * - * @type {Object} - */ - l10n: { - add_to_widget: '{{add_to_widget}}', - add_media: '{{add_media}}' - }, - - /** - * Widget ID base. - * - * This may be defined by the subclass. It may be exported from PHP to JS - * such as is done in WP_Widget_Media_Image::enqueue_admin_scripts(). If not, - * it will attempt to be discovered by looking to see if this control - * instance extends each member of component.controlConstructors, and if - * it does extend one, will use the key as the id_base. - * - * @type {string} - */ - id_base: '', - - /** - * Mime type. - * - * This must be defined by the subclass. It may be exported from PHP to JS - * such as is done in WP_Widget_Media_Image::enqueue_admin_scripts(). - * - * @type {string} - */ - mime_type: '', - - /** - * View events. - * - * @type {Object} - */ - events: { - 'click .notice-missing-attachment a': 'handleMediaLibraryLinkClick', - 'click .select-media': 'selectMedia', - 'click .placeholder': 'selectMedia', - 'click .edit-media': 'editMedia' - }, - - /** - * Show display settings. - * - * @type {boolean} - */ - showDisplaySettings: true, - - /** - * Media Widget Control. - * - * @constructs wp.mediaWidgets.MediaWidgetControl - * @augments Backbone.View - * @abstract - * - * @param {Object} options - Options. - * @param {Backbone.Model} options.model - Model. - * @param {jQuery} options.el - Control field container element. - * @param {jQuery} options.syncContainer - Container element where fields are synced for the server. - * - * @returns {void} - */ - initialize: function initialize( options ) { - var control = this; - - Backbone.View.prototype.initialize.call( control, options ); - - if ( ! ( control.model instanceof component.MediaWidgetModel ) ) { - throw new Error( 'Missing options.model' ); - } - if ( ! options.el ) { - throw new Error( 'Missing options.el' ); - } - if ( ! options.syncContainer ) { - throw new Error( 'Missing options.syncContainer' ); - } - - control.syncContainer = options.syncContainer; - - control.$el.addClass( 'media-widget-control' ); - - // Allow methods to be passed in with control context preserved. - _.bindAll( control, 'syncModelToInputs', 'render', 'updateSelectedAttachment', 'renderPreview' ); - - if ( ! control.id_base ) { - _.find( component.controlConstructors, function( Constructor, idBase ) { - if ( control instanceof Constructor ) { - control.id_base = idBase; - return true; - } - return false; - }); - if ( ! control.id_base ) { - throw new Error( 'Missing id_base.' ); - } - } - - // Track attributes needed to renderPreview in it's own model. - control.previewTemplateProps = new Backbone.Model( control.mapModelToPreviewTemplateProps() ); - - // Re-render the preview when the attachment changes. - control.selectedAttachment = new wp.media.model.Attachment(); - control.renderPreview = _.debounce( control.renderPreview ); - control.listenTo( control.previewTemplateProps, 'change', control.renderPreview ); - - // Make sure a copy of the selected attachment is always fetched. - control.model.on( 'change:attachment_id', control.updateSelectedAttachment ); - control.model.on( 'change:url', control.updateSelectedAttachment ); - control.updateSelectedAttachment(); - - /* - * Sync the widget instance model attributes onto the hidden inputs that widgets currently use to store the state. - * In the future, when widgets are JS-driven, the underlying widget instance data should be exposed as a model - * from the start, without having to sync with hidden fields. See <https://core.trac.wordpress.org/ticket/33507>. - */ - control.listenTo( control.model, 'change', control.syncModelToInputs ); - control.listenTo( control.model, 'change', control.syncModelToPreviewProps ); - control.listenTo( control.model, 'change', control.render ); - - // Update the title. - control.$el.on( 'input change', '.title', function updateTitle() { - control.model.set({ - title: $.trim( $( this ).val() ) - }); - }); - - // Update link_url attribute. - control.$el.on( 'input change', '.link', function updateLinkUrl() { - var linkUrl = $.trim( $( this ).val() ), linkType = 'custom'; - if ( control.selectedAttachment.get( 'linkUrl' ) === linkUrl || control.selectedAttachment.get( 'link' ) === linkUrl ) { - linkType = 'post'; - } else if ( control.selectedAttachment.get( 'url' ) === linkUrl ) { - linkType = 'file'; - } - control.model.set( { - link_url: linkUrl, - link_type: linkType - }); - - // Update display settings for the next time the user opens to select from the media library. - control.displaySettings.set( { - link: linkType, - linkUrl: linkUrl - }); - }); - - /* - * Copy current display settings from the widget model to serve as basis - * of customized display settings for the current media frame session. - * Changes to display settings will be synced into this model, and - * when a new selection is made, the settings from this will be synced - * into that AttachmentDisplay's model to persist the setting changes. - */ - control.displaySettings = new Backbone.Model( _.pick( - control.mapModelToMediaFrameProps( - _.extend( control.model.defaults(), control.model.toJSON() ) - ), - _.keys( wp.media.view.settings.defaultProps ) - ) ); - }, - - /** - * Update the selected attachment if necessary. - * - * @returns {void} - */ - updateSelectedAttachment: function updateSelectedAttachment() { - var control = this, attachment; - - if ( 0 === control.model.get( 'attachment_id' ) ) { - control.selectedAttachment.clear(); - control.model.set( 'error', false ); - } else if ( control.model.get( 'attachment_id' ) !== control.selectedAttachment.get( 'id' ) ) { - attachment = new wp.media.model.Attachment({ - id: control.model.get( 'attachment_id' ) - }); - attachment.fetch() - .done( function done() { - control.model.set( 'error', false ); - control.selectedAttachment.set( attachment.toJSON() ); - }) - .fail( function fail() { - control.model.set( 'error', 'missing_attachment' ); - }); - } - }, - - /** - * Sync the model attributes to the hidden inputs, and update previewTemplateProps. - * - * @returns {void} - */ - syncModelToPreviewProps: function syncModelToPreviewProps() { - var control = this; - control.previewTemplateProps.set( control.mapModelToPreviewTemplateProps() ); - }, - - /** - * Sync the model attributes to the hidden inputs, and update previewTemplateProps. - * - * @returns {void} - */ - syncModelToInputs: function syncModelToInputs() { - var control = this; - control.syncContainer.find( '.media-widget-instance-property' ).each( function() { - var input = $( this ), value, propertyName; - propertyName = input.data( 'property' ); - value = control.model.get( propertyName ); - if ( _.isUndefined( value ) ) { - return; - } - - if ( 'array' === control.model.schema[ propertyName ].type && _.isArray( value ) ) { - value = value.join( ',' ); - } else if ( 'boolean' === control.model.schema[ propertyName ].type ) { - value = value ? '1' : ''; // Because in PHP, strval( true ) === '1' && strval( false ) === ''. - } else { - value = String( value ); - } - - if ( input.val() !== value ) { - input.val( value ); - input.trigger( 'change' ); - } - }); - }, - - /** - * Get template. - * - * @returns {Function} Template. - */ - template: function template() { - var control = this; - if ( ! $( '#tmpl-widget-media-' + control.id_base + '-control' ).length ) { - throw new Error( 'Missing widget control template for ' + control.id_base ); - } - return wp.template( 'widget-media-' + control.id_base + '-control' ); - }, - - /** - * Render template. - * - * @returns {void} - */ - render: function render() { - var control = this, titleInput; - - if ( ! control.templateRendered ) { - control.$el.html( control.template()( control.model.toJSON() ) ); - control.renderPreview(); // Hereafter it will re-render when control.selectedAttachment changes. - control.templateRendered = true; - } - - titleInput = control.$el.find( '.title' ); - if ( ! titleInput.is( document.activeElement ) ) { - titleInput.val( control.model.get( 'title' ) ); - } - - control.$el.toggleClass( 'selected', control.isSelected() ); - }, - - /** - * Render media preview. - * - * @abstract - * @returns {void} - */ - renderPreview: function renderPreview() { - throw new Error( 'renderPreview must be implemented' ); - }, - - /** - * Whether a media item is selected. - * - * @returns {boolean} Whether selected and no error. - */ - isSelected: function isSelected() { - var control = this; - - if ( control.model.get( 'error' ) ) { - return false; - } - - return Boolean( control.model.get( 'attachment_id' ) || control.model.get( 'url' ) ); - }, - - /** - * Handle click on link to Media Library to open modal, such as the link that appears when in the missing attachment error notice. - * - * @param {jQuery.Event} event - Event. - * @returns {void} - */ - handleMediaLibraryLinkClick: function handleMediaLibraryLinkClick( event ) { - var control = this; - event.preventDefault(); - control.selectMedia(); - }, - - /** - * Open the media select frame to chose an item. - * - * @returns {void} - */ - selectMedia: function selectMedia() { - var control = this, selection, mediaFrame, defaultSync, mediaFrameProps, selectionModels = []; - - if ( control.isSelected() && 0 !== control.model.get( 'attachment_id' ) ) { - selectionModels.push( control.selectedAttachment ); - } - - selection = new wp.media.model.Selection( selectionModels, { multiple: false } ); - - mediaFrameProps = control.mapModelToMediaFrameProps( control.model.toJSON() ); - if ( mediaFrameProps.size ) { - control.displaySettings.set( 'size', mediaFrameProps.size ); - } - - mediaFrame = new component.MediaFrameSelect({ - title: control.l10n.add_media, - frame: 'post', - text: control.l10n.add_to_widget, - selection: selection, - mimeType: control.mime_type, - selectedDisplaySettings: control.displaySettings, - showDisplaySettings: control.showDisplaySettings, - metadata: mediaFrameProps, - state: control.isSelected() && 0 === control.model.get( 'attachment_id' ) ? 'embed' : 'insert', - invalidEmbedTypeError: control.l10n.unsupported_file_type - }); - wp.media.frame = mediaFrame; // See wp.media(). - - // Handle selection of a media item. - mediaFrame.on( 'insert', function onInsert() { - var attachment = {}, state = mediaFrame.state(); - - // Update cached attachment object to avoid having to re-fetch. This also triggers re-rendering of preview. - if ( 'embed' === state.get( 'id' ) ) { - _.extend( attachment, { id: 0 }, state.props.toJSON() ); - } else { - _.extend( attachment, state.get( 'selection' ).first().toJSON() ); - } - - control.selectedAttachment.set( attachment ); - control.model.set( 'error', false ); - - // Update widget instance. - control.model.set( control.getModelPropsFromMediaFrame( mediaFrame ) ); - }); - - // Disable syncing of attachment changes back to server (except for deletions). See <https://core.trac.wordpress.org/ticket/40403>. - defaultSync = wp.media.model.Attachment.prototype.sync; - wp.media.model.Attachment.prototype.sync = function( method ) { - if ( 'delete' === method ) { - return defaultSync.apply( this, arguments ); - } else { - return $.Deferred().rejectWith( this ).promise(); - } - }; - mediaFrame.on( 'close', function onClose() { - wp.media.model.Attachment.prototype.sync = defaultSync; - }); - - mediaFrame.$el.addClass( 'media-widget' ); - mediaFrame.open(); - - // Clear the selected attachment when it is deleted in the media select frame. - if ( selection ) { - selection.on( 'destroy', function onDestroy( attachment ) { - if ( control.model.get( 'attachment_id' ) === attachment.get( 'id' ) ) { - control.model.set({ - attachment_id: 0, - url: '' - }); - } - }); - } - - /* - * Make sure focus is set inside of modal so that hitting Esc will close - * the modal and not inadvertently cause the widget to collapse in the customizer. - */ - mediaFrame.$el.find( '.media-frame-menu .media-menu-item.active' ).focus(); - }, - - /** - * Get the instance props from the media selection frame. - * - * @param {wp.media.view.MediaFrame.Select} mediaFrame - Select frame. - * @returns {Object} Props. - */ - getModelPropsFromMediaFrame: function getModelPropsFromMediaFrame( mediaFrame ) { - var control = this, state, mediaFrameProps, modelProps; - - state = mediaFrame.state(); - if ( 'insert' === state.get( 'id' ) ) { - mediaFrameProps = state.get( 'selection' ).first().toJSON(); - mediaFrameProps.postUrl = mediaFrameProps.link; - - if ( control.showDisplaySettings ) { - _.extend( - mediaFrameProps, - mediaFrame.content.get( '.attachments-browser' ).sidebar.get( 'display' ).model.toJSON() - ); - } - if ( mediaFrameProps.sizes && mediaFrameProps.size && mediaFrameProps.sizes[ mediaFrameProps.size ] ) { - mediaFrameProps.url = mediaFrameProps.sizes[ mediaFrameProps.size ].url; - } - } else if ( 'embed' === state.get( 'id' ) ) { - mediaFrameProps = _.extend( - state.props.toJSON(), - { attachment_id: 0 }, // Because some media frames use `attachment_id` not `id`. - control.model.getEmbedResetProps() - ); - } else { - throw new Error( 'Unexpected state: ' + state.get( 'id' ) ); - } - - if ( mediaFrameProps.id ) { - mediaFrameProps.attachment_id = mediaFrameProps.id; - } - - modelProps = control.mapMediaToModelProps( mediaFrameProps ); - - // Clear the extension prop so sources will be reset for video and audio media. - _.each( wp.media.view.settings.embedExts, function( ext ) { - if ( ext in control.model.schema && modelProps.url !== modelProps[ ext ] ) { - modelProps[ ext ] = ''; - } - }); - - return modelProps; - }, - - /** - * Map media frame props to model props. - * - * @param {Object} mediaFrameProps - Media frame props. - * @returns {Object} Model props. - */ - mapMediaToModelProps: function mapMediaToModelProps( mediaFrameProps ) { - var control = this, mediaFramePropToModelPropMap = {}, modelProps = {}, extension; - _.each( control.model.schema, function( fieldSchema, modelProp ) { - - // Ignore widget title attribute. - if ( 'title' === modelProp ) { - return; - } - mediaFramePropToModelPropMap[ fieldSchema.media_prop || modelProp ] = modelProp; - }); - - _.each( mediaFrameProps, function( value, mediaProp ) { - var propName = mediaFramePropToModelPropMap[ mediaProp ] || mediaProp; - if ( control.model.schema[ propName ] ) { - modelProps[ propName ] = value; - } - }); - - if ( 'custom' === mediaFrameProps.size ) { - modelProps.width = mediaFrameProps.customWidth; - modelProps.height = mediaFrameProps.customHeight; - } - - if ( 'post' === mediaFrameProps.link ) { - modelProps.link_url = mediaFrameProps.postUrl || mediaFrameProps.linkUrl; - } else if ( 'file' === mediaFrameProps.link ) { - modelProps.link_url = mediaFrameProps.url; - } - - // Because some media frames use `id` instead of `attachment_id`. - if ( ! mediaFrameProps.attachment_id && mediaFrameProps.id ) { - modelProps.attachment_id = mediaFrameProps.id; - } - - if ( mediaFrameProps.url ) { - extension = mediaFrameProps.url.replace( /#.*$/, '' ).replace( /\?.*$/, '' ).split( '.' ).pop().toLowerCase(); - if ( extension in control.model.schema ) { - modelProps[ extension ] = mediaFrameProps.url; - } - } - - // Always omit the titles derived from mediaFrameProps. - return _.omit( modelProps, 'title' ); - }, - - /** - * Map model props to media frame props. - * - * @param {Object} modelProps - Model props. - * @returns {Object} Media frame props. - */ - mapModelToMediaFrameProps: function mapModelToMediaFrameProps( modelProps ) { - var control = this, mediaFrameProps = {}; - - _.each( modelProps, function( value, modelProp ) { - var fieldSchema = control.model.schema[ modelProp ] || {}; - mediaFrameProps[ fieldSchema.media_prop || modelProp ] = value; - }); - - // Some media frames use attachment_id. - mediaFrameProps.attachment_id = mediaFrameProps.id; - - if ( 'custom' === mediaFrameProps.size ) { - mediaFrameProps.customWidth = control.model.get( 'width' ); - mediaFrameProps.customHeight = control.model.get( 'height' ); - } - - return mediaFrameProps; - }, - - /** - * Map model props to previewTemplateProps. - * - * @returns {Object} Preview Template Props. - */ - mapModelToPreviewTemplateProps: function mapModelToPreviewTemplateProps() { - var control = this, previewTemplateProps = {}; - _.each( control.model.schema, function( value, prop ) { - if ( ! value.hasOwnProperty( 'should_preview_update' ) || value.should_preview_update ) { - previewTemplateProps[ prop ] = control.model.get( prop ); - } - }); - - // Templates need to be aware of the error. - previewTemplateProps.error = control.model.get( 'error' ); - return previewTemplateProps; - }, - - /** - * Open the media frame to modify the selected item. - * - * @abstract - * @returns {void} - */ - editMedia: function editMedia() { - throw new Error( 'editMedia not implemented' ); - } - }); - - /** - * Media widget model. - * - * @class wp.mediaWidgets.MediaWidgetModel - * @augments Backbone.Model - */ - component.MediaWidgetModel = Backbone.Model.extend(/** @lends wp.mediaWidgets.MediaWidgetModel.prototype */{ - - /** - * Id attribute. - * - * @type {string} - */ - idAttribute: 'widget_id', - - /** - * Instance schema. - * - * This adheres to JSON Schema and subclasses should have their schema - * exported from PHP to JS such as is done in WP_Widget_Media_Image::enqueue_admin_scripts(). - * - * @type {Object.<string, Object>} - */ - schema: { - title: { - type: 'string', - 'default': '' - }, - attachment_id: { - type: 'integer', - 'default': 0 - }, - url: { - type: 'string', - 'default': '' - } - }, - - /** - * Get default attribute values. - * - * @returns {Object} Mapping of property names to their default values. - */ - defaults: function() { - var defaults = {}; - _.each( this.schema, function( fieldSchema, field ) { - defaults[ field ] = fieldSchema['default']; - }); - return defaults; - }, - - /** - * Set attribute value(s). - * - * This is a wrapped version of Backbone.Model#set() which allows us to - * cast the attribute values from the hidden inputs' string values into - * the appropriate data types (integers or booleans). - * - * @param {string|Object} key - Attribute name or attribute pairs. - * @param {mixed|Object} [val] - Attribute value or options object. - * @param {Object} [options] - Options when attribute name and value are passed separately. - * @returns {wp.mediaWidgets.MediaWidgetModel} This model. - */ - set: function set( key, val, options ) { - var model = this, attrs, opts, castedAttrs; // eslint-disable-line consistent-this - if ( null === key ) { - return model; - } - if ( 'object' === typeof key ) { - attrs = key; - opts = val; - } else { - attrs = {}; - attrs[ key ] = val; - opts = options; - } - - castedAttrs = {}; - _.each( attrs, function( value, name ) { - var type; - if ( ! model.schema[ name ] ) { - castedAttrs[ name ] = value; - return; - } - type = model.schema[ name ].type; - if ( 'array' === type ) { - castedAttrs[ name ] = value; - if ( ! _.isArray( castedAttrs[ name ] ) ) { - castedAttrs[ name ] = castedAttrs[ name ].split( /,/ ); // Good enough for parsing an ID list. - } - if ( model.schema[ name ].items && 'integer' === model.schema[ name ].items.type ) { - castedAttrs[ name ] = _.filter( - _.map( castedAttrs[ name ], function( id ) { - return parseInt( id, 10 ); - }, - function( id ) { - return 'number' === typeof id; - } - ) ); - } - } else if ( 'integer' === type ) { - castedAttrs[ name ] = parseInt( value, 10 ); - } else if ( 'boolean' === type ) { - castedAttrs[ name ] = ! ( ! value || '0' === value || 'false' === value ); - } else { - castedAttrs[ name ] = value; - } - }); - - return Backbone.Model.prototype.set.call( this, castedAttrs, opts ); - }, - - /** - * Get props which are merged on top of the model when an embed is chosen (as opposed to an attachment). - * - * @returns {Object} Reset/override props. - */ - getEmbedResetProps: function getEmbedResetProps() { - return { - id: 0 - }; - } - }); - - /** - * Collection of all widget model instances. - * - * @memberOf wp.mediaWidgets - * - * @type {Backbone.Collection} - */ - component.modelCollection = new ( Backbone.Collection.extend( { - model: component.MediaWidgetModel - }) )(); - - /** - * Mapping of widget ID to instances of MediaWidgetControl subclasses. - * - * @memberOf wp.mediaWidgets - * - * @type {Object.<string, wp.mediaWidgets.MediaWidgetControl>} - */ - component.widgetControls = {}; - - /** - * Handle widget being added or initialized for the first time at the widget-added event. - * - * @memberOf wp.mediaWidgets - * - * @param {jQuery.Event} event - Event. - * @param {jQuery} widgetContainer - Widget container element. - * - * @returns {void} - */ - component.handleWidgetAdded = function handleWidgetAdded( event, widgetContainer ) { - var fieldContainer, syncContainer, widgetForm, idBase, ControlConstructor, ModelConstructor, modelAttributes, widgetControl, widgetModel, widgetId, animatedCheckDelay = 50, renderWhenAnimationDone; - widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' ); // Note: '.form' appears in the customizer, whereas 'form' on the widgets admin screen. - idBase = widgetForm.find( '> .id_base' ).val(); - widgetId = widgetForm.find( '> .widget-id' ).val(); - - // Prevent initializing already-added widgets. - if ( component.widgetControls[ widgetId ] ) { - return; - } - - ControlConstructor = component.controlConstructors[ idBase ]; - if ( ! ControlConstructor ) { - return; - } - - ModelConstructor = component.modelConstructors[ idBase ] || component.MediaWidgetModel; - - /* - * Create a container element for the widget control (Backbone.View). - * This is inserted into the DOM immediately before the .widget-content - * element because the contents of this element are essentially "managed" - * by PHP, where each widget update cause the entire element to be emptied - * and replaced with the rendered output of WP_Widget::form() which is - * sent back in Ajax request made to save/update the widget instance. - * To prevent a "flash of replaced DOM elements and re-initialized JS - * components", the JS template is rendered outside of the normal form - * container. - */ - fieldContainer = $( '<div></div>' ); - syncContainer = widgetContainer.find( '.widget-content:first' ); - syncContainer.before( fieldContainer ); - - /* - * Sync the widget instance model attributes onto the hidden inputs that widgets currently use to store the state. - * In the future, when widgets are JS-driven, the underlying widget instance data should be exposed as a model - * from the start, without having to sync with hidden fields. See <https://core.trac.wordpress.org/ticket/33507>. - */ - modelAttributes = {}; - syncContainer.find( '.media-widget-instance-property' ).each( function() { - var input = $( this ); - modelAttributes[ input.data( 'property' ) ] = input.val(); - }); - modelAttributes.widget_id = widgetId; - - widgetModel = new ModelConstructor( modelAttributes ); - - widgetControl = new ControlConstructor({ - el: fieldContainer, - syncContainer: syncContainer, - model: widgetModel - }); - - /* - * Render the widget once the widget parent's container finishes animating, - * as the widget-added event fires with a slideDown of the container. - * This ensures that the container's dimensions are fixed so that ME.js - * can initialize with the proper dimensions. - */ - renderWhenAnimationDone = function() { - if ( ! widgetContainer.hasClass( 'open' ) ) { - setTimeout( renderWhenAnimationDone, animatedCheckDelay ); - } else { - widgetControl.render(); - } - }; - renderWhenAnimationDone(); - - /* - * Note that the model and control currently won't ever get garbage-collected - * when a widget gets removed/deleted because there is no widget-removed event. - */ - component.modelCollection.add( [ widgetModel ] ); - component.widgetControls[ widgetModel.get( 'widget_id' ) ] = widgetControl; - }; - - /** - * Setup widget in accessibility mode. - * - * @memberOf wp.mediaWidgets - * - * @returns {void} - */ - component.setupAccessibleMode = function setupAccessibleMode() { - var widgetForm, widgetId, idBase, widgetControl, ControlConstructor, ModelConstructor, modelAttributes, fieldContainer, syncContainer; - widgetForm = $( '.editwidget > form' ); - if ( 0 === widgetForm.length ) { - return; - } - - idBase = widgetForm.find( '> .widget-control-actions > .id_base' ).val(); - - ControlConstructor = component.controlConstructors[ idBase ]; - if ( ! ControlConstructor ) { - return; - } - - widgetId = widgetForm.find( '> .widget-control-actions > .widget-id' ).val(); - - ModelConstructor = component.modelConstructors[ idBase ] || component.MediaWidgetModel; - fieldContainer = $( '<div></div>' ); - syncContainer = widgetForm.find( '> .widget-inside' ); - syncContainer.before( fieldContainer ); - - modelAttributes = {}; - syncContainer.find( '.media-widget-instance-property' ).each( function() { - var input = $( this ); - modelAttributes[ input.data( 'property' ) ] = input.val(); - }); - modelAttributes.widget_id = widgetId; - - widgetControl = new ControlConstructor({ - el: fieldContainer, - syncContainer: syncContainer, - model: new ModelConstructor( modelAttributes ) - }); - - component.modelCollection.add( [ widgetControl.model ] ); - component.widgetControls[ widgetControl.model.get( 'widget_id' ) ] = widgetControl; - - widgetControl.render(); - }; - - /** - * Sync widget instance data sanitized from server back onto widget model. - * - * This gets called via the 'widget-updated' event when saving a widget from - * the widgets admin screen and also via the 'widget-synced' event when making - * a change to a widget in the customizer. - * - * @memberOf wp.mediaWidgets - * - * @param {jQuery.Event} event - Event. - * @param {jQuery} widgetContainer - Widget container element. - * - * @returns {void} - */ - component.handleWidgetUpdated = function handleWidgetUpdated( event, widgetContainer ) { - var widgetForm, widgetContent, widgetId, widgetControl, attributes = {}; - widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' ); - widgetId = widgetForm.find( '> .widget-id' ).val(); - - widgetControl = component.widgetControls[ widgetId ]; - if ( ! widgetControl ) { - return; - } - - // Make sure the server-sanitized values get synced back into the model. - widgetContent = widgetForm.find( '> .widget-content' ); - widgetContent.find( '.media-widget-instance-property' ).each( function() { - var property = $( this ).data( 'property' ); - attributes[ property ] = $( this ).val(); - }); - - // Suspend syncing model back to inputs when syncing from inputs to model, preventing infinite loop. - widgetControl.stopListening( widgetControl.model, 'change', widgetControl.syncModelToInputs ); - widgetControl.model.set( attributes ); - widgetControl.listenTo( widgetControl.model, 'change', widgetControl.syncModelToInputs ); - }; - - /** - * Initialize functionality. - * - * This function exists to prevent the JS file from having to boot itself. - * When WordPress enqueues this script, it should have an inline script - * attached which calls wp.mediaWidgets.init(). - * - * @memberOf wp.mediaWidgets - * - * @returns {void} - */ - component.init = function init() { - var $document = $( document ); - $document.on( 'widget-added', component.handleWidgetAdded ); - $document.on( 'widget-synced widget-updated', component.handleWidgetUpdated ); - - /* - * Manually trigger widget-added events for media widgets on the admin - * screen once they are expanded. The widget-added event is not triggered - * for each pre-existing widget on the widgets admin screen like it is - * on the customizer. Likewise, the customizer only triggers widget-added - * when the widget is expanded to just-in-time construct the widget form - * when it is actually going to be displayed. So the following implements - * the same for the widgets admin screen, to invoke the widget-added - * handler when a pre-existing media widget is expanded. - */ - $( function initializeExistingWidgetContainers() { - var widgetContainers; - if ( 'widgets' !== window.pagenow ) { - return; - } - widgetContainers = $( '.widgets-holder-wrap:not(#available-widgets)' ).find( 'div.widget' ); - widgetContainers.one( 'click.toggle-widget-expanded', function toggleWidgetExpanded() { - var widgetContainer = $( this ); - component.handleWidgetAdded( new jQuery.Event( 'widget-added' ), widgetContainer ); - }); - - // Accessibility mode. - $( window ).on( 'load', function() { - component.setupAccessibleMode(); - }); - }); - }; - - return component; -})( jQuery ); diff --git a/srcs/wordpress/wp-admin/js/widgets/media-widgets.min.js b/srcs/wordpress/wp-admin/js/widgets/media-widgets.min.js deleted file mode 100644 index 48b5d2f..0000000 --- a/srcs/wordpress/wp-admin/js/widgets/media-widgets.min.js +++ /dev/null @@ -1 +0,0 @@ -wp.mediaWidgets=function(h){"use strict";var g={controlConstructors:{},modelConstructors:{}};return g.PersistentDisplaySettingsLibrary=wp.media.controller.Library.extend({initialize:function(e){_.bindAll(this,"handleDisplaySettingChange"),wp.media.controller.Library.prototype.initialize.call(this,e)},handleDisplaySettingChange:function(e){this.get("selectedDisplaySettings").set(e.attributes)},display:function(e){var t,i=this.get("selectedDisplaySettings");return(t=wp.media.controller.Library.prototype.display.call(this,e)).off("change",this.handleDisplaySettingChange),t.set(i.attributes),"custom"===i.get("link_type")&&(t.linkUrl=i.get("link_url")),t.on("change",this.handleDisplaySettingChange),t}}),g.MediaEmbedView=wp.media.view.Embed.extend({initialize:function(e){var t,i=this;wp.media.view.Embed.prototype.initialize.call(i,e),"image"!==i.controller.options.mimeType&&(t=i.controller.states.get("embed")).off("scan",t.scanImage,t)},refresh:function(){var e;e="image"===this.controller.options.mimeType?wp.media.view.EmbedImage:wp.media.view.EmbedLink.extend({setAddToWidgetButtonDisabled:function(e){this.views.parent.views.parent.views.get(".media-frame-toolbar")[0].$el.find(".media-button-select").prop("disabled",e)},setErrorNotice:function(e){var t;t=this.views.parent.$el.find("> .notice:first-child"),e?(t.length||((t=h('<div class="media-widget-embed-notice notice notice-error notice-alt"></div>')).hide(),this.views.parent.$el.prepend(t)),t.empty(),t.append(h("<p>",{html:e})),t.slideDown("fast")):t.length&&t.slideUp("fast")},updateoEmbed:function(){var e,t=this;if(!(e=t.model.get("url")))return t.setErrorNotice(""),void t.setAddToWidgetButtonDisabled(!0);e.match(/^(http|https):\/\/.+\//)||(t.controller.$el.find("#embed-url-field").addClass("invalid"),t.setAddToWidgetButtonDisabled(!0)),wp.media.view.EmbedLink.prototype.updateoEmbed.call(t)},fetch:function(){var t,e,i,n,d,o,a=this;if(d=a.model.get("url"),a.dfd&&"pending"===a.dfd.state()&&a.dfd.abort(),t=function(e){a.renderoEmbed({data:{body:e}}),a.controller.$el.find("#embed-url-field").removeClass("invalid"),a.setErrorNotice(""),a.setAddToWidgetButtonDisabled(!1)},(n=document.createElement("a")).href=d,e=n.pathname.toLowerCase().match(/\.(\w+)$/))return i=e[1],void(wp.media.view.settings.embedMimes[i]?0!==wp.media.view.settings.embedMimes[i].indexOf(a.controller.options.mimeType)?a.renderFail():t("\x3c!--success--\x3e"):a.renderFail());(o=/https?:\/\/www\.youtube\.com\/embed\/([^/]+)/.exec(d))&&(d="https://www.youtube.com/watch?v="+o[1],a.model.attributes.url=d),a.dfd=wp.apiRequest({url:wp.media.view.settings.oEmbedProxyUrl,data:{url:d,maxwidth:a.model.get("width"),maxheight:a.model.get("height"),discover:!1},type:"GET",dataType:"json",context:a}),a.dfd.done(function(e){a.controller.options.mimeType===e.type?t(e.html):a.renderFail()}),a.dfd.fail(_.bind(a.renderFail,a))},renderFail:function(){var e=this;e.controller.$el.find("#embed-url-field").addClass("invalid"),e.setErrorNotice(e.controller.options.invalidEmbedTypeError||"ERROR"),e.setAddToWidgetButtonDisabled(!0)}}),this.settings(new e({controller:this.controller,model:this.model.props,priority:40}))}}),g.MediaFrameSelect=wp.media.view.MediaFrame.Post.extend({createStates:function(){var t=this.options.mimeType,i=[];_.each(wp.media.view.settings.embedMimes,function(e){0===e.indexOf(t)&&i.push(e)}),0<i.length&&(t=i),this.states.add([new g.PersistentDisplaySettingsLibrary({id:"insert",title:this.options.title,selection:this.options.selection,priority:20,toolbar:"main-insert",filterable:"dates",library:wp.media.query({type:t}),multiple:!1,editable:!0,selectedDisplaySettings:this.options.selectedDisplaySettings,displaySettings:!!_.isUndefined(this.options.showDisplaySettings)||this.options.showDisplaySettings,displayUserSettings:!1}),new wp.media.controller.EditImage({model:this.options.editImage}),new wp.media.controller.Embed({metadata:this.options.metadata,type:"image"===this.options.mimeType?"image":"link",invalidEmbedTypeError:this.options.invalidEmbedTypeError})])},mainInsertToolbar:function(e){var i=this;e.set("insert",{style:"primary",priority:80,text:i.options.text,requires:{selection:!0},click:function(){var e=i.state(),t=e.get("selection");i.close(),e.trigger("insert",t).reset()}})},mainEmbedToolbar:function(e){e.view=new wp.media.view.Toolbar.Embed({controller:this,text:this.options.text,event:"insert"})},embedContent:function(){var e=new g.MediaEmbedView({controller:this,model:this.state()}).render();this.content.set(e)}}),g.MediaWidgetControl=Backbone.View.extend({l10n:{add_to_widget:"{{add_to_widget}}",add_media:"{{add_media}}"},id_base:"",mime_type:"",events:{"click .notice-missing-attachment a":"handleMediaLibraryLinkClick","click .select-media":"selectMedia","click .placeholder":"selectMedia","click .edit-media":"editMedia"},showDisplaySettings:!0,initialize:function(e){var i=this;if(Backbone.View.prototype.initialize.call(i,e),!(i.model instanceof g.MediaWidgetModel))throw new Error("Missing options.model");if(!e.el)throw new Error("Missing options.el");if(!e.syncContainer)throw new Error("Missing options.syncContainer");if(i.syncContainer=e.syncContainer,i.$el.addClass("media-widget-control"),_.bindAll(i,"syncModelToInputs","render","updateSelectedAttachment","renderPreview"),!i.id_base&&(_.find(g.controlConstructors,function(e,t){return i instanceof e&&(i.id_base=t,!0)}),!i.id_base))throw new Error("Missing id_base.");i.previewTemplateProps=new Backbone.Model(i.mapModelToPreviewTemplateProps()),i.selectedAttachment=new wp.media.model.Attachment,i.renderPreview=_.debounce(i.renderPreview),i.listenTo(i.previewTemplateProps,"change",i.renderPreview),i.model.on("change:attachment_id",i.updateSelectedAttachment),i.model.on("change:url",i.updateSelectedAttachment),i.updateSelectedAttachment(),i.listenTo(i.model,"change",i.syncModelToInputs),i.listenTo(i.model,"change",i.syncModelToPreviewProps),i.listenTo(i.model,"change",i.render),i.$el.on("input change",".title",function(){i.model.set({title:h.trim(h(this).val())})}),i.$el.on("input change",".link",function(){var e=h.trim(h(this).val()),t="custom";i.selectedAttachment.get("linkUrl")===e||i.selectedAttachment.get("link")===e?t="post":i.selectedAttachment.get("url")===e&&(t="file"),i.model.set({link_url:e,link_type:t}),i.displaySettings.set({link:t,linkUrl:e})}),i.displaySettings=new Backbone.Model(_.pick(i.mapModelToMediaFrameProps(_.extend(i.model.defaults(),i.model.toJSON())),_.keys(wp.media.view.settings.defaultProps)))},updateSelectedAttachment:function(){var e,t=this;0===t.model.get("attachment_id")?(t.selectedAttachment.clear(),t.model.set("error",!1)):t.model.get("attachment_id")!==t.selectedAttachment.get("id")&&(e=new wp.media.model.Attachment({id:t.model.get("attachment_id")})).fetch().done(function(){t.model.set("error",!1),t.selectedAttachment.set(e.toJSON())}).fail(function(){t.model.set("error","missing_attachment")})},syncModelToPreviewProps:function(){this.previewTemplateProps.set(this.mapModelToPreviewTemplateProps())},syncModelToInputs:function(){var n=this;n.syncContainer.find(".media-widget-instance-property").each(function(){var e,t,i=h(this);t=i.data("property"),e=n.model.get(t),_.isUndefined(e)||(e="array"===n.model.schema[t].type&&_.isArray(e)?e.join(","):"boolean"===n.model.schema[t].type?e?"1":"":String(e),i.val()!==e&&(i.val(e),i.trigger("change")))})},template:function(){if(!h("#tmpl-widget-media-"+this.id_base+"-control").length)throw new Error("Missing widget control template for "+this.id_base);return wp.template("widget-media-"+this.id_base+"-control")},render:function(){var e,t=this;t.templateRendered||(t.$el.html(t.template()(t.model.toJSON())),t.renderPreview(),t.templateRendered=!0),(e=t.$el.find(".title")).is(document.activeElement)||e.val(t.model.get("title")),t.$el.toggleClass("selected",t.isSelected())},renderPreview:function(){throw new Error("renderPreview must be implemented")},isSelected:function(){return!this.model.get("error")&&Boolean(this.model.get("attachment_id")||this.model.get("url"))},handleMediaLibraryLinkClick:function(e){e.preventDefault(),this.selectMedia()},selectMedia:function(){var e,i,t,n,d=this,o=[];d.isSelected()&&0!==d.model.get("attachment_id")&&o.push(d.selectedAttachment),e=new wp.media.model.Selection(o,{multiple:!1}),(n=d.mapModelToMediaFrameProps(d.model.toJSON())).size&&d.displaySettings.set("size",n.size),i=new g.MediaFrameSelect({title:d.l10n.add_media,frame:"post",text:d.l10n.add_to_widget,selection:e,mimeType:d.mime_type,selectedDisplaySettings:d.displaySettings,showDisplaySettings:d.showDisplaySettings,metadata:n,state:d.isSelected()&&0===d.model.get("attachment_id")?"embed":"insert",invalidEmbedTypeError:d.l10n.unsupported_file_type}),(wp.media.frame=i).on("insert",function(){var e={},t=i.state();"embed"===t.get("id")?_.extend(e,{id:0},t.props.toJSON()):_.extend(e,t.get("selection").first().toJSON()),d.selectedAttachment.set(e),d.model.set("error",!1),d.model.set(d.getModelPropsFromMediaFrame(i))}),t=wp.media.model.Attachment.prototype.sync,wp.media.model.Attachment.prototype.sync=function(e){return"delete"===e?t.apply(this,arguments):h.Deferred().rejectWith(this).promise()},i.on("close",function(){wp.media.model.Attachment.prototype.sync=t}),i.$el.addClass("media-widget"),i.open(),e&&e.on("destroy",function(e){d.model.get("attachment_id")===e.get("id")&&d.model.set({attachment_id:0,url:""})}),i.$el.find(".media-frame-menu .media-menu-item.active").focus()},getModelPropsFromMediaFrame:function(e){var t,i,n,d=this;if("insert"===(t=e.state()).get("id"))(i=t.get("selection").first().toJSON()).postUrl=i.link,d.showDisplaySettings&&_.extend(i,e.content.get(".attachments-browser").sidebar.get("display").model.toJSON()),i.sizes&&i.size&&i.sizes[i.size]&&(i.url=i.sizes[i.size].url);else{if("embed"!==t.get("id"))throw new Error("Unexpected state: "+t.get("id"));i=_.extend(t.props.toJSON(),{attachment_id:0},d.model.getEmbedResetProps())}return i.id&&(i.attachment_id=i.id),n=d.mapMediaToModelProps(i),_.each(wp.media.view.settings.embedExts,function(e){e in d.model.schema&&n.url!==n[e]&&(n[e]="")}),n},mapMediaToModelProps:function(e){var t,n=this,d={},o={};return _.each(n.model.schema,function(e,t){"title"!==t&&(d[e.media_prop||t]=t)}),_.each(e,function(e,t){var i=d[t]||t;n.model.schema[i]&&(o[i]=e)}),"custom"===e.size&&(o.width=e.customWidth,o.height=e.customHeight),"post"===e.link?o.link_url=e.postUrl||e.linkUrl:"file"===e.link&&(o.link_url=e.url),!e.attachment_id&&e.id&&(o.attachment_id=e.id),e.url&&(t=e.url.replace(/#.*$/,"").replace(/\?.*$/,"").split(".").pop().toLowerCase())in n.model.schema&&(o[t]=e.url),_.omit(o,"title")},mapModelToMediaFrameProps:function(e){var n=this,d={};return _.each(e,function(e,t){var i=n.model.schema[t]||{};d[i.media_prop||t]=e}),d.attachment_id=d.id,"custom"===d.size&&(d.customWidth=n.model.get("width"),d.customHeight=n.model.get("height")),d},mapModelToPreviewTemplateProps:function(){var i=this,n={};return _.each(i.model.schema,function(e,t){e.hasOwnProperty("should_preview_update")&&!e.should_preview_update||(n[t]=i.model.get(t))}),n.error=i.model.get("error"),n},editMedia:function(){throw new Error("editMedia not implemented")}}),g.MediaWidgetModel=Backbone.Model.extend({idAttribute:"widget_id",schema:{title:{type:"string",default:""},attachment_id:{type:"integer",default:0},url:{type:"string",default:""}},defaults:function(){var i={};return _.each(this.schema,function(e,t){i[t]=e.default}),i},set:function(e,t,i){var n,d,o,a=this;return null===e?a:(d="object"==typeof e?(n=e,t):((n={})[e]=t,i),o={},_.each(n,function(e,t){var i;a.schema[t]?"array"===(i=a.schema[t].type)?(o[t]=e,_.isArray(o[t])||(o[t]=o[t].split(/,/)),a.schema[t].items&&"integer"===a.schema[t].items.type&&(o[t]=_.filter(_.map(o[t],function(e){return parseInt(e,10)},function(e){return"number"==typeof e})))):o[t]="integer"===i?parseInt(e,10):"boolean"===i?!(!e||"0"===e||"false"===e):e:o[t]=e}),Backbone.Model.prototype.set.call(this,o,d))},getEmbedResetProps:function(){return{id:0}}}),g.modelCollection=new(Backbone.Collection.extend({model:g.MediaWidgetModel})),g.widgetControls={},g.handleWidgetAdded=function(e,t){var i,n,d,o,a,r,s,l,c,m,p;o=(d=t.find("> .widget-inside > .form, > .widget-inside > form")).find("> .id_base").val(),m=d.find("> .widget-id").val(),g.widgetControls[m]||(a=g.controlConstructors[o])&&(r=g.modelConstructors[o]||g.MediaWidgetModel,i=h("<div></div>"),(n=t.find(".widget-content:first")).before(i),s={},n.find(".media-widget-instance-property").each(function(){var e=h(this);s[e.data("property")]=e.val()}),s.widget_id=m,c=new r(s),l=new a({el:i,syncContainer:n,model:c}),(p=function(){t.hasClass("open")?l.render():setTimeout(p,50)})(),g.modelCollection.add([c]),g.widgetControls[c.get("widget_id")]=l)},g.setupAccessibleMode=function(){var e,t,i,n,d,o,a,r,s;0!==(e=h(".editwidget > form")).length&&(i=e.find("> .widget-control-actions > .id_base").val(),(d=g.controlConstructors[i])&&(t=e.find("> .widget-control-actions > .widget-id").val(),o=g.modelConstructors[i]||g.MediaWidgetModel,r=h("<div></div>"),(s=e.find("> .widget-inside")).before(r),a={},s.find(".media-widget-instance-property").each(function(){var e=h(this);a[e.data("property")]=e.val()}),a.widget_id=t,n=new d({el:r,syncContainer:s,model:new o(a)}),g.modelCollection.add([n.model]),(g.widgetControls[n.model.get("widget_id")]=n).render()))},g.handleWidgetUpdated=function(e,t){var i,n,d,o={};n=(i=t.find("> .widget-inside > .form, > .widget-inside > form")).find("> .widget-id").val(),(d=g.widgetControls[n])&&(i.find("> .widget-content").find(".media-widget-instance-property").each(function(){var e=h(this).data("property");o[e]=h(this).val()}),d.stopListening(d.model,"change",d.syncModelToInputs),d.model.set(o),d.listenTo(d.model,"change",d.syncModelToInputs))},g.init=function(){var e=h(document);e.on("widget-added",g.handleWidgetAdded),e.on("widget-synced widget-updated",g.handleWidgetUpdated),h(function(){"widgets"===window.pagenow&&(h(".widgets-holder-wrap:not(#available-widgets)").find("div.widget").one("click.toggle-widget-expanded",function(){var e=h(this);g.handleWidgetAdded(new jQuery.Event("widget-added"),e)}),h(window).on("load",function(){g.setupAccessibleMode()}))})},g}(jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/widgets/text-widgets.js b/srcs/wordpress/wp-admin/js/widgets/text-widgets.js deleted file mode 100644 index 184e724..0000000 --- a/srcs/wordpress/wp-admin/js/widgets/text-widgets.js +++ /dev/null @@ -1,552 +0,0 @@ -/** - * @output wp-admin/js/widgets/text-widgets.js - */ - -/* global tinymce, switchEditors */ -/* eslint consistent-this: [ "error", "control" ] */ - -/** - * @namespace wp.textWidgets - */ -wp.textWidgets = ( function( $ ) { - 'use strict'; - - var component = { - dismissedPointers: [], - idBases: [ 'text' ] - }; - - component.TextWidgetControl = Backbone.View.extend(/** @lends wp.textWidgets.TextWidgetControl.prototype */{ - - /** - * View events. - * - * @type {Object} - */ - events: {}, - - /** - * Text widget control. - * - * @constructs wp.textWidgets.TextWidgetControl - * @augments Backbone.View - * @abstract - * - * @param {Object} options - Options. - * @param {jQuery} options.el - Control field container element. - * @param {jQuery} options.syncContainer - Container element where fields are synced for the server. - * - * @returns {void} - */ - initialize: function initialize( options ) { - var control = this; - - if ( ! options.el ) { - throw new Error( 'Missing options.el' ); - } - if ( ! options.syncContainer ) { - throw new Error( 'Missing options.syncContainer' ); - } - - Backbone.View.prototype.initialize.call( control, options ); - control.syncContainer = options.syncContainer; - - control.$el.addClass( 'text-widget-fields' ); - control.$el.html( wp.template( 'widget-text-control-fields' ) ); - - control.customHtmlWidgetPointer = control.$el.find( '.wp-pointer.custom-html-widget-pointer' ); - if ( control.customHtmlWidgetPointer.length ) { - control.customHtmlWidgetPointer.find( '.close' ).on( 'click', function( event ) { - event.preventDefault(); - control.customHtmlWidgetPointer.hide(); - $( '#' + control.fields.text.attr( 'id' ) + '-html' ).focus(); - control.dismissPointers( [ 'text_widget_custom_html' ] ); - }); - control.customHtmlWidgetPointer.find( '.add-widget' ).on( 'click', function( event ) { - event.preventDefault(); - control.customHtmlWidgetPointer.hide(); - control.openAvailableWidgetsPanel(); - }); - } - - control.pasteHtmlPointer = control.$el.find( '.wp-pointer.paste-html-pointer' ); - if ( control.pasteHtmlPointer.length ) { - control.pasteHtmlPointer.find( '.close' ).on( 'click', function( event ) { - event.preventDefault(); - control.pasteHtmlPointer.hide(); - control.editor.focus(); - control.dismissPointers( [ 'text_widget_custom_html', 'text_widget_paste_html' ] ); - }); - } - - control.fields = { - title: control.$el.find( '.title' ), - text: control.$el.find( '.text' ) - }; - - // Sync input fields to hidden sync fields which actually get sent to the server. - _.each( control.fields, function( fieldInput, fieldName ) { - fieldInput.on( 'input change', function updateSyncField() { - var syncInput = control.syncContainer.find( '.sync-input.' + fieldName ); - if ( syncInput.val() !== fieldInput.val() ) { - syncInput.val( fieldInput.val() ); - syncInput.trigger( 'change' ); - } - }); - - // Note that syncInput cannot be re-used because it will be destroyed with each widget-updated event. - fieldInput.val( control.syncContainer.find( '.sync-input.' + fieldName ).val() ); - }); - }, - - /** - * Dismiss pointers for Custom HTML widget. - * - * @since 4.8.1 - * - * @param {Array} pointers Pointer IDs to dismiss. - * @returns {void} - */ - dismissPointers: function dismissPointers( pointers ) { - _.each( pointers, function( pointer ) { - wp.ajax.post( 'dismiss-wp-pointer', { - pointer: pointer - }); - component.dismissedPointers.push( pointer ); - }); - }, - - /** - * Open available widgets panel. - * - * @since 4.8.1 - * @returns {void} - */ - openAvailableWidgetsPanel: function openAvailableWidgetsPanel() { - var sidebarControl; - wp.customize.section.each( function( section ) { - if ( section.extended( wp.customize.Widgets.SidebarSection ) && section.expanded() ) { - sidebarControl = wp.customize.control( 'sidebars_widgets[' + section.params.sidebarId + ']' ); - } - }); - if ( ! sidebarControl ) { - return; - } - setTimeout( function() { // Timeout to prevent click event from causing panel to immediately collapse. - wp.customize.Widgets.availableWidgetsPanel.open( sidebarControl ); - wp.customize.Widgets.availableWidgetsPanel.$search.val( 'HTML' ).trigger( 'keyup' ); - }); - }, - - /** - * Update input fields from the sync fields. - * - * This function is called at the widget-updated and widget-synced events. - * A field will only be updated if it is not currently focused, to avoid - * overwriting content that the user is entering. - * - * @returns {void} - */ - updateFields: function updateFields() { - var control = this, syncInput; - - if ( ! control.fields.title.is( document.activeElement ) ) { - syncInput = control.syncContainer.find( '.sync-input.title' ); - control.fields.title.val( syncInput.val() ); - } - - syncInput = control.syncContainer.find( '.sync-input.text' ); - if ( control.fields.text.is( ':visible' ) ) { - if ( ! control.fields.text.is( document.activeElement ) ) { - control.fields.text.val( syncInput.val() ); - } - } else if ( control.editor && ! control.editorFocused && syncInput.val() !== control.fields.text.val() ) { - control.editor.setContent( wp.editor.autop( syncInput.val() ) ); - } - }, - - /** - * Initialize editor. - * - * @returns {void} - */ - initializeEditor: function initializeEditor() { - var control = this, changeDebounceDelay = 1000, id, textarea, triggerChangeIfDirty, restoreTextMode = false, needsTextareaChangeTrigger = false, previousValue; - textarea = control.fields.text; - id = textarea.attr( 'id' ); - previousValue = textarea.val(); - - /** - * Trigger change if dirty. - * - * @returns {void} - */ - triggerChangeIfDirty = function() { - var updateWidgetBuffer = 300; // See wp.customize.Widgets.WidgetControl._setupUpdateUI() which uses 250ms for updateWidgetDebounced. - if ( control.editor.isDirty() ) { - - /* - * Account for race condition in customizer where user clicks Save & Publish while - * focus was just previously given to the editor. Since updates to the editor - * are debounced at 1 second and since widget input changes are only synced to - * settings after 250ms, the customizer needs to be put into the processing - * state during the time between the change event is triggered and updateWidget - * logic starts. Note that the debounced update-widget request should be able - * to be removed with the removal of the update-widget request entirely once - * widgets are able to mutate their own instance props directly in JS without - * having to make server round-trips to call the respective WP_Widget::update() - * callbacks. See <https://core.trac.wordpress.org/ticket/33507>. - */ - if ( wp.customize && wp.customize.state ) { - wp.customize.state( 'processing' ).set( wp.customize.state( 'processing' ).get() + 1 ); - _.delay( function() { - wp.customize.state( 'processing' ).set( wp.customize.state( 'processing' ).get() - 1 ); - }, updateWidgetBuffer ); - } - - if ( ! control.editor.isHidden() ) { - control.editor.save(); - } - } - - // Trigger change on textarea when it has changed so the widget can enter a dirty state. - if ( needsTextareaChangeTrigger && previousValue !== textarea.val() ) { - textarea.trigger( 'change' ); - needsTextareaChangeTrigger = false; - previousValue = textarea.val(); - } - }; - - // Just-in-time force-update the hidden input fields. - control.syncContainer.closest( '.widget' ).find( '[name=savewidget]:first' ).on( 'click', function onClickSaveButton() { - triggerChangeIfDirty(); - }); - - /** - * Build (or re-build) the visual editor. - * - * @returns {void} - */ - function buildEditor() { - var editor, onInit, showPointerElement; - - // Abort building if the textarea is gone, likely due to the widget having been deleted entirely. - if ( ! document.getElementById( id ) ) { - return; - } - - // The user has disabled TinyMCE. - if ( typeof window.tinymce === 'undefined' ) { - wp.editor.initialize( id, { - quicktags: true, - mediaButtons: true - }); - - return; - } - - // Destroy any existing editor so that it can be re-initialized after a widget-updated event. - if ( tinymce.get( id ) ) { - restoreTextMode = tinymce.get( id ).isHidden(); - wp.editor.remove( id ); - } - - // Add or enable the `wpview` plugin. - $( document ).one( 'wp-before-tinymce-init.text-widget-init', function( event, init ) { - // If somebody has removed all plugins, they must have a good reason. - // Keep it that way. - if ( ! init.plugins ) { - return; - } else if ( ! /\bwpview\b/.test( init.plugins ) ) { - init.plugins += ',wpview'; - } - } ); - - wp.editor.initialize( id, { - tinymce: { - wpautop: true - }, - quicktags: true, - mediaButtons: true - }); - - /** - * Show a pointer, focus on dismiss, and speak the contents for a11y. - * - * @param {jQuery} pointerElement Pointer element. - * @returns {void} - */ - showPointerElement = function( pointerElement ) { - pointerElement.show(); - pointerElement.find( '.close' ).focus(); - wp.a11y.speak( pointerElement.find( 'h3, p' ).map( function() { - return $( this ).text(); - } ).get().join( '\n\n' ) ); - }; - - editor = window.tinymce.get( id ); - if ( ! editor ) { - throw new Error( 'Failed to initialize editor' ); - } - onInit = function() { - - // When a widget is moved in the DOM the dynamically-created TinyMCE iframe will be destroyed and has to be re-built. - $( editor.getWin() ).on( 'unload', function() { - _.defer( buildEditor ); - }); - - // If a prior mce instance was replaced, and it was in text mode, toggle to text mode. - if ( restoreTextMode ) { - switchEditors.go( id, 'html' ); - } - - // Show the pointer. - $( '#' + id + '-html' ).on( 'click', function() { - control.pasteHtmlPointer.hide(); // Hide the HTML pasting pointer. - - if ( -1 !== component.dismissedPointers.indexOf( 'text_widget_custom_html' ) ) { - return; - } - showPointerElement( control.customHtmlWidgetPointer ); - }); - - // Hide the pointer when switching tabs. - $( '#' + id + '-tmce' ).on( 'click', function() { - control.customHtmlWidgetPointer.hide(); - }); - - // Show pointer when pasting HTML. - editor.on( 'pastepreprocess', function( event ) { - var content = event.content; - if ( -1 !== component.dismissedPointers.indexOf( 'text_widget_paste_html' ) || ! content || ! /<\w+.*?>/.test( content ) ) { - return; - } - - // Show the pointer after a slight delay so the user sees what they pasted. - _.delay( function() { - showPointerElement( control.pasteHtmlPointer ); - }, 250 ); - }); - }; - - if ( editor.initialized ) { - onInit(); - } else { - editor.on( 'init', onInit ); - } - - control.editorFocused = false; - - editor.on( 'focus', function onEditorFocus() { - control.editorFocused = true; - }); - editor.on( 'paste', function onEditorPaste() { - editor.setDirty( true ); // Because pasting doesn't currently set the dirty state. - triggerChangeIfDirty(); - }); - editor.on( 'NodeChange', function onNodeChange() { - needsTextareaChangeTrigger = true; - }); - editor.on( 'NodeChange', _.debounce( triggerChangeIfDirty, changeDebounceDelay ) ); - editor.on( 'blur hide', function onEditorBlur() { - control.editorFocused = false; - triggerChangeIfDirty(); - }); - - control.editor = editor; - } - - buildEditor(); - } - }); - - /** - * Mapping of widget ID to instances of TextWidgetControl subclasses. - * - * @memberOf wp.textWidgets - * - * @type {Object.<string, wp.textWidgets.TextWidgetControl>} - */ - component.widgetControls = {}; - - /** - * Handle widget being added or initialized for the first time at the widget-added event. - * - * @memberOf wp.textWidgets - * - * @param {jQuery.Event} event - Event. - * @param {jQuery} widgetContainer - Widget container element. - * - * @returns {void} - */ - component.handleWidgetAdded = function handleWidgetAdded( event, widgetContainer ) { - var widgetForm, idBase, widgetControl, widgetId, animatedCheckDelay = 50, renderWhenAnimationDone, fieldContainer, syncContainer; - widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' ); // Note: '.form' appears in the customizer, whereas 'form' on the widgets admin screen. - - idBase = widgetForm.find( '> .id_base' ).val(); - if ( -1 === component.idBases.indexOf( idBase ) ) { - return; - } - - // Prevent initializing already-added widgets. - widgetId = widgetForm.find( '.widget-id' ).val(); - if ( component.widgetControls[ widgetId ] ) { - return; - } - - // Bypass using TinyMCE when widget is in legacy mode. - if ( ! widgetForm.find( '.visual' ).val() ) { - return; - } - - /* - * Create a container element for the widget control fields. - * This is inserted into the DOM immediately before the .widget-content - * element because the contents of this element are essentially "managed" - * by PHP, where each widget update cause the entire element to be emptied - * and replaced with the rendered output of WP_Widget::form() which is - * sent back in Ajax request made to save/update the widget instance. - * To prevent a "flash of replaced DOM elements and re-initialized JS - * components", the JS template is rendered outside of the normal form - * container. - */ - fieldContainer = $( '<div></div>' ); - syncContainer = widgetContainer.find( '.widget-content:first' ); - syncContainer.before( fieldContainer ); - - widgetControl = new component.TextWidgetControl({ - el: fieldContainer, - syncContainer: syncContainer - }); - - component.widgetControls[ widgetId ] = widgetControl; - - /* - * Render the widget once the widget parent's container finishes animating, - * as the widget-added event fires with a slideDown of the container. - * This ensures that the textarea is visible and an iframe can be embedded - * with TinyMCE being able to set contenteditable on it. - */ - renderWhenAnimationDone = function() { - if ( ! widgetContainer.hasClass( 'open' ) ) { - setTimeout( renderWhenAnimationDone, animatedCheckDelay ); - } else { - widgetControl.initializeEditor(); - } - }; - renderWhenAnimationDone(); - }; - - /** - * Setup widget in accessibility mode. - * - * @memberOf wp.textWidgets - * - * @returns {void} - */ - component.setupAccessibleMode = function setupAccessibleMode() { - var widgetForm, idBase, widgetControl, fieldContainer, syncContainer; - widgetForm = $( '.editwidget > form' ); - if ( 0 === widgetForm.length ) { - return; - } - - idBase = widgetForm.find( '> .widget-control-actions > .id_base' ).val(); - if ( -1 === component.idBases.indexOf( idBase ) ) { - return; - } - - // Bypass using TinyMCE when widget is in legacy mode. - if ( ! widgetForm.find( '.visual' ).val() ) { - return; - } - - fieldContainer = $( '<div></div>' ); - syncContainer = widgetForm.find( '> .widget-inside' ); - syncContainer.before( fieldContainer ); - - widgetControl = new component.TextWidgetControl({ - el: fieldContainer, - syncContainer: syncContainer - }); - - widgetControl.initializeEditor(); - }; - - /** - * Sync widget instance data sanitized from server back onto widget model. - * - * This gets called via the 'widget-updated' event when saving a widget from - * the widgets admin screen and also via the 'widget-synced' event when making - * a change to a widget in the customizer. - * - * @memberOf wp.textWidgets - * - * @param {jQuery.Event} event - Event. - * @param {jQuery} widgetContainer - Widget container element. - * @returns {void} - */ - component.handleWidgetUpdated = function handleWidgetUpdated( event, widgetContainer ) { - var widgetForm, widgetId, widgetControl, idBase; - widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' ); - - idBase = widgetForm.find( '> .id_base' ).val(); - if ( -1 === component.idBases.indexOf( idBase ) ) { - return; - } - - widgetId = widgetForm.find( '> .widget-id' ).val(); - widgetControl = component.widgetControls[ widgetId ]; - if ( ! widgetControl ) { - return; - } - - widgetControl.updateFields(); - }; - - /** - * Initialize functionality. - * - * This function exists to prevent the JS file from having to boot itself. - * When WordPress enqueues this script, it should have an inline script - * attached which calls wp.textWidgets.init(). - * - * @memberOf wp.textWidgets - * - * @returns {void} - */ - component.init = function init() { - var $document = $( document ); - $document.on( 'widget-added', component.handleWidgetAdded ); - $document.on( 'widget-synced widget-updated', component.handleWidgetUpdated ); - - /* - * Manually trigger widget-added events for media widgets on the admin - * screen once they are expanded. The widget-added event is not triggered - * for each pre-existing widget on the widgets admin screen like it is - * on the customizer. Likewise, the customizer only triggers widget-added - * when the widget is expanded to just-in-time construct the widget form - * when it is actually going to be displayed. So the following implements - * the same for the widgets admin screen, to invoke the widget-added - * handler when a pre-existing media widget is expanded. - */ - $( function initializeExistingWidgetContainers() { - var widgetContainers; - if ( 'widgets' !== window.pagenow ) { - return; - } - widgetContainers = $( '.widgets-holder-wrap:not(#available-widgets)' ).find( 'div.widget' ); - widgetContainers.one( 'click.toggle-widget-expanded', function toggleWidgetExpanded() { - var widgetContainer = $( this ); - component.handleWidgetAdded( new jQuery.Event( 'widget-added' ), widgetContainer ); - }); - - // Accessibility mode. - $( window ).on( 'load', function() { - component.setupAccessibleMode(); - }); - }); - }; - - return component; -})( jQuery ); diff --git a/srcs/wordpress/wp-admin/js/widgets/text-widgets.min.js b/srcs/wordpress/wp-admin/js/widgets/text-widgets.min.js deleted file mode 100644 index e886495..0000000 --- a/srcs/wordpress/wp-admin/js/widgets/text-widgets.min.js +++ /dev/null @@ -1 +0,0 @@ -wp.textWidgets=function(r){"use strict";var u={dismissedPointers:[],idBases:["text"]};return u.TextWidgetControl=Backbone.View.extend({events:{},initialize:function(t){var n=this;if(!t.el)throw new Error("Missing options.el");if(!t.syncContainer)throw new Error("Missing options.syncContainer");Backbone.View.prototype.initialize.call(n,t),n.syncContainer=t.syncContainer,n.$el.addClass("text-widget-fields"),n.$el.html(wp.template("widget-text-control-fields")),n.customHtmlWidgetPointer=n.$el.find(".wp-pointer.custom-html-widget-pointer"),n.customHtmlWidgetPointer.length&&(n.customHtmlWidgetPointer.find(".close").on("click",function(t){t.preventDefault(),n.customHtmlWidgetPointer.hide(),r("#"+n.fields.text.attr("id")+"-html").focus(),n.dismissPointers(["text_widget_custom_html"])}),n.customHtmlWidgetPointer.find(".add-widget").on("click",function(t){t.preventDefault(),n.customHtmlWidgetPointer.hide(),n.openAvailableWidgetsPanel()})),n.pasteHtmlPointer=n.$el.find(".wp-pointer.paste-html-pointer"),n.pasteHtmlPointer.length&&n.pasteHtmlPointer.find(".close").on("click",function(t){t.preventDefault(),n.pasteHtmlPointer.hide(),n.editor.focus(),n.dismissPointers(["text_widget_custom_html","text_widget_paste_html"])}),n.fields={title:n.$el.find(".title"),text:n.$el.find(".text")},_.each(n.fields,function(e,i){e.on("input change",function(){var t=n.syncContainer.find(".sync-input."+i);t.val()!==e.val()&&(t.val(e.val()),t.trigger("change"))}),e.val(n.syncContainer.find(".sync-input."+i).val())})},dismissPointers:function(t){_.each(t,function(t){wp.ajax.post("dismiss-wp-pointer",{pointer:t}),u.dismissedPointers.push(t)})},openAvailableWidgetsPanel:function(){var e;wp.customize.section.each(function(t){t.extended(wp.customize.Widgets.SidebarSection)&&t.expanded()&&(e=wp.customize.control("sidebars_widgets["+t.params.sidebarId+"]"))}),e&&setTimeout(function(){wp.customize.Widgets.availableWidgetsPanel.open(e),wp.customize.Widgets.availableWidgetsPanel.$search.val("HTML").trigger("keyup")})},updateFields:function(){var t,e=this;e.fields.title.is(document.activeElement)||(t=e.syncContainer.find(".sync-input.title"),e.fields.title.val(t.val())),t=e.syncContainer.find(".sync-input.text"),e.fields.text.is(":visible")?e.fields.text.is(document.activeElement)||e.fields.text.val(t.val()):e.editor&&!e.editorFocused&&t.val()!==e.fields.text.val()&&e.editor.setContent(wp.editor.autop(t.val()))},initializeEditor:function(){var d,t,o,e,s=this,a=1e3,l=!1,c=!1;t=s.fields.text,d=t.attr("id"),e=t.val(),o=function(){s.editor.isDirty()&&(wp.customize&&wp.customize.state&&(wp.customize.state("processing").set(wp.customize.state("processing").get()+1),_.delay(function(){wp.customize.state("processing").set(wp.customize.state("processing").get()-1)},300)),s.editor.isHidden()||s.editor.save()),c&&e!==t.val()&&(t.trigger("change"),c=!1,e=t.val())},s.syncContainer.closest(".widget").find("[name=savewidget]:first").on("click",function(){o()}),function t(){var e,i,n;if(document.getElementById(d))if(void 0!==window.tinymce){if(tinymce.get(d)&&(l=tinymce.get(d).isHidden(),wp.editor.remove(d)),r(document).one("wp-before-tinymce-init.text-widget-init",function(t,e){e.plugins&&(/\bwpview\b/.test(e.plugins)||(e.plugins+=",wpview"))}),wp.editor.initialize(d,{tinymce:{wpautop:!0},quicktags:!0,mediaButtons:!0}),n=function(t){t.show(),t.find(".close").focus(),wp.a11y.speak(t.find("h3, p").map(function(){return r(this).text()}).get().join("\n\n"))},!(e=window.tinymce.get(d)))throw new Error("Failed to initialize editor");i=function(){r(e.getWin()).on("unload",function(){_.defer(t)}),l&&switchEditors.go(d,"html"),r("#"+d+"-html").on("click",function(){s.pasteHtmlPointer.hide(),-1===u.dismissedPointers.indexOf("text_widget_custom_html")&&n(s.customHtmlWidgetPointer)}),r("#"+d+"-tmce").on("click",function(){s.customHtmlWidgetPointer.hide()}),e.on("pastepreprocess",function(t){var e=t.content;-1===u.dismissedPointers.indexOf("text_widget_paste_html")&&e&&/<\w+.*?>/.test(e)&&_.delay(function(){n(s.pasteHtmlPointer)},250)})},e.initialized?i():e.on("init",i),s.editorFocused=!1,e.on("focus",function(){s.editorFocused=!0}),e.on("paste",function(){e.setDirty(!0),o()}),e.on("NodeChange",function(){c=!0}),e.on("NodeChange",_.debounce(o,a)),e.on("blur hide",function(){s.editorFocused=!1,o()}),s.editor=e}else wp.editor.initialize(d,{quicktags:!0,mediaButtons:!0})}()}}),u.widgetControls={},u.handleWidgetAdded=function(t,e){var i,n,d,o,s,a,l;n=(i=e.find("> .widget-inside > .form, > .widget-inside > form")).find("> .id_base").val(),-1!==u.idBases.indexOf(n)&&(o=i.find(".widget-id").val(),u.widgetControls[o]||i.find(".visual").val()&&(a=r("<div></div>"),(l=e.find(".widget-content:first")).before(a),d=new u.TextWidgetControl({el:a,syncContainer:l}),u.widgetControls[o]=d,(s=function(){e.hasClass("open")?d.initializeEditor():setTimeout(s,50)})()))},u.setupAccessibleMode=function(){var t,e,i,n;0!==(t=r(".editwidget > form")).length&&(e=t.find("> .widget-control-actions > .id_base").val(),-1!==u.idBases.indexOf(e)&&t.find(".visual").val()&&(i=r("<div></div>"),(n=t.find("> .widget-inside")).before(i),new u.TextWidgetControl({el:i,syncContainer:n}).initializeEditor()))},u.handleWidgetUpdated=function(t,e){var i,n,d,o;o=(i=e.find("> .widget-inside > .form, > .widget-inside > form")).find("> .id_base").val(),-1!==u.idBases.indexOf(o)&&(n=i.find("> .widget-id").val(),(d=u.widgetControls[n])&&d.updateFields())},u.init=function(){var t=r(document);t.on("widget-added",u.handleWidgetAdded),t.on("widget-synced widget-updated",u.handleWidgetUpdated),r(function(){"widgets"===window.pagenow&&(r(".widgets-holder-wrap:not(#available-widgets)").find("div.widget").one("click.toggle-widget-expanded",function(){var t=r(this);u.handleWidgetAdded(new jQuery.Event("widget-added"),t)}),r(window).on("load",function(){u.setupAccessibleMode()}))})},u}(jQuery);
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/word-count.js b/srcs/wordpress/wp-admin/js/word-count.js deleted file mode 100644 index 999a42c..0000000 --- a/srcs/wordpress/wp-admin/js/word-count.js +++ /dev/null @@ -1,218 +0,0 @@ -/** - * Word or character counting functionality. Count words or characters in a - * provided text string. - * - * @namespace wp.utils - * @since 2.6.0 - * @output wp-admin/js/word-count.js - */ - -( function() { - /** - * Word counting utility - * - * @namespace wp.utils.wordcounter - * @memberof wp.utils - * - * @class - * - * @param {Object} settings Optional. Key-value object containing overrides for - * settings. - * @param {RegExp} settings.HTMLRegExp Optional. Regular expression to find HTML elements. - * @param {RegExp} settings.HTMLcommentRegExp Optional. Regular expression to find HTML comments. - * @param {RegExp} settings.spaceRegExp Optional. Regular expression to find irregular space - * characters. - * @param {RegExp} settings.HTMLEntityRegExp Optional. Regular expression to find HTML entities. - * @param {RegExp} settings.connectorRegExp Optional. Regular expression to find connectors that - * split words. - * @param {RegExp} settings.removeRegExp Optional. Regular expression to find remove unwanted - * characters to reduce false-positives. - * @param {RegExp} settings.astralRegExp Optional. Regular expression to find unwanted - * characters when searching for non-words. - * @param {RegExp} settings.wordsRegExp Optional. Regular expression to find words by spaces. - * @param {RegExp} settings.characters_excluding_spacesRegExp Optional. Regular expression to find characters which - * are non-spaces. - * @param {RegExp} settings.characters_including_spacesRegExp Optional. Regular expression to find characters - * including spaces. - * @param {RegExp} settings.shortcodesRegExp Optional. Regular expression to find shortcodes. - * @param {Object} settings.l10n Optional. Localization object containing specific - * configuration for the current localization. - * @param {String} settings.l10n.type Optional. Method of finding words to count. - * @param {Array} settings.l10n.shortcodes Optional. Array of shortcodes that should be removed - * from the text. - * - * @return void - */ - function WordCounter( settings ) { - var key, - shortcodes; - - // Apply provided settings to object settings. - if ( settings ) { - for ( key in settings ) { - - // Only apply valid settings. - if ( settings.hasOwnProperty( key ) ) { - this.settings[ key ] = settings[ key ]; - } - } - } - - shortcodes = this.settings.l10n.shortcodes; - - // If there are any localization shortcodes, add this as type in the settings. - if ( shortcodes && shortcodes.length ) { - this.settings.shortcodesRegExp = new RegExp( '\\[\\/?(?:' + shortcodes.join( '|' ) + ')[^\\]]*?\\]', 'g' ); - } - } - - // Default settings. - WordCounter.prototype.settings = { - HTMLRegExp: /<\/?[a-z][^>]*?>/gi, - HTMLcommentRegExp: /<!--[\s\S]*?-->/g, - spaceRegExp: / | /gi, - HTMLEntityRegExp: /&\S+?;/g, - - // \u2014 = em-dash - connectorRegExp: /--|\u2014/g, - - // Characters to be removed from input text. - removeRegExp: new RegExp( [ - '[', - - // Basic Latin (extract) - '\u0021-\u0040\u005B-\u0060\u007B-\u007E', - - // Latin-1 Supplement (extract) - '\u0080-\u00BF\u00D7\u00F7', - - /* - * The following range consists of: - * General Punctuation - * Superscripts and Subscripts - * Currency Symbols - * Combining Diacritical Marks for Symbols - * Letterlike Symbols - * Number Forms - * Arrows - * Mathematical Operators - * Miscellaneous Technical - * Control Pictures - * Optical Character Recognition - * Enclosed Alphanumerics - * Box Drawing - * Block Elements - * Geometric Shapes - * Miscellaneous Symbols - * Dingbats - * Miscellaneous Mathematical Symbols-A - * Supplemental Arrows-A - * Braille Patterns - * Supplemental Arrows-B - * Miscellaneous Mathematical Symbols-B - * Supplemental Mathematical Operators - * Miscellaneous Symbols and Arrows - */ - '\u2000-\u2BFF', - - // Supplemental Punctuation - '\u2E00-\u2E7F', - ']' - ].join( '' ), 'g' ), - - // Remove UTF-16 surrogate points, see https://en.wikipedia.org/wiki/UTF-16#U.2BD800_to_U.2BDFFF - astralRegExp: /[\uD800-\uDBFF][\uDC00-\uDFFF]/g, - wordsRegExp: /\S\s+/g, - characters_excluding_spacesRegExp: /\S/g, - - /* - * Match anything that is not a formatting character, excluding: - * \f = form feed - * \n = new line - * \r = carriage return - * \t = tab - * \v = vertical tab - * \u00AD = soft hyphen - * \u2028 = line separator - * \u2029 = paragraph separator - */ - characters_including_spacesRegExp: /[^\f\n\r\t\v\u00AD\u2028\u2029]/g, - l10n: window.wordCountL10n || {} - }; - - /** - * Counts the number of words (or other specified type) in the specified text. - * - * @since 2.6.0 - * @memberof wp.utils.wordcounter - * - * @param {String} text Text to count elements in. - * @param {String} type Optional. Specify type to use. - * - * @return {Number} The number of items counted. - */ - WordCounter.prototype.count = function( text, type ) { - var count = 0; - - // Use default type if none was provided. - type = type || this.settings.l10n.type; - - // Sanitize type to one of three possibilities: 'words', 'characters_excluding_spaces' or 'characters_including_spaces'. - if ( type !== 'characters_excluding_spaces' && type !== 'characters_including_spaces' ) { - type = 'words'; - } - - // If we have any text at all. - if ( text ) { - text = text + '\n'; - - // Replace all HTML with a new-line. - text = text.replace( this.settings.HTMLRegExp, '\n' ); - - // Remove all HTML comments. - text = text.replace( this.settings.HTMLcommentRegExp, '' ); - - // If a shortcode regular expression has been provided use it to remove shortcodes. - if ( this.settings.shortcodesRegExp ) { - text = text.replace( this.settings.shortcodesRegExp, '\n' ); - } - - // Normalize non-breaking space to a normal space. - text = text.replace( this.settings.spaceRegExp, ' ' ); - - if ( type === 'words' ) { - - // Remove HTML Entities. - text = text.replace( this.settings.HTMLEntityRegExp, '' ); - - // Convert connectors to spaces to count attached text as words. - text = text.replace( this.settings.connectorRegExp, ' ' ); - - // Remove unwanted characters. - text = text.replace( this.settings.removeRegExp, '' ); - } else { - - // Convert HTML Entities to "a". - text = text.replace( this.settings.HTMLEntityRegExp, 'a' ); - - // Remove surrogate points. - text = text.replace( this.settings.astralRegExp, 'a' ); - } - - // Match with the selected type regular expression to count the items. - text = text.match( this.settings[ type + 'RegExp' ] ); - - // If we have any matches, set the count to the number of items found. - if ( text ) { - count = text.length; - } - } - - return count; - }; - - // Add the WordCounter to the WP Utils. - window.wp = window.wp || {}; - window.wp.utils = window.wp.utils || {}; - window.wp.utils.WordCounter = WordCounter; -} )(); diff --git a/srcs/wordpress/wp-admin/js/word-count.min.js b/srcs/wordpress/wp-admin/js/word-count.min.js deleted file mode 100644 index fc89fcf..0000000 --- a/srcs/wordpress/wp-admin/js/word-count.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(){function e(e){var t,s;if(e)for(t in e)e.hasOwnProperty(t)&&(this.settings[t]=e[t]);(s=this.settings.l10n.shortcodes)&&s.length&&(this.settings.shortcodesRegExp=new RegExp("\\[\\/?(?:"+s.join("|")+")[^\\]]*?\\]","g"))}e.prototype.settings={HTMLRegExp:/<\/?[a-z][^>]*?>/gi,HTMLcommentRegExp:/<!--[\s\S]*?-->/g,spaceRegExp:/ | /gi,HTMLEntityRegExp:/&\S+?;/g,connectorRegExp:/--|\u2014/g,removeRegExp:new RegExp(["[","!-@[-`{-~","\x80-\xbf\xd7\xf7","\u2000-\u2bff","\u2e00-\u2e7f","]"].join(""),"g"),astralRegExp:/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,wordsRegExp:/\S\s+/g,characters_excluding_spacesRegExp:/\S/g,characters_including_spacesRegExp:/[^\f\n\r\t\v\u00AD\u2028\u2029]/g,l10n:window.wordCountL10n||{}},e.prototype.count=function(e,t){var s=0;return"characters_excluding_spaces"!==(t=t||this.settings.l10n.type)&&"characters_including_spaces"!==t&&(t="words"),e&&(e=(e=(e+="\n").replace(this.settings.HTMLRegExp,"\n")).replace(this.settings.HTMLcommentRegExp,""),this.settings.shortcodesRegExp&&(e=e.replace(this.settings.shortcodesRegExp,"\n")),e=e.replace(this.settings.spaceRegExp," "),(e=(e="words"===t?(e=(e=e.replace(this.settings.HTMLEntityRegExp,"")).replace(this.settings.connectorRegExp," ")).replace(this.settings.removeRegExp,""):(e=e.replace(this.settings.HTMLEntityRegExp,"a")).replace(this.settings.astralRegExp,"a")).match(this.settings[t+"RegExp"]))&&(s=e.length)),s},window.wp=window.wp||{},window.wp.utils=window.wp.utils||{},window.wp.utils.WordCounter=e}();
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/wp-fullscreen-stub.js b/srcs/wordpress/wp-admin/js/wp-fullscreen-stub.js deleted file mode 100644 index 490d18d..0000000 --- a/srcs/wordpress/wp-admin/js/wp-fullscreen-stub.js +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Distraction-Free Writing (wp-fullscreen) backward compatibility stub. - * - * @deprecated 4.1 - * @removed 4.3. - * @output wp-admin/js/wp-fullscreen-stub.js - */ -( function() { - var noop = function(){}; - - window.wp = window.wp || {}; - window.wp.editor = window.wp.editor || {}; - window.wp.editor.fullscreen = { - bind_resize: noop, - dfwWidth: noop, - off: noop, - on: noop, - refreshButtons: noop, - resizeTextarea: noop, - save: noop, - switchmode: noop, - toggleUI: noop, - - settings: {}, - pubsub: { - publish: noop, - subscribe: noop, - unsubscribe: noop, - topics: {} - }, - fade: { - In: noop, - Out: noop - }, - ui: { - fade: noop, - init: noop - } - }; -}()); diff --git a/srcs/wordpress/wp-admin/js/wp-fullscreen-stub.min.js b/srcs/wordpress/wp-admin/js/wp-fullscreen-stub.min.js deleted file mode 100644 index 3654ff2..0000000 --- a/srcs/wordpress/wp-admin/js/wp-fullscreen-stub.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(){function i(){}window.wp=window.wp||{},window.wp.editor=window.wp.editor||{},window.wp.editor.fullscreen={bind_resize:i,dfwWidth:i,off:i,on:i,refreshButtons:i,resizeTextarea:i,save:i,switchmode:i,toggleUI:i,settings:{},pubsub:{publish:i,subscribe:i,unsubscribe:i,topics:{}},fade:{In:i,Out:i},ui:{fade:i,init:i}}}();
\ No newline at end of file diff --git a/srcs/wordpress/wp-admin/js/xfn.js b/srcs/wordpress/wp-admin/js/xfn.js deleted file mode 100644 index b72540d..0000000 --- a/srcs/wordpress/wp-admin/js/xfn.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Generates the XHTML Friends Network 'rel' string from the inputs. - * - * @deprecated 3.5.0 - * @output wp-admin/js/xfn.js - */ -jQuery( document ).ready(function( $ ) { - $( '#link_rel' ).prop( 'readonly', true ); - $( '#linkxfndiv input' ).bind( 'click keyup', function() { - var isMe = $( '#me' ).is( ':checked' ), inputs = ''; - $( 'input.valinp' ).each( function() { - if ( isMe ) { - $( this ).prop( 'disabled', true ).parent().addClass( 'disabled' ); - } else { - $( this ).removeAttr( 'disabled' ).parent().removeClass( 'disabled' ); - if ( $( this ).is( ':checked' ) && $( this ).val() !== '') { - inputs += $( this ).val() + ' '; - } - } - }); - $( '#link_rel' ).val( ( isMe ) ? 'me' : inputs.substr( 0,inputs.length - 1 ) ); - }); -}); diff --git a/srcs/wordpress/wp-admin/js/xfn.min.js b/srcs/wordpress/wp-admin/js/xfn.min.js deleted file mode 100644 index f85f743..0000000 --- a/srcs/wordpress/wp-admin/js/xfn.min.js +++ /dev/null @@ -1 +0,0 @@ -jQuery(document).ready(function(n){n("#link_rel").prop("readonly",!0),n("#linkxfndiv input").bind("click keyup",function(){var e=n("#me").is(":checked"),i="";n("input.valinp").each(function(){e?n(this).prop("disabled",!0).parent().addClass("disabled"):(n(this).removeAttr("disabled").parent().removeClass("disabled"),n(this).is(":checked")&&""!==n(this).val()&&(i+=n(this).val()+" "))}),n("#link_rel").val(e?"me":i.substr(0,i.length-1))})});
\ No newline at end of file |
