1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027 |
- /**
- * @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,
- __ = wp.i18n.__, _n = wp.i18n._n, sprintf = wp.i18n.sprintf;
- component = {
- 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).
- * @return {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 __( 'The changes you made will be lost if you navigate away from this page.' );
- }
- 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
- * @return {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' ).trigger( '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.
- * @return {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
- * @return {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
- * @return {void}
- */
- component.onChange = function() {
- component.dirty = true;
- component.removeNotice( 'file_saved' );
- };
- /**
- * Submit file via Ajax.
- *
- * @since 4.9.0
- * @param {jQuery.Event} event - Event.
- * @return {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: __( 'Something went wrong. Your change may not have been saved. Please try again. There is also a chance that you may need to manually fix and upload the file over FTP.' )
- },
- 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.
- * @return {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.
- * @return {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
- * @return {void}
- */
- component.initCodeEditor = function initCodeEditor() {
- var codeEditorSettings, editor;
- codeEditorSettings = $.extend( {}, component.codeEditor );
- /**
- * Handle tabbing to the field before the editor.
- *
- * @since 4.9.0
- *
- * @return {void}
- */
- codeEditorSettings.onTabPrevious = function() {
- $( '#templateside' ).find( ':tabbable' ).last().trigger( 'focus' );
- };
- /**
- * Handle tabbing to the field after the editor.
- *
- * @since 4.9.0
- *
- * @return {void}
- */
- codeEditorSettings.onTabNext = function() {
- $( '#template' ).find( ':tabbable:not(.CodeMirror-code)' ).first().trigger( 'focus' );
- };
- /**
- * Handle change to the linting errors.
- *
- * @since 4.9.0
- *
- * @param {Array} errors - List of linting errors.
- * @return {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.
- * @return {void}
- */
- codeEditorSettings.onUpdateErrorNotice = function onUpdateErrorNotice( errorAnnotations ) {
- var noticeElement;
- component.submitButton.toggleClass( 'disabled', errorAnnotations.length > 0 );
- if ( 0 !== errorAnnotations.length ) {
- noticeElement = component.addNotice({
- code: 'lint_errors',
- type: 'error',
- message: sprintf(
- /* translators: %s: Error count. */
- _n(
- 'There is %s error which must be fixed before you can update this file.',
- 'There are %s errors which must be fixed before you can update this file.',
- errorAnnotations.length
- ),
- String( errorAnnotations.length )
- ),
- 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
- * @return {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 );
- /**
- * Removed in 5.5.0, needed for back-compatibility.
- *
- * @since 4.9.0
- * @deprecated 5.5.0
- *
- * @type {object}
- */
- wp.themePluginEditor.l10n = wp.themePluginEditor.l10n || {
- saveAlert: '',
- saveError: '',
- lintError: {
- alternative: 'wp.i18n',
- func: function() {
- return {
- singular: '',
- plural: ''
- };
- }
- }
- };
- wp.themePluginEditor.l10n = window.wp.deprecateL10nObject( 'wp.themePluginEditor.l10n', wp.themePluginEditor.l10n, '5.5.0' );
|