Mercurial > cosocket
changeset 45:27785e0ac4d8
Added error detection on the client-side.
author | Atul Varma <varmaa@toolness.com> |
---|---|
date | Tue, 28 Apr 2009 10:03:51 -0700 |
parents | d6467f3845ad |
children | 346573b610cd |
files | openwebchat.css openwebchat.html openwebchat.js openwebchat.py |
diffstat | 4 files changed, 76 insertions(+), 31 deletions(-) [+] |
line wrap: on
line diff
--- a/openwebchat.css Tue Apr 28 08:32:25 2009 -0700 +++ b/openwebchat.css Tue Apr 28 10:03:51 2009 -0700 @@ -53,3 +53,10 @@ #templates { display: none; } + +.error { + background: red; + padding: 1em; + margin-top: 1em; + margin-bottom: 1em; +}
--- a/openwebchat.html Tue Apr 28 08:32:25 2009 -0700 +++ b/openwebchat.html Tue Apr 28 10:03:51 2009 -0700 @@ -15,6 +15,11 @@ <p>Your name is <input type="text" id="name"/>.</p> </div> <div id="templates"> + <div class="error"> + It appears that your connection to the server has been + severed. Please reload this page to reconnect. (Sorry, this will + be more user-friendly in the future!) + </div> <div class="message"> <div class="author"></div> <div class="timestamp"></div>
--- a/openwebchat.js Tue Apr 28 08:32:25 2009 -0700 +++ b/openwebchat.js Tue Apr 28 10:03:51 2009 -0700 @@ -1,13 +1,29 @@ var OpenWebChat = { - startMessageListener: function startMessageListener(onMessage) { + startMessageListener: function startMessageListener(options) { var req = new XMLHttpRequest(); req.multipart = true; req.open('GET', 'listen/multipart', true); req.overrideMimeType('application/json'); req.addEventListener( + "error", + function() { + options.onError(null); + }, + false + ); + req.addEventListener( "load", function onload(evt) { - onMessage(JSON.parse(req.responseText)); + var msg; + var errorOccurred = false; + try { + msg = JSON.parse(req.responseText); + } catch (e) { + options.onError(e); + errorOccurred = true; + } + if (!errorOccurred) + options.onMessage(msg); }, false ); @@ -46,30 +62,39 @@ }); OpenWebChat.startMessageListener( - function(msg) { - var block = $('#templates .message').clone(); + {onMessage: function onMessage(msg) { + var block = $('#templates .message').clone(); - // Try to dynamically determine if the message is HTML or not. - var parser = new DOMParser(); - var dom = parser.parseFromString('<xml>' + msg.content + '</xml>', - 'text/xml'); - if (dom.firstChild.nodeName == 'parsererror') - $('.content', block).text(msg.content); - else - $('.content', block).html(msg.content); + // Try to dynamically determine if the message is HTML or not. + var parser = new DOMParser(); + var dom = parser.parseFromString('<xml>' + msg.content + '</xml>', + 'text/xml'); + if (dom.firstChild.nodeName == 'parsererror') + $('.content', block).text(msg.content); + else + $('.content', block).html(msg.content); - var author = msg.author ? msg.author : 'Anonymous'; - if (author != $('#content .author:last').text()) - $('.author', block).text(author); - else - $('.author', block).remove(); + var author = msg.author ? msg.author : 'Anonymous'; + if (author != $('#content .author:last').text()) + $('.author', block).text(author); + else + $('.author', block).remove(); + + $('.timestamp', block).text(msg.time); - $('.timestamp', block).text(msg.time); - - block.hide(); - $('#incoming-messages').append(block); - block.slideDown(function() { - window.scrollTo(0, $(window).height()); - }); + block.hide(); + $('#incoming-messages').append(block); + block.slideDown(function() { + window.scrollTo(0, $(window).height()); + }); + }, + onError: function onError(exception) { + if (window.console) + window.console.log('The error', exception, 'occurred.'); + var error = $('#templates .error').clone(); + error.hide(); + $('#incoming-messages').append(error); + error.slideDown(); + } }); });
--- a/openwebchat.py Tue Apr 28 08:32:25 2009 -0700 +++ b/openwebchat.py Tue Apr 28 10:03:51 2009 -0700 @@ -86,21 +86,29 @@ while 1: yield self._until_one_request_processed(addr) + def __multipart_boundary(self, boundary): + # Here we actually declare the content type and start the + # transfer of the document itself; this is needed to + # trigger an error on the browser-side, because a closed + # connection during any other phase is unlikely to + # cause any event to trigger on the client webpage. + return '\r\n'.join(('--%s' % boundary, + 'Content-Type: text/plain', + '', + '')) + def _until_multipart_header_sent(self, boundary): yield self._until_http_response_sent( - '--%s\r\n' % boundary, + self.__multipart_boundary(boundary), mimetype = ('multipart/x-mixed-replace; ' 'boundary="%s"' % boundary)) def _until_multipart_part_sent(self, boundary, msg): yield until_sent('\r\n'.join( - ('Content-Length: %d' % len(msg), - 'Content-Type: text/plain', + (msg, '', - msg, - '', - '--%s' % boundary, - ''))) + self.__multipart_boundary(boundary)) + )) def _until_one_request_processed(self, addr): request = yield until_received(terminator = '\r\n\r\n')