2012-05-24

My Very Own AJAX Tutorial

So, I finally accomplished my dream of figuring out how applications where, rather than just downloading a static webpage, the client communicates with the server and is constantly updating data (like chat rooms, MMORPGs and the like) work and implementing one of my own. Since this is at least the fourth time I tried to figure this out and the first I succeeded, I thought I would make my own, less complicated, tutorial of how to do so.

The example I'll be running through is a fairly simple chat room. To start off, you need to download the Python module web.py. Then, create a new python file, and we can get to work on the actual code.
import web, os
form = """
<script>
  setInterval(update,100);
  function update() {
    sendreq("ask");
  }
  function sendreq(type) {
    var xmlhttp = new XMLHttpRequest;
    xmlhttp.open("POST","/");
    xmlhttp.onreadystatechange=handler;
    var name = document.getElementById('name').value.replace(':','');
    if (name == '') name = 'Guest'
    if (type == "send") {
      var message = document.getElementById('text').value;
      xmlhttp.send(name+': '+message); //Requests containing a message post a message
    }
    else xmlhttp.send(name); //Requests with just a name ask for content
    function handler() {
      if(xmlhttp.readyState==4) {
        document.getElementById("messages").innerHTML = xmlhttp.responseText;
        xmlhttp.close;
      }
    }
  }
</script>
<div id="messages"></div><hr />
Name:<br><textarea id="name" cols="20" rows="1"></textarea>
<br>Message:<br><textarea id="text" cols="50" rows="5"></textarea>
<br><input type="button" onclick="sendreq('send')" value="Send">
"""

This big long string is the client-side, HTML/Javascript part of the code. A function lower down in our python script will send this off to the client's browser to render. The main method here is sendreq. It creates an XML HTTP request, xmlhttp, gives it the name of the function that it will call once it receives a response, handler, and sends the request off with a string containing the actual data that is sent. If sendreq is called with the parameter "ask", which we do automatically every 100 milliseconds, it sends just the name that you give (without any colons for processing purposes), but if it's called with "send" (which we do when the button is pressed) it sends the name and the message, with a colon separating the two. Once we receive a response, which will be the past 12 lines of messages that have been sent so far, the handler function is called, setting the HTML of the div with id messages to the response's text. Now, on to the server side:
class mainpage:
  def GET(self):
    return form
  def POST(self):
    data = web.data()
    name = data[:data.find(':')] if ':' in data else data 
    if os.path.exists('messages'): messages = open('messages','r').read().split('\n') #Read the existing messages from the 'messages' file
    else: messages = []
    if data.find(':') >= 0: open('messages','w').write('\n'.join(messages) + '\n' +  data) #Add our new message to that list if we have one
    return '<br>'.join(messages[-12:]).replace(name+':','<b>'+name+':</b>') #Return last 12 lines with the name in the request bolded

urls = ('/', 'mainpage')

app = web.application(urls, globals())

if __name__ == '__main__':
    app.run()
The GET function handles GET requests, which are just a new client asking for the webpage. We respond to them by sending off the HTML/Javascript that we had earlier. As for the POST function, it starts off by setting the data variable to the text sent by the request, and tries to extract the user's name. If there's a colon, the name is everything up to the colon, and if there isn't, the whole request is just the name. Then, it reads the file 'messages', where we're caching everything, and converts it into an array of lines (so that we can return just the last 12 lines later on), setting the array to be empty if the file does not yet exist. If the request text contains a colon (ie. it isn't just a name, so we're providing a new message), it adds the request text to our cache. Finally, it returns the last 12 lines, joined by <br> tags instead of literal newlines, and with the given name bolded to make it easier for users to see which of the past 12 lines are theirs and which are not.

Put these two chunks of code into your python file, run it, and that's it! You can go to localhost:8080 on your browser (or multiple browsers, so you can be sure that there's actual client-server communication going on) and try out your new chat room!

2 Comments:

At 02 August, 2017 09:21 , Blogger bmtcsch2 said...

thanks, been looking for something like this

 
At 21 July, 2021 14:32 , Blogger D.GB3 said...

Do you ever check this? I'll be trying this tonight. I know it's old though.

 

Post a Comment

Subscribe to Post Comments [Atom]

<< Home