Current File : /home/honehdyv/readbtooom.com/wp-content/plugins/autodescription/lib/js/pt.js |
/**
* This file holds The SEO Framework plugin's JS code for Primary Term Selection.
* Serve JavaScript as an addition, not as an ends or means.
*
* @author Sybre Waaijer <https://cyberwire.nl/>
* @link <https://wordpress.org/plugins/autodescription/>
*/
/**
* The SEO Framework plugin
* Copyright (C) 2019 - 2023 Sybre Waaijer, CyberWire B.V. (https://cyberwire.nl/)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
'use strict';
/**
* Holds tsfPT (tsf primary term) values in an object to avoid polluting global namespace.
*
* This is a self-constructed function assigned as an object.
* This also is deprecated in favor for `pt-gb.js`.
*
* We might de-jQuery-fy this, though. TODO let's do it... Classic Editor won't go away.
*
* @since 3.1.0
*
* @constructor
* @param {!jQuery} $ jQuery object.
*/
window.tsfPT = function( $ ) {
/**
* Data property injected by WordPress l10n handler.
*
* @since 4.0.0
* @access public
* @type {(Object<string, *>)|boolean|null} l10n Localized strings
*/
const l10n = 'undefined' !== typeof tsfPTL10n && tsfPTL10n;
/**
* Initializes primary term selection.
*
* @since 3.0.0
* @since 3.0.4 1 : Added postbox toggle event listeners for help display correction.
* 2 : Added tab visibility checkers.
*
* @function
*/
const _initPrimaryTerm = () => {
if ( ! Object.keys( l10n.taxonomies ).length ) return;
let taxonomies = l10n.taxonomies,
inputTemplate = wp.template( 'tsf-primary-term-selector' ),
helpTemplate = wp.template( 'tsf-primary-term-selector-help' );
let termSelector = document.createElement( 'span' );
termSelector.classList.add( 'tsf-primary-term-selector', 'tsf-set-primary-term' );
(() => {
let radio = document.createElement( 'input' );
radio.setAttribute( 'type', 'radio' );
termSelector.appendChild( radio );
})();
// These are better set as Maps... oh well, Classic Editor will be with us for only 10 more years.
let input$ = {},
checked$ = {},
uniqueChecked$ = {},
box$ = {},
primaries = {};
// Namespaces an action for jQuery
const nsAction = ( action, taxonomy ) => `${action}.tsfShowPrimary${taxonomy}`;
const addInput = taxonomy => {
let $wrap = $( `#${taxonomy}div` ),
template = inputTemplate( { taxonomy: taxonomies[ taxonomy ] } );
$wrap.append( template );
}
const addHelp = taxonomy => {
let $wrap = $( `#taxonomy-${taxonomy}` ),
template = helpTemplate( { taxonomy: taxonomies[ taxonomy ] } ),
$ulChild = $wrap.children( 'ul:first' );
if ( $ulChild.length ) {
$( template ).insertAfter( $ulChild ); // Maintain tab order.
} else {
$wrap.prepend( template );
}
tsfTT.triggerReset();
fixHelpPos( taxonomy );
}
const fixHelpPos = taxonomy => {
let wrap = document.getElementById( `taxonomy-${taxonomy}` ),
tabs = wrap.querySelectorAll( '.tabs-panel' );
let postbox = wrap.closest( '.postbox' );
if ( postbox && postbox.classList.contains( 'closed' ) ) return;
let tab = [].slice.call( tabs ).filter( el => {
return el.offsetWidth > 0 || el.offsetHeight > 0 || el.getClientRects().length > 0;
} )[0];
if ( ! tab ) return;
let offset = tab.scrollHeight > tab.clientHeight
? tab.offsetWidth - tab.clientWidth + 25 - 2 // 2px is padding or something?
: 25;
if ( window.isRtl ) {
wrap.querySelector( '.tsf-primary-term-selector-help-wrap' ).style.left = `${offset}px`;
} else {
wrap.querySelector( '.tsf-primary-term-selector-help-wrap' ).style.right = `${offset}px`;
}
}
const fixHelpPosOnTabToggle = event => {
fixHelpPos( event.data.taxonomy );
}
const createSelector = taxonomy => {
let selector = termSelector.cloneNode( true );
selector.setAttribute( 'title', taxonomies[ taxonomy ].i18n.makePrimary );
selector.setAttribute( 'aria-label', taxonomies[ taxonomy ].i18n.makePrimary );
return selector;
}
const setPostValue = ( taxonomy, value ) => {
let element = document.getElementById( `autodescription[_primary_term_${taxonomy}]` );
if ( element && element instanceof Element )
element.value = value || 0;
}
const getBox = ( taxonomy, reset ) => {
if ( ! reset && box$[ taxonomy ] )
return box$[ taxonomy ];
box$[ taxonomy ] = $( `#${taxonomy}checklist, #${taxonomy}checklist-pop` );
return box$[ taxonomy ];
}
const getInputWithVal = ( taxonomy, value ) => input$[ taxonomy ].filter( `[value="${value}"]` );
const makePrimary = ( taxonomy, value ) => {
let $label = getInputWithVal( taxonomy, value ).closest( 'label' );
if ( $label.length ) {
$label.addClass( 'tsf-is-primary-term' );
$label.find( '.tsf-set-primary-term' ).each( function( index, e ) {
e.setAttribute( 'title', taxonomies[ taxonomy ].i18n.primary );
e.setAttribute( 'aria-label', taxonomies[ taxonomy ].i18n.primary );
e.querySelector( 'input' ).checked = true;
} );
setPostValue( taxonomy, value );
primaries[ taxonomy ] = value;
} else {
makeFirstPrimary( taxonomy );
}
}
const unsetPrimaries = taxonomy => {
let $label = getBox( taxonomy ).find( 'label' );
$label.removeClass( 'tsf-is-primary-term' );
$label.find( '.tsf-set-primary-term' ).each( function( index, e ) {
e.setAttribute( 'title', taxonomies[ taxonomy ].i18n.makePrimary );
e.setAttribute( 'aria-label', taxonomies[ taxonomy ].i18n.makePrimary );
e.querySelector( 'input' ).checked = false;
} );
setPostValue( taxonomy, 0 );
primaries[ taxonomy ] = 0;
}
const makeFirstPrimary = taxonomy => {
let $checked = uniqueChecked$[ taxonomy ].first(),
value;
if ( $checked.length ) {
value = $checked.val() || '';
makePrimary( taxonomy, value );
primaries[ taxonomy ] = value;
} else {
primaries[ taxonomy ] = 0;
}
}
const setPrimary = event => {
let taxonomy = event.data.taxonomy;
if ( event.target instanceof HTMLInputElement ) {
// Stop the loop.
event.stopPropagation();
$( event.target ).closest( '.tsf-set-primary-term' ).trigger( nsAction( 'click', taxonomy ) );
// Forward default: Check the button.
return true;
}
unsetPrimaries( taxonomy );
makePrimary( taxonomy, $( event.target ).closest( 'label' ).find( 'input[type=checkbox]' ).val() );
//= Stop default, don't deselect the term.
return false;
}
const toggleShowSwitch = event => {
let taxonomy = event.data.taxonomy;
if ( event.target.checked ) {
addCheckedNode( taxonomy, event.target );
appendButton( taxonomy, event.target );
} else {
removeCheckedNode( taxonomy, event.target );
removeButton( taxonomy, event.target );
}
switch ( uniqueChecked$[ taxonomy ].length ) {
case 0:
unsetPrimaries( taxonomy );
break;
case 1:
makeFirstPrimary( taxonomy );
break;
}
}
const appendButton = ( taxonomy, element ) => {
let $label, selector;
getInputWithVal( taxonomy, element.value ).each( ( index, e ) => {
$label = $( e ).closest( 'label' );
if ( ! $label.find( '.tsf-primary-term-selector' ).length ) {
selector = createSelector( taxonomy );
$label.find( 'input' ).after( selector );
}
} );
}
const removeButton = ( taxonomy, element ) => {
let $label, wasPrimary;
getInputWithVal( taxonomy, element.value ).each( ( index, e ) => {
$label = $( e ).closest( 'label' );
wasPrimary = $label.hasClass( 'tsf-is-primary-term' );
$label.removeClass( 'tsf-is-primary-term' );
// This should also remove all attached events.
$label.find( '.tsf-primary-term-selector' ).remove();
if ( wasPrimary ) makeFirstPrimary( taxonomy );
} );
}
const addCheckedNode = ( taxonomy, element ) => {
checked$[ taxonomy ] = checked$[ taxonomy ].add( `[value="${element.value}"]` );
uniqueChecked$[ taxonomy ] = uniqueChecked$[ taxonomy ].add( element );
}
const removeCheckedNode = ( taxonomy, element ) => {
checked$[ taxonomy ] = checked$[ taxonomy ].not( `[value="${element.value}"]` );
uniqueChecked$[ taxonomy ] = uniqueChecked$[ taxonomy ].not( `[value="${element.value}"]` );
}
const togglePostbox = ( event, postbox ) => {
fixHelpPos( event.data.taxonomy );
}
const initVars = taxonomy => {
let $box = getBox( taxonomy, 1 );
input$[ taxonomy ] = $box.find( 'input[type=checkbox]' );
checked$[ taxonomy ] = $box.find( 'input[type=checkbox]:checked' );
let found = {}, val;
uniqueChecked$[ taxonomy ] = checked$[ taxonomy ];
uniqueChecked$[ taxonomy ].each( ( index, element ) => {
val = $( element ).val();
if ( found[ val ] ) {
uniqueChecked$[ taxonomy ].splice( index, 1 );
} else {
found[ val ] = true;
}
} );
}
const updateList = ( event, settings, wpList ) => {
if ( wpList.hasOwnProperty( 'settings' ) && wpList.settings.hasOwnProperty( 'what' ) ) {
initVars( wpList.settings.what );
initActions( wpList.settings.what );
reload( wpList.settings.what );
fixHelpPos( wpList.settings.what );
}
}
const initActions = taxonomy => {
let data = { taxonomy },
$box = getBox( taxonomy ),
$div = $( `#${taxonomy}div` ),
$tabs = $( `#${taxonomy}-tabs` ),
$postbox = $box.closest( '.postbox' );
let defaultClickAction = nsAction( 'click', taxonomy );
$box.off( defaultClickAction )
.on( defaultClickAction, 'input[type=checkbox]', data, toggleShowSwitch )
.on( defaultClickAction, '.tsf-primary-term-selector', data, setPrimary );
$div.off( nsAction( 'wpListAddEnd', taxonomy ) )
.on( nsAction( 'wpListAddEnd', taxonomy ), `#${taxonomy}checklist`, updateList );
$tabs.off( defaultClickAction )
.on( defaultClickAction, 'a', data, fixHelpPosOnTabToggle );
$postbox.off( nsAction( 'click.postboxes', taxonomy ) )
.on( nsAction( 'click.postboxes', taxonomy ), data, togglePostbox );
}
const reload = taxonomy => {
getBox( taxonomy ).find( 'input[type=checkbox]:checked' )
.each( ( index, element ) => {
appendButton( taxonomy, element );
} );
if ( primaries[ taxonomy ] ) {
// One has been set previously via this script, reselect it.
makePrimary( taxonomy, primaries[ taxonomy ] );
} else {
// Select one according to WordPress's term list sorting.
makeFirstPrimary( taxonomy );
}
}
const load = taxonomy => {
getBox( taxonomy ).find( 'input[type=checkbox]:checked' )
.each( ( index, element ) => {
appendButton( taxonomy, element );
} );
if ( taxonomies[ taxonomy ].primary ) {
// One has been saved earlier via this script.
makePrimary( taxonomy, taxonomies[ taxonomy ].primary );
} else {
// Select one according to WordPress's term list sorting.
makeFirstPrimary( taxonomy );
}
}
// Hook data handles, don't overwrite vars.
const init = () => {
for ( let taxonomy in taxonomies ) {
if ( getBox( taxonomy ).length ) {
addInput( taxonomy );
addHelp( taxonomy );
initVars( taxonomy );
initActions( taxonomy );
load( taxonomy );
}
}
}
init();
}
return Object.assign( {
/**
* Initialises all aspects of the scripts.
* You shouldn't call this.
*
* @since 3.1.0
* @access protected
*
* @function
*/
load: () => {
document.body.addEventListener( 'tsf-onload', _initPrimaryTerm );
}
}, {
l10n
} );
}( jQuery );
window.tsfPT.load();