I am using Python CGI to create a webpage that shows a title, dropdown menu and image. I would like to be able to select an option from the dropdown menu (would love to get rid of "submit" as well and just run when an option is chosen), trigger my python code (runthis.py) and update the image on the webpage. I want to do this WITHOUT opening new tabs and hopefully without refreshing the page. Currently I run this .py file to get my html:
#!C:\Python27\python
print "Content-type: text/html"
print
print "<html>"
print "<head>"
print "<title>Tab Title</title>"
print "</head>"
print '''<body bgcolor="#ccffcc">'''
print '''<h1 align="center">Page Heading</h1>'''
print '''<form action="/cgi-bin/dropdown.py" method="post" target="_blank">'''
print '''<select name="dropdown">'''
print '''<option value="Option1" selected>Option1</option>'''
print '''<option value="Option2" selected>Option2</option>'''
print "</select>"
print '''<input type="submit" value="Submit"/>'''
print "</form>"
print "<img src = /test.png>"
print "</body>"
print "</html>"
When I click "submit", a new tab will open showing the same page layout, just a different image (same one for example's sake). This is done through my dropdown.py
file in cgi-bin:
#!C:\Python27\python
import cgi,cgitb,os
cgitb.enable()
os.environ['HOME']='C:\python_cgi'
import matplotlib
matplotlib.use('Agg')
form = cgi.FieldStorage()
if form.getvalue('dropdown'):
subject = form.getvalue('dropdown')
else:
subject = "Not Entered"
from matplotlib.figure import Figure
from matplotlib.backends.backend_agg import FigureCanvasAgg
import StringIO
import msvcrt,sys, urllib, base64
fig = Figure(figsize=[4,4])
ax = fig.add_axes([.1,.1,.8,.8])
ax.scatter([1,2],[3,4])
canvas = FigureCanvasAgg(fig)
imgdata = StringIO.StringIO()
fig.savefig(imgdata, format='png')
imgdata.seek(0)
uri = 'data:image/png;base64,' + urllib.quote(base64.b64encode(imgdata.buf))
print "Content-Type: text/html"
print
print """\
<html>
<head>
<title>Tab Title</title>
</head>
<body>
<body bgcolor="#ccffcc">
<h1 align="center">Page Heading</h1>
<form action="/cgi-bin/dropdown.py" method="post" target="_blank">
<select name="dropdown">
<option value="Option1" selected>Option1</option>
<option value="Option2" selected>Option2</option>
</select>
<input type="submit" value="Submit"/>
</form>
<img src = %s/>
</body>
</html> """ % uri
To recap -- I just want to change the picture/image on the current page rather than opening up a whole new page. My gut tells me to use javascript (which I know nothing about). Does anyone have a suggestion on a code block that I need to enter to do such a thing?
Thanks!
EDIT
Per the comments below, I am trying to implement this html file:
<html>
<head>
<title>Tab Title</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" ></script>
</head>
<body>
<script>
function changeImage(imgName)
{
jQuery.get('/cgi-bin/dropdown.py', function(data) {
image = document.getElementById('imgDisp');
image.src = data;
})
}
</script>
<body bgcolor="#ccffcc">
<h1 align="center">Page Heading</h1>
<select name="dropdown" onchange="changeImage(this.value)">
<option value="Option1">Option1</option>
<option value="Option2">Option2</option>
</select>
<img id="imgDisp" src="/test.png" />
</body>
</html>
This loads my page correctly but nothing happens when I make a selection from the dropdownlist. I was hoping the image would change. My "dropdown.py" code now looks like:
#!C:\Python27\python
import cgi,cgitb,os
cgitb.enable()
os.environ['HOME']='C:\python_cgi'
import matplotlib
matplotlib.use('Agg')
from matplotlib.figure import Figure
from matplotlib.backends.backend_agg import FigureCanvasAgg
import StringIO
import msvcrt,sys, urllib, base64
fig = Figure(figsize=[4,4])
ax = fig.add_axes([.1,.1,.8,.8])
ax.scatter([1,2],[3,4])
canvas = FigureCanvasAgg(fig)
imgdata = StringIO.StringIO()
fig.savefig(imgdata, format='png')
imgdata.seek(0)
uri = 'data:image/png;base64,' + urllib.quote(base64.b64encode(imgdata.buf))
return uri
I haven't gotten to the url parameter approach yet -- not sure how that is done. Any more advice would be greatly appreciated!
In response to your edited question, the solution can actually be simpler:
Here you are making an asynchronous request to your Python script, and waiting for some data to be returned. However, you could consider your Python script a standalone service that maps, so to speak, a unique set of parameters to a (dynamically generated) image. This requires your Python script to output the image to the browser instead of returning the image data through CGI:
Once you are confident that an HTTP request to your Python script serves up a valid PNG, your front-end code only has to update the
src
attribute of the image you are displaying:When your
img
element is given a newsrc
value, the browser will automatically make a request to that URL and try to retrieve an image, which will load onto your page, replacing the previous image. You would have to modify your Python script, however, to expect a request parameter namedimage
, which holds a string. CGI has a simple method for accessing these parameter values passed inside the URL:This page is a great resource that you can check out: http://lost-theory.org/python/dynamicimg.html