Enabling jquery when dragging available widget to sidebar area

I know this issue from this Q&A: Update widget form after drag-and-drop (WP save bug).

I was answering a Stack Overflow question and faced the same problem. We have to add an AjaxComplete action and fire our function when XMLHttpRequest.responseText is true. I’m not sure about the inner workings but we only have to modify one line in the following code (by onetrickpony):

// https://wordpress.stackexchange.com/a/37707
jQuery( document ).ajaxComplete( function( event, XMLHttpRequest, ajaxOptions ) {
    // determine which ajax request is this (we're after "save-widget")
    var request = {}, pairs = ajaxOptions.data.split('&'), i, split, widget;
    for( i in pairs ) {
        split = pairs[i].split( '=' );
        request[decodeURIComponent( split[0] )] = decodeURIComponent( split[1] );
    }
    // only proceed if this was a widget-save request
    if( request.action && ( request.action === 'save-widget' ) ) {
        // locate the widget block
        widget = jQuery('input.widget-id[value="' + request['widget-id'] + '"]').parents('.widget');
        
        // trigger manual save, if this was the save request 
        // and if we didn't get the form html response (the wp bug)
        if( !XMLHttpRequest.responseText ) 
            wpWidgets.save(widget, 0, 1, 0);
            
        // we got an response, this could be either our request above,
        // or a correct widget-save call, so fire an event on which we can hook our js
        else
            jQuery('DO_OUR_STUFF');
    }
});

Demo plugin

<?php
/* Plugin Name: Demo Widget jQuery Damit */

add_action( 'widgets_init', 'b5f_load_widgets' );

function b5f_load_widgets() {
    register_widget( 'B5F_Example_Widget' );
}

class B5F_Example_Widget extends WP_Widget {
    private $url;
    
    function B5F_Example_Widget() {
        $this->url = plugins_url( '/test-me.js', __FILE__ );
        $widget_ops = array( 'classname' => 'example', 'description' => '' );
        $control_ops = array( 'width' => 300, 'height' => 350, 'id_base' => 'example-widget' );
        $this->WP_Widget( 'example-widget','Example Widget', $widget_ops, $control_ops );
        if( is_admin() )
            wp_enqueue_script( 'test-me', $this->url, array(), false, true );
    }

    function widget( $args, $instance ) {
        echo 'Test';
    }

    function update( $new_instance, $old_instance ) {
        return $instance;
    }

    function form( $instance ) {
        echo "<a href="#" class="test-me">File to load: {$this->url}</a>";
    }
}

And onetrickpony’s code adapted to our widget (/wp-content/our-plugin/test-me.js):

// Common function to do the Trick and our jQuery action
function test_click() {
    var number = 1 + Math.floor( Math.random() * 5000000 );
    jQuery( this ).html( 'WordPress Answers #' + number );
}

// Our jQuery
jQuery( document ).ready( function( $ ) {
    $( '.test-me' ).click( test_click );
});

// OneTrick's
// https://wordpress.stackexchange.com/a/37707
jQuery( document ).ajaxComplete( function( event, XMLHttpRequest, ajaxOptions ) {
    var request = {}, pairs = ajaxOptions.data.split('&'), i, split, widget;
    for( i in pairs ) {
        split = pairs[i].split( '=' );
        request[decodeURIComponent( split[0] )] = decodeURIComponent( split[1] );
    }

    if( request.action && ( request.action === 'save-widget' ) ) {
        widget = jQuery('input.widget-id[value="' + request['widget-id'] + '"]').parents('.widget');
        if( !XMLHttpRequest.responseText ) 
            wpWidgets.save(widget, 0, 1, 0);
        else
            jQuery( '.test-me' ).click( test_click ); // <--- One trick, pony!
    }
});

Leave a Comment