Elegantly using JavaScript on widget admin forms

I’m working on a project involving a lot of widgets, and I’m thinking it’d be really great to have a “More options” section built using jQuery UI Accordion that expands when clicked.

So, I’ve enqueued ‘jquery-ui-accordion’ using the ‘admin_enqueue_scripts’ action:

function add_my_deps() {
    wp_enqueue_script('jquery-ui-accordion');
}    
add_action( 'admin_enqueue_scripts', 'add_my_deps' );

…And my JavaScript looks something like this:

(function($){
    $('.more-options-expansible').accordion();
})(jQuery)

Now what?

If I enqueue that via the “add_my_deps” action above, it only works if I reload the page (I.e., when placing the widget, the JavaScript is instantiated before the element is created; if the widget is saved, its JavaScript is enqueued as normal and it instantiates as normal.).

If I place that in a <script> tag at the end of my HTML output in my widget’s form() method, I get the following exception: Uncaught TypeError: Object [object Object] has no method 'accordion'. This is because it seems to be instantiating the accordion via the inline <script> before the jQuery UI Accordion library is loaded.

Is there something obvious I’m missing? I’m using a simple jQuery instantiation for this example, but it seems like I’d have even worse issues if I tried to do anything using AJAX (Namely, how would I select the appropriate element to place the response in? Is this something I need to start using Backbone.js to accomplish?).

Any help?

3 Answers
3

One way around this I’ve discovered since posting the above question is to instantiate inline via WP_Widget::form(), with wp_enqueue_script() loading the necessary JavaScript (exactly as mentioned above) — except, and here’s the key part, load the JavaScript in the header instead of the footer (fifth argument of wp_enqueue_script()).

Which makes a lot of sense now that I think about it.

Even still, I hate using inline JavaScript — ever — and loading everything in the header is less than ideal.

As such, am leaving this question open in case anyone has a better idea.

Leave a Comment