The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
% my $channel = $_[0]->{handler}->args->[0];
% my $mxhr = $_[0]->{handler}->request->param('mxhr');
<html>
<head>
<title>Tatsumaki Chat demo</title>
<script src="/static/jquery-1.3.2.min.js"></script>
% if ($mxhr) {
<script src="/static/DUI.js"></script>
<script src="/static/Stream.js"></script>
% } else {
<script src="/static/jquery.ev.js"></script>
% }
<script src="/static/jquery.md5.js"></script>
<script src="/static/jquery.cookie.js"></script>
<script src="/static/jquery.oembed.js"></script>
<script src="/static/pretty.js"></script>
<script>
var cookieName = 'tatsumaki_chat_ident';
function doPost(el1, el) {
  var ident = el1.attr('value');
  if (ident) $.cookie(cookieName, ident, { path: '/chat' });
  var text = el.attr('value');
  if (!text) return;
  $.ajax({
    url: "/chat/<%= $channel %>/post",
    data: { ident: ident, text: text },
    type: 'post',
    dataType: 'json',
    success: function(r) { }
  });
  el.attr('value', '');
  return;
}

$(function(){
  var onNewEvent = function(e) {
    try {
      var src    = e.avatar || ("http://www.gravatar.com/avatar/" + $.md5(e.ident || 'foo'));
      var name   = e.name   || e.ident || 'Anonymous';
      var avatar = $('<img/>').attr('src', src).attr('alt', name);
      if (e.ident) {
        var link = e.ident.match(/https?:/) ? e.ident : 'mailto:' + e.ident;
        avatar = $('<a/>').attr('href', link).attr('target', '_blank').append(avatar);
      }
      avatar = $('<td/>').addClass('avatar').append(avatar);

      var message = $('<td/>').addClass('chat-message');
      if (e.text) message.text(e.text);
      if (e.html) message.html(e.html);
      message.find('a').oembed(null, { embedMethod: "append", maxWidth: 500 });
      var name = e.name || (e.ident ? e.ident.split('@')[0] : null);
      if (name)
        message.prepend($('<span/>').addClass('name').text(name+ ': '));

      var date = new Date(e.time * 1000);
      var meta = $('<td/>').addClass('meta').append(
        '(' +
        '<span class="pretty-time" title="' + date.toUTCString() + '">' + date.toDateString() + '</span>' +
        ' from ' + e.address + ')'
      );
      $('.pretty-time', meta).prettyDate();
      $('#messages').prepend($('<tr/>').addClass('message').append(avatar).append(message).append(meta));
    } catch(e) { if (console) console.log(e) };
  }

  if (typeof DUI != 'undefined') {
    var s = new DUI.Stream();
    s.listen('application/json', function(payload) {
      var event = eval('(' + payload + ')');
      onNewEvent(event);
    });
    s.load('/chat/<%= $channel %>/mxhrpoll?session=' + Math.random());
  } else {
    $.ev.handlers.message = onNewEvent;
    $.ev.loop('/chat/<%= $channel %>/poll?session=' + Math.random());
  }

  if ($.cookie(cookieName))
    $('#ident').attr('value', $.cookie(cookieName));

  window.setInterval(function(){ $(".pretty-time").prettyDate() }, 1000 * 30);
});
</script>
<link rel="stylesheet" href="/static/screen.css" />
<style>
#messages {
  margin-top: 1em;
  margin-right: 3em;
  width: 100%;
}
.avatar {
  width: 25px;
  vertical-align: top;
}
.avatar img {
  width: 25px; height: 25px;
  vertical-align: top;
  margin-right: 0.5em;
}
.chat-message {
  width: 70%;
}
.chat-message .name {
  font-weight: bold;
}
.meta {
  vertical-align: top;
  color: #888;
  font-size: 0.8em;
}
body {
  margin: 1em 2em
}

</style>
</head>
<body>
<h1 class="chat-room-name">Chat room: <%= $channel %></h1>
<!-- move this input out of form so Firefox can submit with enter key :/ -->
Your email (for Gravatar): <input id="ident" type="text" name="ident" size="24"/>
<form onsubmit="doPost($('#ident'), $('#chat')); return false">
Something to say: <input id="chat" type="text" size="48"/>
</form>

<table id="messages">
</table>

<div id="footer">Powered by <a href="http://github.com/miyagawa/Tatsumaki">Tatsumaki/<%= $Tatsumaki::VERSION %></a>.</div>

</body>
</html>