JQuery AJAX Post and Refresh Page Content without reload page

Now I know that I am at risk here of asking a duplicate question, however I don’t really know what to search for because I am a complete AJAX jQuery noob. Believe me, I have tried searching what I think is the obvious, with no luck so please go easy on me.

I have a php wordpress site which shows prices in GBP as default. At the top, is a select box with onchange="this.form.submit()" which allows the user to change the default currency that all prices are quoted in.

Read More
<form method="post" action="">
    <select name="ChangeCurrency" onChange="this.form.submit()">
        <option value="GBP">GBP</option>
        <option value="USD">USD</option>
        <option value="EUR">EUR</option>
    </select>
</form>

On the home page, are several, what I call “shortcode widgets”, each one containing products and price tables. A dashboard if you like.

How it currently works (inefficient):

  1. User changes select.
  2. Form submitted
  3. Homepage reloaded with updated prices in selected currency.

This is not good, because whenever somebody changes currency, the whole page is reloaded (this takes time, transfers approx 1mb without caching, not to mention unnecessary load on the server).

What I want (more efficient):

  1. When the select box is changed, I wish to asynchronously post the form which changes the currency session variable.
  2. Each “shortcode widget” is updated one by one without having to reload the entire page.

Is this something that jquery can do? where do I start?

Just in case it makes any difference so that you can see what I mean, here is the URL so that you can see what I am talking about… http://bit.ly/10ChZys

PART 2:
I have used jQuery and ajax to update the fixTable thanks to a mashup of answers below… I am using session variables to store the users choice, that way, if they return to the site, the option will be saved.

I am having problems with my code because the session variable stored within http://goldealers.co.uk/wp-content/plugins/gd/tables.php?currency=GBP&table=fixTable appears to have a different session_id to the user’s session id because the option is no longer stored.

Is there a way of telling the server that they are one and the same session?

SOLUTION
I used Ribot’s Solution to start with which worked and solved the initial problem, then extended with NomikOS’s solution…

Related posts

Leave a Reply

3 comments

  1. NOTE: this answer show some ideas about the php backend for the AJAX process. It is a complement for the other answers talking about the frontend process.

    1.- a mockup to manage AJAX request in WP, just some ideas, ok?

    add_action('init', 'process_ajax_callback');
    
    function process_ajax_callback()
    {
        if ( ! $_REQUEST['go_ajax'])
        {
            return;
        }
    
        try
        {
            if (isset($_REQUEST['nonce_my_ajax']))
            {
                $nonce   = $_REQUEST['nonce_my_ajax'];
                if ( ! wp_verify_nonce($nonce    = $_REQUEST['nonce_my_ajax'], 'nonce_my_ajax'))
                {
                    throw new Exception("Nonce token invalid."); // security
                }
            }
        }
        catch (Exception $e)
        {
            $output['result']    = false;
            $output['message']   = $e->getMessage();
    
            echo json_encode($output);
            exit;
        }
    
        $result  = true;
        $message = '';
    
        switch ($_REQUEST['action'])
        {
            case 'update_price':
            try
            {
                // update price
                // price value comes in $_REQUEST['price']
            }
            catch (Exception $e)
            {
                $result              = false;
                $message             = $e->getMessage();
            }
            break;      
    
            case 'other_actions':
            break;      
        }
    
        $output['result']    = $result ? true : false;
        $output['message']   = $message;
    
        echo json_encode($output);
        exit;
    }
    

    2.- don’t forget security

    // nonce_my_ajax is passed to javascript like this:
    wp_localize_script('my_js_admin', 'myJsVars', array(
        'nonce_my_ajax'  => wp_create_nonce('nonce_my_ajax')
    ));
    

    3.- in general the needed in the frontend (to use with the backend mockup showed above) is something like:

    $("select[name='ChangeCurrency']").live("change", function() {
        var price = $(this).val();
        $.post(
                window.location.href,
                {
                    go_ajax : 1, // parse ajax
                    action : 'update_price', // what to do
                    price : price, // vars to use in backend
                    nonce_my_ajax : myJsVars.nonce_my_ajax // security
                },
                function(output) {
                if ( output.result == true )
                    // update widgets or whatever
                    // $("#my_div").html("we happy, yabadabadoo!");
                    // or do nothing (AJAX action was successful)
                else
                    alert(output.message)
                }, 'json');
    });
    

    4.- You can use $.get() or $.post() to send/process data to/in server but .load() is not good when you update DB because you can’t manage returning messages of failures with the precision of a json response (for example: multiples validation error messages). Just use .load() to load HTML views.

    UPDATE:

    Set session_id() where can be executed both for normal requests and for ajax requests and at the early stage as possible. I hope you are using a class to wrap your plugin, if not now is the right moment to do it… example:

    class my_plugin {
    
        function __construct()
        {
            if ( ! session_id())
            {
                session_start();
            }
    
            add_action('init', array($this, 'process_ajax_callback'));
    
            // ...
        }   
    
        function process_ajax_callback()
        {
            // ...
        }
    }
    

    UPDATE 2:

    About nonce based security:

    A security feature available in WordPress is a “nonce”. Generally, a
    “nonce” is a token that can only be used once and are often used to
    prevent unauthorised people from submitting data on behalf of another
    person.

    Ref: http://myatus.com/p/wordpress-caching-and-nonce-lifespan/

    In this mockup nonce_my_ajax is just an example, indeed it should be more unique like nonce_{my_plugin_name}, or even better nonce_{my_plugin_name}_{what_action} where what_action represents updating user, or inserting new book, etc…

    More info about it: WP Codex: WordPress Nonces, WPtuts+: Capabilities and Nonces.

  2. Yes, jQuery can do it using ajax.

    First of all, when using ajax, you don’t have to post a form to get the data. Ajax in jQuery will load the text data of an url.

    You may start by giving your select an id (here id=”changeCurrency”) and:

    $("#changeCurrency").change(function(){
        currency = $('#changeCurrency option:selected').val() // get the selected option's value
        $("#some_div").load("someurl.php?currency=" + currency);
    });
    

    Now read up on jQuery and ajax for what kind of ajax call you need to do that suites your needs the best.

  3. Drop the onchange and add an ID

    <select name="ChangeCurrency" id="ChangeCurrency">...
    

    On the page give all your prices a price in your base currency as well as outputting them

    <span class="price" data-base="0.12">&pound;0.12</span>
    

    In your JS have a conversion table

    // base currency is GBP
    // each currency has 0: currency symbol, 1: conversion rate
    var currency={"GBP":["&pound;", 1], "USD":["&dollar;", 0.67]};
    var usercurrency=currency['GBP'];
    

    and bind an event to the change

    $('#ChangeCurrency').on('change', function(){
        // post to the server to update it
        $.post(...);
        // set locally on the page
        usercurrency=currency[$(this).val()];
        // and change all the values
        $('.price').each(function(){
            $(this).html(usercurrency[0] + (usercurrency[1] * $(this).data('base')).toFixed(2) );
        });
    }).trigger('change'); // trigger this to run on page load if you want.
    

    I haven’t checked any of this code