DSi Browser にも console.log が欲しい
DSi Browser 上で動く JavaScript を書く必要があることがしばしばあると思いますが、今のご時世でもデバッグが面倒で、alert デバッグに頼ったりすることがあります。これは大変今時としてはありえないので、console.log が欲しいところです。とはいえ、DSi Browser の表示領域というのは非常に限らており、console.log を作るにしても表示する場所がありません。
なので以下のようなサーバを立ててやることがあります。
#!/usr/bin/env plackup -s AnyEvent
# vim:set ft=perl:
use strict;
use warnings;
use lib 'lib/perl/lib/perl5', 'lib/perl/lib/perl5/x86_64-linux-thread-multi';
use Plack::Request;
use AnyEvent;
use JSON::XS;
my $template = <<'EOS';
<!DOCTYPE html>
<title>tail</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.4.2.min.js"></script>
<script type="text/javascript">$(function () {
var log = document.getElementById('log');
var $style = $(document.createElement('style')).appendTo(document.body);
$('.host').live('click', function () {
var host = $(this).text();
$style.text( '.line { display: none } ' + '.line.' + classOfHost(host) + ' { display: block }');
});
$(document.body).dblclick(function () {
$style.text('.line { display: block }');
});
function classOfHost (host) {
return 'h-' + host.replace(/\./g, '-');
}
function read () {
$.ajax({
url: '/api/read',
dataType : 'json',
success : function (data) {
var messages = data.messages;
for (var i = 0, len = messages.length; i < len; i++) {
var message = messages[i];
$('<div class="line"></div>').
append($('<span class="host"></span>').text(message.host)).
append($('<span class="body"></span>').text(message.body)).
addClass(classOfHost(message.host)).
prependTo(log);
}
while (log.childNodes.length > 100) log.removeChild(log.lastChild);
},
complete : function () {
setTimeout(function () {
read();
}, 1000);
}
});
}
read();
})</script>
<style type="text/css">
pre {
font-size: 14px;
line-height: 1.33;
}
.host {
color: #666;
margin: 0 1em 0 0;
cursor: pointer;
}
.body {
}
</style>
<pre id="log"></pre>
EOS
my $i = 0;
my $sessions = {};
my $app = sub {
my $env = shift;
$env->{'psgi.streaming'} or die;
sub {
my $callback = shift;
my $req = Plack::Request->new($env);
my $res = $req->new_response(200);
eval {
+{
'/' => sub {
$res->content_type('text/html');
$res->content($template);
$callback->($res->finalize);
},
'/api/read' => sub {
my $sid = $req->cookies->{sid} || $i++;
my $session = $sessions->{$sid} || +{
sid => $sid,
messages => [],
callback => undef,
expire => 0,
ua => $req->header('User-Agent'),
};
$session->{expire} = time() + 60 * 60;
$sessions->{$sid} = $session;
$res->cookies->{sid} = $sid;
if (@{ $session->{messages} }) {
$res->content(encode_json +{
sid => $sid,
messages => $session->{messages},
});
$session->{messages} = [];
$callback->($res->finalize);
} else {
$session->{callback} = sub {
my $message = shift;
delete $session->{callback};
$res->content(encode_json +{
sid => $sid,
messages => [ $message ],
});
$res->content_type('application/json');
$callback->($res->finalize);
};
}
},
'/p' => sub {
my $message = {
host => $req->address,
body => $req->param('m'),
};
for my $sid (keys %$sessions) {
my $session = $sessions->{$sid};
if ($session->{expire} < time()) {
delete $sessions->{$sid};
next;
}
if ($session->{callback}) {
$session->{callback}->($message);
} else {
push @{ $session->{messages} }, $message;
}
}
$res->content_type('application/json');
$res->content(encode_json +{ status => 'ok' });
$callback->($res->finalize);
},
}->{ $req->path }->();
};
if ($@) {
$res->code(200);
$res->content($@);
$callback->($res->finalize);
}
};
};
use Plack::Builder;
builder {
enable "Plack::Middleware::ReverseProxy";
$app;
};このサーバを立てたうえで、JS で以下のようなコードをつくっておきます。
function toTail (msg) {
var img = new Image();
img.src = 'http://tail.psgi/p?m=' + encodeURIComponent(msg);
}
if (typeof console == 'undefined') {
console = {
log : toTail
};
}どや
