Aggiungere onload al body in WordPress
Sto attualmente sviluppando un plugin che incorporerà un Tour di Google Earth in un post/pagina WP tramite shortcode.
Il problema che sto riscontrando è che per far caricare il tour, devo aggiungere un onload="init()"
nel tag <body>
.
Posso modificare un file template specifico, ma trattandosi di una release, devo aggiungerlo dinamicamente tramite un hook. Qualche idea?

Ed ecco una soluzione jQuery (come suggerito da Mike nel suo primo commento).
function add_my_scripts() {
wp_enqueue_script( 'jquery' );
wp_enqueue_script( 'my_init_script', SCRIPTSRC, 'jquery', '1.0' );
}
add_action( 'init', 'add_my_scripts' );
Quindi aggiungi uno script al tuo plugin che faccia questo:
jQuery.noConflict();
jQuery(document).ready(function($) {
init();
});
Questo avvierà jQuery in modalità no conflict (se non lo è già) e aggiungerà una chiamata al metodo init()
quando il documento è pronto. È un metodo più sicuro da usare rispetto a body onready()
perché la funzione onready()
può chiamare solo una cosa... quindi nessun altro può agganciarvi qualcosa o aggiungere script personalizzati. È meglio rendere il tuo plugin il meno intrusivo possibile, così altri plugin non interferiranno o viceversa.

Penso che il tuo sia uno dei metodi preferiti. Credo che il codice jQuery possa essere addirittura ridotto, perché jQuery offre una scorciatoia alla funzione ready.

@EAMann - Puoi spiegare meglio jQuery.noConflict()? Non l'ho mai usato e la documentazione non mi è stata chiara.

Di default, jQuery imposta il simbolo $
come sinonimo di jQuery
... questo può rompere altre librerie (Prototype, Scriptaculous, ecc.) e può anche compromettere funzioni $
definite dall'utente. Usando jQuery.noConflict()
si disabilita questa impostazione predefinita, ma puoi ancora usare la funzione $
nel tuo codice se la passi come parametro... quindi la funzione che ho definito sopra potrebbe usare $.ajax
e altre chiamate native all'interno della funzione definita.

@MikeSchinkel: http://hakre.wordpress.com/2010/08/11/selekturz-they-iz-serius-bizniss/

@EAMann - Grazie. Sapevo dell'uso all'interno della funzione ready() ma non avevo realizzato che ci sarebbe stato un conflitto se non avessi mai usato il $ al di fuori di una chiusura. Ancora non capisco cosa faccia. Forse dovrei semplicemente fare qualche ricerca in più...

@MikeSchinkel - Di default, jQuery imposta il simbolo globale $
come alias per l'oggetto jQuery. Invocare jQuery in modalità noConflict()
sovrascrive questa impostazione predefinita.

Ecco un approccio. Dovresti aggiungere la chiamata add_action()
all'interno del tuo hook, credo. Il JavaScript che includo presume che la funzione init sia già stata definita. Se non lo è, allora questo fallirà, ma includere lo script sembra un problema che hai già risolto, se ho capito bene. Nota che non è necessariamente necessario aggiungerlo a wp_foot
, potresti altrettanto facilmente aggiungerlo a wp_head
:
<?php
function mypluginprefix_onload_init() { ?>
<script language="text/javascript">
// controlla il modo standard per aggiungere eventi onload
if ( typeof(window.addEventListener) !== 'undefined' )
window.addEventListener( "load", init, false );
// o il vecchio modo non standard di msie
else if ( typeof(window.attachEvent) !== 'undefined' ) {
window.attachEvent( "onload", init );
}
</script>
<?php }
// questo va nel tuo hook
add_action('wp_foot', 'mypluginprefix_onload_event');
?>

Perché JavaScript diretto e non jQuery? jQuery gestisce tutti i casi limite in cui il codice potrebbe essere eseguito prima che la pagina sia completamente caricata.

Per un semplice onload, penso che jQuery sia eccessivo. Basta allegare il gestore e il gioco è fatto. jQuery comporta un costo in termini di overhead per il download. Amo jQuery, ma non è la soluzione a tutto. Ora, se jQuery fosse già in coda, allora direi di usarlo, ma la mia risposta fa a meno di esso.

Ignorando la possibilità di farlo con jQuery, una cosa che potresti fare è agganciare il filtro template_include
e usare ob_start()
con una callback. La tua callback può poi cercare la stringa '<body'
e sostituirla con '<body onload="init()"'
come fa il seguente codice. Dovresti essere in grado di inserirlo direttamente nel tuo plugin, assicurati solo di cambiare i nomi per seguire la convenzione di denominazione del tuo plugin:
<?php
add_filter('template_include','start_buffer_capture',1);
function start_buffer_capture($template) {
ob_start('end_buffer_capture'); // Avvia il buffer della pagina
return $template;
}
function end_buffer_capture($buffer) {
return str_replace('<body','<body onload="init()"',$buffer);
}
Nota che, se fossi in te, non darei per scontato che il codice sopra sia già completamente robusto. Dubito che gestirà tutti i casi limite visto che l'ho buttato giù velocemente per rispondere alla tua domanda, ma almeno ti mostra come gestire il caso normale. Con qualche test sugli use case sono sicuro che riuscirai a fargli gestire anche i casi limite importanti (tipo cosa succede se '<BODY'
è in maiuscolo, ecc.)

Ecco del codice JavaScript per aggiungere dinamicamente una callback al caricamento della pagina, con o senza jQuery:
function add_onload() {
?>
<script type="text/javascript">
my_onload_callback = function() { alert('Ciao!'); }; // funzione di test
if( typeof jQuery == "function" ) {
jQuery(my_onload_callback); // document.ready
} else {
document.getElementsByTagName('body')[0].onload = my_onload_callback; // body.onload
}
</script>
<?php
}
add_action( 'wp_footer', 'add_onload' );
Nel tuo caso dovresti semplicemente sostituire my_onload_callback con il tuo metodo init.

Ho fatto ulteriori ricerche e ho trovato un modo "migliore" per farlo funzionare (Google rende difficile l'embed dei loro Earth Tours, e il loro gadget non funziona).
Alla fine ho creato un plugin che utilizza una combinazione di shortcode e un campo personalizzato.

Se puoi, ti consiglierei di pubblicare il codice a beneficio di altre persone che troveranno questo post.

Sì, sarebbe anche utile per capire meglio quello che hai chiesto inizialmente. Domanda e risposta dovrebbero andare insieme.

Per chiunque possa volerlo, ecco il plugin. È ospitato sul repository di WP http://wordpress.org/extend/plugins/google-earth-tours/
