Cum să încarci scripturi doar dacă un anumit shortcode sau widget este prezent
Am avut nevoie de o metodă pentru a filtra conținutul unei pagini/articole înainte de încărcare, pentru a putea adăuga scripturi în header dacă un anumit shortcode era prezent. După multă căutare, am dat peste această soluție pe http://wpengineer.com
function has_my_shortcode($posts) {
if ( empty($posts) )
return $posts;
$found = false;
foreach ($posts as $post) {
if ( stripos($post->post_content, '[my_shortcode') )
$found = true;
break;
}
if ($found){
$urljs = get_bloginfo( 'template_directory' ).IMP_JS;
wp_register_script('my_script', $urljs.'myscript.js' );
wp_print_scripts('my_script');
}
return $posts;
}
add_action('the_posts', 'has_my_shortcode');
care este absolut genială și a făcut exact ce aveam nevoie.
Acum trebuie să extind funcționalitatea pentru a face același lucru și pentru bara laterală. Poate fi prin detectarea unui anumit tip de widget, shortcode, fragment de cod sau orice altceva care ar putea identifica momentul în care scriptul trebuie încărcat.
Problema este că nu pot să găsesc cum să accesez conținutul barelor laterale înainte ca acestea să fie încărcate (tema în cauză are mai multe bare laterale).

Puteți utiliza funcția is_active_widget. De exemplu:
function check_widget() {
if( is_active_widget( '', '', 'search' ) ) { // verifică dacă widget-ul de căutare este utilizat
wp_enqueue_script('my-script');
}
}
add_action( 'init', 'check_widget' );
Pentru a încărca scriptul doar în pagina unde este încărcat widget-ul, va trebui să adăugați codul is_active_widget() în clasa widget-ului dumneavoastră. De exemplu, vedeți widget-ul implicit pentru comentarii recente (wp-includes/default-widgets.php, linia 602):
class WP_Widget_Recent_Comments extends WP_Widget {
function WP_Widget_Recent_Comments() {
$widget_ops = array('classname' => 'widget_recent_comments', 'description' => __( 'Cele mai recente comentarii' ) );
$this->WP_Widget('recent-comments', __('Comentarii Recente'), $widget_ops);
$this->alt_option_name = 'widget_recent_comments';
if ( is_active_widget(false, false, $this->id_base) )
add_action( 'wp_head', array(&$this, 'recent_comments_style') );
add_action( 'comment_post', array(&$this, 'flush_widget_cache') );
add_action( 'transition_comment_status', array(&$this, 'flush_widget_cache') );
}

Poate fi apelat ÎNAINTE de încărcarea widget-urilor. Pentru a fi clar, acest lucru trebuie să aibă loc chiar înainte de încărcarea paginii. Codul meu exemplu folosește the_posts pentru a filtra conținutul de pe pagină, dar asta nu include sidebarele/widget-urile.

De fapt, așa era. wp_enqueue_script nu pare să funcționeze atunci când este aplicat la wp_head, dar wp_print_scripts funcționează. Totuși, wp_enqueue_script funcționează dacă este aplicat la init astfel: add_action( 'init', 'check_widget' );

Cu toate acestea, încarcă scripturile pe fiecare pagină a site-ului, chiar dacă widget-ul este activ doar într-o singură bară laterală. De exemplu, dacă am o bară laterală pentru paginile de blog și o altă bară laterală pentru alte pagini. Adaug widget-ul de căutare în bara laterală a blogului și scripturile se încarcă, dar se încarcă și pe paginile care nu au bara laterală a blogului. Trebuie să pot încărca scriptul doar dacă widget-ul este prezent pe acea pagină.

Am vrut să împărtășesc o soluție la care am lucrat, care mi-a oferit mai multă versatilitate în implementare. În loc să am o funcție care să verifice o varietate de shortcode-uri, am modificat-o să caute un singur shortcode care face referire la o funcție de script/stil care trebuie încărcată. Aceasta va funcționa atât pentru metode din alte clase (cum ar fi plugin-uri care nu fac asta în mod automat), cât și pentru funcții în scopul curent. Pur și simplu adăugați codul de mai jos în functions.php și folosiți următoarea sintaxă în orice pagină/post unde doriți CSS și JS specific.
Sintaxă pentru Pagină/Post: [loadCSSandJS function="(nume_clasă->metodă/nume_funcție)"]
Cod pentru functions.php:
function page_specific_CSSandJS( $posts ) {
if ( empty( $posts ) )
return $posts;
foreach ($posts as $post) {
$returnValue = preg_match_all('#\[loadCSSandJS function="([A-z\-\>]+)"\]#i', $post->post_content, $types);
foreach($types[1] as $type) {
$items = explode("->",$type);
if (count($items) == 2) {
global $$items[0];
if( method_exists( $$items[0], $items[1] ))
add_action( 'wp_enqueue_scripts', array(&$$items[0], $items[1]) );
}
else if( !empty( $type ) && function_exists( $type ))
add_action( 'wp_enqueue_scripts', $type );
}
}
return $posts;
}
Această soluție vă permite, de asemenea, să adăugați câte funcții doriți pe o pagină. Rețineți că aveți nevoie de o metodă/funcție care să facă încărcarea.

cu WordPress 4.7 există o altă modalitate de a realiza acest lucru în fișierul tău functions.php
,
add_action( 'wp_enqueue_scripts', 'register_my_script');
function register_my_script(){
wp_register_script('my-shortcode-js',$src, $dependency, $version, $inFooter);
}
mai întâi îți înregistrezi scriptul, care nu va fi afișat efectiv pe pagină decât dacă îl adaugi în coadă atunci când shortcode-ul tău este apelat,
add_filter( 'do_shortcode_tag','enqueue_my_script',10,3);
function enqueue_my_script($output, $tag, $attr){
if('myShortcode' != $tag){ //verifică dacă este shortcode-ul corect
return $output;
}
if(!isset($attr['id'])){ //poți verifica chiar și pentru atribute specifice
return $output;
}
wp_enqueue_script('my-shortcode-js'); //adaugă scriptul în coadă pentru afișare
return $output;
}
filtrul do_shortcode_tag
a fost introdus în WP 4.7 și poate fi găsit în noile pagini de documentație pentru dezvoltatori.

Mulțumesc pentru acest pont!
Mi-a cauzat puțină migrenă, deoarece la început nu funcționa. Cred că sunt câteva greșeli (poate tipografice) în codul de mai sus has_my_shortcode
și am rescris funcția astfel:
function has_my_shortcode( $posts ) {
if ( empty($posts) )
return $posts;
$shortcode_found = false;
foreach ($posts as $post) {
if ( !( stripos($post->post_content, '[my-shortcode') === false ) ) {
$shortcode_found = true;
break;
}
}
if ( $shortcode_found ) {
$this->add_scripts();
$this->add_styles();
}
return $posts;
}
Cred că au fost două probleme principale: break
nu se afla în sfera instrucțiunii if, iar acest lucru a făcut ca bucla să se întrerupă întotdeauna la prima iterație. Cealaltă problemă a fost mai subtilă și mai greu de descoperit. Codul de mai sus nu funcționează dacă shortcode-ul este chiar primul lucru scris într-un articol. A trebuit să folosesc operatorul ===
pentru a rezolva acest lucru.
Oricum, mulțumesc mult pentru împărtășirea acestei tehnici, a fost de mare ajutor.
