1? my ($host, $room) = @_ 2<html> 3<head> 4<title>Twiggy/Plack WebSocket Chat demo</title> 5<script src="/static/jquery-1.3.2.min.js"></script> 6<script src="/static/jquery.ev.js"></script> 7<script src="/static/jquery.md5.js"></script> 8<script src="/static/jquery.cookie.js"></script> 9<script src="/static/jquery.oembed.js"></script> 10<script src="/static/pretty.js"></script> 11<script> 12var ws; 13var cookieName = 'tatsumaki_chat_ident'; 14 15function doPost(el1, el) { 16 if (!ws) return; 17 18 var ident = el1.attr('value'); 19 if (ident) $.cookie(cookieName, ident, { path: '/chat' }); 20 var text = el.attr('value'); 21 if (!text) return; 22 23 ws.send(JSON.stringify({ ident:ident, text:text })); 24 el.attr('value', ''); 25 return; 26} 27 28$(function(){ 29 if ("WebSocket" in window) { 30 ws = new WebSocket("ws://<?= $host ?>/ws/<?= $room ?>"); 31 } 32 else { 33 $("#content").text("This browser doesn't support WebSocket."); 34 return; 35 } 36 37 if (ws) { 38 ws.onmessage = function (ev) { 39 try { 40 var d = eval("("+ev.data+")"); 41 var src = d.avator || ("http://www.gravatar.com/avatar/" + $.md5(d.ident || 'foo')); 42 var name = d.name || d.ident || 'Anonymous'; 43 var avatar = $('<img/>').attr('src', src).attr('alt', name); 44 if (d.ident) { 45 var link = d.ident.match(/https?:/) ? d.ident : 'mailto:' + d.ident; 46 avatar = $('<a/>').attr('href', link).attr('target', '_blank').append(avatar); 47 } 48 avatar = $('<td/>').addClass('avatar').append(avatar); 49 50 var message = $('<td/>').addClass('chat-message'); 51 if (d.text) message.text(d.text); 52 if (d.html) message.html(d.html); 53 54 message.find('a').oembed(null, { embedMethod:"append", maxWidth:500 }); 55 var name = d.name || (d.ident ? d.ident.split('@')[0] : null); 56 if (name) 57 message.prepend($('<span/>').addClass('name').text(name+': ')); 58 59 var date = new Date(d.time * 1000); 60 var meta = $('<td/>').addClass('meta').append( 61 '(' + 62 '<span class="pretty-time" title="' + date.toUTCString() + '">' + date.toDateString() + '</span>' + 63 ' from ' + d.address + ')' 64 ); 65 $('.pretty-time', meta).prettyDate(); 66 $('#messages').prepend($('<tr/>').addClass('message').append(avatar).append(message).append(meta)); 67 68 } catch(e) { if (console) console.log(e) } 69 } 70 } 71 72 if ($.cookie(cookieName)) 73 $('#ident').attr('value', $.cookie(cookieName)); 74 75 window.setInterval(function(){ $(".pretty-time").prettyDate() }, 1000 * 30); 76}); 77</script> 78<link rel="stylesheet" href="/static/screen.css" /> 79<style> 80#messages { 81 margin-top: 1em; 82 margin-right: 3em; 83 width: 100%; 84} 85.avatar { 86 width: 25px; 87 vertical-align: top; 88} 89.avatar img { 90 width: 25px; height: 25px; 91 vertical-align: top; 92 margin-right: 0.5em; 93} 94.chat-message { 95 width: 70%; 96} 97.chat-message .name { 98 font-weight: bold; 99} 100.meta { 101 vertical-align: top; 102 color: #888; 103 font-size: 0.8em; 104} 105body { 106 margin: 1em 2em 107} 108 109</style> 110</head> 111<body> 112 113<div id="content"> 114 115<h1 class="chat-room-name">Chat room: <?= $room ?></h1> 116<!-- move this input out of form so Firefox can submit with enter key :/ --> 117Your email (for Gravatar): <input id="ident" type="text" name="ident" size="24"/> 118<form onsubmit="doPost($('#ident'), $('#chat')); return false"> 119Something to say: <input id="chat" type="text" size="48"/> 120</form> 121 122<table id="messages"> 123</table> 124 125<div id="footer">Powered by <a href="http://github.com/miyagawa/Twiggy">Twiggy/<?= $Twiggy::VERSION ?></a>.</div> 126 127</div> 128</body> 129</html> 130