User:Jonas Lund/jQueryAjax

From XPUB & Lens-Based wiki

Ajax request to Python cgi script (Simple)

Like in the next recipe, the following two scripts will use a jQuery's Ajax function in an HTML file, to send an asynchronous request to a (cgi) Python script, the input will be processed and send back to the HTML page.

HTML Note: jquery required;

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <h1>Test Ajax POST</h1>
    <form id="postform">
        <input type="text" name="myquery" id="query" />
    </form>
    <input id="submit" type="submit" name="submit" value="Go!">
    <p id="response"></p>
    <script type="text/javascript" src="js/jquery-1.11.1.min.js"></script>
    <script type="text/javascript">

$('input#submit').click(
    function(){
        var formVal= $("#query").val();

        //Ajax POST
        $.ajax({
            contentType:"application/json",
            type: "POST",
            data:JSON.stringify({'myquery': formVal}),
            dataType:"json",
            url: "http://localhost/cgi-bin/test_ajax.cgi", //the url of	the cgi	scrip\
t
            success: function(data){
        	console.log('success');
        	if(data){
                    console.log(data.success, data.msg);
                   $('p#response').text(data.msg)
        	}

            }
        })

    }
)
  </script>
</body>
</html>

Python (cgi) script, located inside the cgi-bin

#!/usr/bin/env python                                                                         
import cgitb; cgitb.enable()
import cgi, os, json, sys

method = os.environ.get("REQUEST_METHOD")

if method == "POST":
   myjson =  json.load(sys.stdin) #receive JSON object send from Ajax call                    
   myquery=myjson['myquery'] #in JSON look for value of key 'myquery'                         

# JSON response                                                                               
result = {'success':'true', 'msg':myquery + " was posted by you"}
print "Content-type: application/json\n\n"
print json.dumps(result)


Note: If the HTML page and the CGI script are not in the same server - Cross-Origin Request Blocked - when you submit the Ajax request, your browser will complain about the different origins of the 2, and wont send the request. There is a away around it. Look for it :)



The following is a little more elaborate, but the principal is the same.

How to do Simple Ajax Request with jQuery

An easy way of sending a python script data (from an html file) and retrieving a result, is by using jQuery's Ajax function, to send an asynchronous request to the python script and process what the script outputs.

A simple jQuery ajax requests looks like this

$.ajax({ 
  //What Type Of Request (GET or POST)
  type: 'POST',
  //The Data you send to the script 
  data: {name: val},
  //Url of script  
  url: 'http://yourdomain.com/python.py',
  
  //success function, when the request has successfully completed
  //the data is the variable in which the returned output from the python script is stored
  success: function(data) { 
  }
});

There's a lot more you can do, have a look here for the full documentation. http://api.jquery.com/category/ajax/


So, let's look at some real examples of using this together with a python script. We'll be using the Image Merger as an example.

Here's our index.html, contains our form which we'll use for user input. We send the input from the form to the python script, and then get some data back, in this case a url to an image, which we prepend to the body, by creating a new img element and setting the src to the returned data.

<!doctype html>
<!-- check for IE browsers to make it easier to target with css -->
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en"> <![endif]-->
<!--[if IE 7]>    <html class="no-js ie7 oldie" lang="en"> <![endif]-->
<!--[if IE 8]>    <html class="no-js ie8 oldie" lang="en"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <title>Image Merger</title>
  <meta name="description" content="Image Merger">
  <meta name="author" content="Image Merger">
  <meta name="viewport" content="width=device-width,initial-scale=1">
 
  <style>
    body, html {width: 100%;}
    html {margin: 0; padding: 0;}
    body {font: 14px/1.3 sans-serif; color: #333;}
    #search-form {position: absolute; top: 20px; right: 20px; width: 300px;}
    #loader {display: none; position: fixed; top: 20px; left: 0; text-align: center;}
    img {margin: 20px;}
    #results {text-align: center; width: 100%;}
  </style>
</head>
 
<body>  
  <!-- Loading Icon -->
  <div id="loader">
    <img src="http://pzwart3.wdka.hro.nl/~jlund/imger/loader.gif"/>
  </div> 

 <!-- Our Search Form -->
  <div id="search-form" role="main">
      <form action="http://pzwart3.wdka.hro.nl/~jlund/cgi-bin/imger.py" method="POST" id="search">
          <label for="query">Search for...</label>
          <input type="text" name="query" id="query" />
          <input type="submit" name="submit" value="Go!">        
      </form>
  </div>

  <!-- Container for our results --> 
  <div id="results">
    
  </div>
  
  <!-- Get jQuery from Google CDN, at the bottom -->
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
  <!-- If it fails, load the local version -->
  <script>window.jQuery || document.write('<script src="js/libs/jquery-1.6.4.min.js"><\/script>')</script>

  <script src="script.js"></script>
</body>
</html>

Our script.js to capture the form submit event and send the ajax request.

  //Note, since the script.js is loaded at the bottom of the page,
  //We don't need to use the jQuery dom-ready function. 

  //When an Ajax Request is started, show the loading icon
  $("#loader").ajaxStart(function() { 
       $(this).show();
  });
  
  $("#search").submit(function() { 
    //get the value from the text input field in the form
    var formVal = $("#query").val();
    
    //Ajax Request
    $.ajax({ 
      type: "POST",
      data: {query: formVal},
      url : 'http://pzwart3.wdka.hro.nl/~jlund/cgi-bin/imger.py',
      success : function(data) { 
          //hide the loader
          $("#loader").hide();

          //Check if data is not empty
          if(data) {

            //Prepend a new img tag and use the returned data as src
            $("<img/>", {
              src: data                 
            }).prependTo($("#results"));                            
          }            
      }        
    });
    
    //Prevent default behaviour or form, if not it would go to the url of the form.
    return false;
  });

This is the easiest way of sending one value, and getting one value back, and do then something with it, but what if you want to return more than one value?

jQuery has a pretty handy function for parsing JSON, so let's see how that works.

  //Ajax Request
  $.ajax({ 
    type: "POST",
    data: {name: value},
    url : '',
    success : function(data) { 
      //parse our data in to a JSON-object 
      var obj = $.parseJSON(data);
      
      //now we can access the data returned like this      
      var value1 = obj.value1;
    
      //to iterate through it all (if you return array(1 => array(), 2 => array())) etc
      $.each(obj, function(i, object) {
        var value1 = obj.value1;
      });
    }        
  });


To make nicely formatted json return results in python you can do it like this (as seen here http://docs.python.org/library/json.html)

  >>> import json
  #outputs your data as json encoded
  >>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
  '["foo", {"bar": ["baz", null, 1.0, 2]}]'