Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm currently trying to develop a plugin that will embed a Google Earth Tour into a WP post / page via a shortcode.

The issue I am running into is that for the tour to load, I have to add an onload="init()" into the <body> tag.

I can modify a specific template file, but since this is for release, I need to add it dynamically via a hook. Any ideas?

share|improve this question
    
Is it not possible to use unintrusive Javascript via jQuery? –  MikeSchinkel Aug 25 '10 at 7:20

5 Answers 5

Ignoring the potential to do this with jQuery one thing you could do is hook the template_include filter and use ob_start() with a callback. Your callback can then do a string search on '<body' and replace it with '<body onload="init()"' like the following code does. You should be able to drop it directly in your plugin, just be sure to change the names to follow your plugin's own naming convention:

<?php
add_filter('template_include','start_buffer_capture',1);
function start_buffer_capture($template) {
  ob_start('end_buffer_capture');  // Start Page Buffer
  return $template;
}
function end_buffer_capture($buffer) {
  return str_replace('<body','<body onload="init()"',$buffer);
}

Note that I would not assume the above code to be fully robust yet if I were you. I doubt it will handle all edge cases since I just threw it together to answer your question but minimally it shows you how to accomplish the normal case, and then with some use-case testing I'm sure you'' get it to handle all the important edge cases (like what if '<BODY' is uppercase, etc?)

share|improve this answer

Here's some JavaScript to dynamically add a callback to the page load, with or without jQuery:

function add_onload() {
    ?>
    <script type="text/javascript">
    my_onload_callback = function() { alert('Hello!'); }; // test function

    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' );

In your case you would just replace the my_onload_callbacks with your init method.

share|improve this answer

Here's an approach. You would add the the add_action() call inside your hook, I believe. The JavaScript I include presumes that the init function has already been defined. If it has not, then this will fail, but including the script seems like a problem you've already solved if I'm understanding you right. Note that you don't necessarily need to add it to wp_foot, you could just as easily add it to wp_head:

<?php

function mypluginprefix_onload_init() { ?>
<script language="text/javascript">
// check for the standards-compliant way to add onload events
if ( typeof(window.addEventListener) !== 'undefined' )
    window.addEventListener( "load", init, false );
// or the older msie nonstandard way
else if ( typeof(window.attachEvent) !== 'undefined' ) {
    window.attachEvent( "onload", init );
}
</script>
<?php }

// this goes in your hook
add_action('wp_foot', 'mypluginprefix_onload_event');
?>
share|improve this answer
    
Why direct Javascript and not jQuery? jQuery handles all the edge cases where code can run before the page is fully loaded. –  MikeSchinkel Aug 25 '10 at 18:16
2  
For a simple onload, I think jQuery is overkill. Just attach the handler and be done. jQuery comes with a cost in overhead in terms of download. I love jQuery, but it's not the answer to everything. Now, if jQuery were already queued, then I'd say use it, but my answer does without it. –  artlung Aug 25 '10 at 19:00

And here's a jQuery solution (as Mike suggested in his first comment).

function add_my_scripts() {
    wp_enqueue_script('jquery');
    wp_enqueue_script('my_init_script', SCRIPTSRC, 'jquery', '1.0');
}
add_action('init', 'add_my_scripts');

Then add a script to your plug-in that does this:

jQuery.noConflict();

jQuery(document).ready(function($) {
    init();
}

This will start jQuery in no conflict mode (if it isn't already) and add a call to the init() method when the document is ready. It's a safer method to use than body onready() because the onready() function can only call one thing ... so no one else can hook anything to that or add custom script. It's better to make your plug-in as unobtrusive as possible so other plug-ins don't interfere or vice-versa.

share|improve this answer
    
I think that yours is on of the preferred methods. I think the jQuery code can even be reduced, because jQuery offers a shortcut to the ready function. –  hakre Aug 25 '10 at 16:02
    
@EAMann - Can you better explain the jQuery.noConflict()? I've never used and the docs were not clear to me. –  MikeSchinkel Aug 25 '10 at 18:17
1  
By default, jQuery sets the $ symbol as a synonym for jQuery ... this will break other libraries (Prototype, Scriptaculous, etc) and can break user-defined $ functions as well. Using jQuery.noConflict() disable this default, but you can still use the $ function in your code if you pass it in ... so the function I defined above could use $.ajax and other native calls inside the defined function. –  EAMann Aug 25 '10 at 18:35
    
    
@EAMann - Thanks. I knew about using inside the ready() function but I didn't realize that there would be a conflict if you simply never use the $ outside of a closure. I still don't see what it does. Maybe I should just go research a bit more... –  MikeSchinkel Aug 27 '10 at 23:49
up vote 0 down vote accepted

Did some more digging and found a 'better' way to get it working (Google makes it hard to get their damn Earth Tours embedded, and their gadget doesn't work).

I ended up making a plugin that uses a combination of a shortcode and a custom field.

share|improve this answer
    
If you're able, I'd recommend posting the code for the benefit of others who find this post. –  Annika Backstrom Aug 26 '10 at 15:45
    
Yeah would be even helpful to better understand for what you have asked for in the first place. Question and Answer should go together. –  hakre Aug 27 '10 at 22:46
    
For anyone that might want it, here's the plugin. It's hosted on the WP repository wordpress.org/extend/plugins/google-earth-tours –  Norcross Sep 14 '10 at 20:54
    
You can accept your own answer, to indicate that the problem is solved for you. –  Jan Fabry Nov 4 '10 at 18:02

protected by toscho Dec 16 at 7:18

Thank you for your interest in this question. Because it has attracted low-quality answers, posting an answer now requires 10 reputation on this site.

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.