diff --git a/content/static/datenspuren/2012/images/derbug.png b/content/static/datenspuren/2012/images/derbug.png
new file mode 100644
index 000000000..a6c3e10cf
Binary files /dev/null and b/content/static/datenspuren/2012/images/derbug.png differ
diff --git a/content/static/datenspuren/2012/script/derbug.js b/content/static/datenspuren/2012/script/derbug.js
new file mode 100644
index 000000000..b87da50a6
--- /dev/null
+++ b/content/static/datenspuren/2012/script/derbug.js
@@ -0,0 +1,128 @@
+var MOUSE_TIMEOUT = 1000;
+var mouseTimeout;
+
+$('body').mousemove(function() {
+ hideAll();
+
+ if (mouseTimeout)
+ clearTimeout(mouseTimeout);
+ mouseTimeout = setTimeout(onMouseTimeout, MOUSE_TIMEOUT);
+});
+
+function onMouseTimeout() {
+ canSpawn();
+}
+
+
+var MAX_BUGS = 5;
+var bugs = [];
+var SPAWN_INTERVAL = 2000;
+var spawnInterval;
+function canSpawn() {
+ if (!spawnInterval)
+ spawnInterval = setInterval(spawn, SPAWN_INTERVAL);
+}
+
+function spawn() {
+ bugs = bugs.filter(function(bug) {
+ return !bug.shouldHide;
+ });
+ /*console.log("spawn", bugs.length, "/", MAX_BUGS);*/
+ if (bugs.length >= MAX_BUGS)
+ return;
+
+ bugs.push(new Bug());
+}
+
+function hideAll() {
+ if (spawnInterval) {
+ clearInterval(spawnInterval);
+ spawnInterval = null;
+ hideAll();
+ }
+
+ for(var i = 0; i < bugs.length; i++) {
+ bugs[i].shouldHide = true;
+ }
+ bugs = [];
+}
+
+function Bug() {
+ this.alpha = 0;
+ this.rotation = 0;
+ this.x = $('body').scrollLeft() + Math.floor(window.innerWidth * Math.random());
+ this.y = $('body').scrollTop() + Math.floor(window.innerHeight * Math.random());
+ this.selectTarget();
+
+ this.el = $('
');
+ this.el.css({ position: 'absolute',
+ width: "28px",
+ height: "28px"
+ });
+ $('body').append(this.el);
+ /*console.log("new bug", this, this.x, this.y);*/
+
+ this.think();
+}
+Bug.prototype = {
+ update: function() {
+ this.el.css({ left: Math.floor(this.x) + "px",
+ top: Math.floor(this.y) + "px",
+ opacity: this.alpha,
+ transform: "rotate(" + this.rotation + "rad)",
+ '-webkitTransform': "rotate(" + this.rotation + "rad)",
+ '-mozTransform': "rotate(" + this.rotation + "rad)"
+ });
+ },
+ selectTarget: function() {
+ this.targetRotation = 2 * Math.PI * (Math.random() - 0.5);
+ this.targetSteps = 5 + Math.ceil(10 * Math.random());
+ },
+ think: function() {
+ if (this.shouldHide && this.alpha > 0) {
+ /* fading out */
+ this.alpha -= 0.1;
+ } else if (this.shouldHide) {
+ this.el.remove();
+ /* destroy
+ * HACK: Avoid nextTick() */
+ return;
+ } else if (this.alpha < 1) {
+ /* fading in */
+ this.alpha += 0.1;
+ }
+
+ var dr = this.targetRotation - this.rotation;
+ if (Math.abs(dr) > 1) {
+ this.rotation += Math.random() * dr / 10;
+ }
+ if (this.targetSteps > 0) {
+ this.targetSteps--;
+ this.x += Math.sin(this.rotation);
+ this.y -= Math.cos(this.rotation);
+
+ /* Emergency suicide: */
+ if (this.x < 16 ||
+ this.x > $('body').innerWidth() - 16 ||
+ this.y < 16 ||
+ this.y > $('body').innerHeight() - 16) {
+ this.shouldHide = true;
+ }
+ } else {
+ this.selectTarget();
+ }
+
+ this.update();
+ nextTick(this.think.bind(this));
+ }
+};
+
+var nextTick =
+ window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.msRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ function(f) {
+ window.setTimeout(f, 40);
+ };
diff --git a/content/static/datenspuren/2012/style/style.css b/content/static/datenspuren/2012/style/style.css
index 652bf6c52..10a7ff204 100644
--- a/content/static/datenspuren/2012/style/style.css
+++ b/content/static/datenspuren/2012/style/style.css
@@ -248,6 +248,9 @@ table.schedule {
border-radius: 8pt;
padding: 0.5em 1em;
}
+.schedule h4 {
+ margin: 0;
+}
.schedule ul {
padding: 0;
margin: 1em 0;
diff --git a/xsl/datenspuren/xhtml5.xsl b/xsl/datenspuren/xhtml5.xsl
index f915fd765..38ad83543 100644
--- a/xsl/datenspuren/xhtml5.xsl
+++ b/xsl/datenspuren/xhtml5.xsl
@@ -202,9 +202,11 @@
event
-
-
-
+