MediaWiki:Skin/Projekt:Adventure2/lib.js: Unterschied zwischen den Versionen

aus Kamelopedia, der wüsten Enzyklopädie
Zur Navigation springen Zur Suche springen
 
(158 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
 
// A2lib
 
// A2lib
  
a2 = {};
+
if (window.a2 === undefined)
 +
window.a2 = {};
 
a2.events = {};
 
a2.events = {};
 +
a2.virtuals = {};
 +
a2.errorCount = 0;
 +
 +
a2.EVENT_CHAIN_MAX_LENGTH = 20;
 +
a2.eventChain = [];
 +
 +
a2.clearEventChain = function clearEventChain () {
 +
    a2.eventChain = [];
 +
};
  
 
a2.clearScope = function clearScope(sc) {
 
a2.clearScope = function clearScope(sc) {
 
     delete a2.events[sc];
 
     delete a2.events[sc];
 +
    delete a2.virtuals[sc];
 
};
 
};
  
 
a2.registerEventHandler = function registerEventHandler(e) {
 
a2.registerEventHandler = function registerEventHandler(e) {
 +
    var sc = e.scope;
 +
 +
    if (!a2.events[sc])
 +
        a2.events[sc]={};
  
     if (!a2.events[e.scope])
+
     for(var i=0; i<e.trigger.length; i++){
         a2.events[e.scope]={};
+
        var tr = e.trigger[i];
 +
        if (!a2.events[sc][tr])
 +
            a2.events[sc][tr] = [];
 +
   
 +
         a2.events[sc][tr].push(function(real){
 +
            a2.log("run", e.name);
 +
            var cond = e.condition();
 +
            a2.debugEventInstance(e.scope, e.name, cond);
 +
            if (cond)
 +
                e.action(real);
 +
        });
 +
    }
 +
};
  
    if (!a2.events[e.scope][e.trigger])
+
a2.log = function () {return;};
        a2.events[e.scope][e.trigger] = [];
+
if (window.console && window.console.log && window.console.log.apply)
 +
    a2.log = function() { console.log.apply(window.console, arguments) };
  
    a2.events[e.scope][e.trigger].push(function(){if (e.condition()) e.action();});
 
};
 
  
a2.fireEvent = function fireEvent (event) {
+
a2.virtualTriggerMap = {
 +
    add: [1],
 +
    remove: [1],
 +
    activate: [1],
 +
    apply: [1,0],
 +
    combine: [1,1],
 +
    enter: [1],
 +
    leave: [1]
 +
}
 +
 
 +
a2.xJoin = function xJoin (z){
 +
    function _xj(arr, vals){
 +
        var ret = [];
 +
        for (var i=0; i<arr.length; i++)
 +
            for (var j=0; j<vals.length; j++)
 +
                ret.push(arr[i].concat(vals[j]));
 +
        return ret;
 +
    }
 +
    var n = [[]];
 +
    for (var i=0; i<z.length; i++)
 +
        n = _xj(n,z[i]);
 +
    return n;
 +
}
 +
 
 +
a2.createVirtualTriggers = function createVirtualTriggers (tr) {
 +
    var b = tr[0];
 +
    return a2.xJoin($.map(tr, function (val, i) {
 +
        if (i>0 && a2.virtualTriggerMap[b] && a2.virtualTriggerMap[b][i-1] && a2.virtuals[val])
 +
            return [[val].concat(a2.virtuals[val])];
 +
        else
 +
            return [[val]];
 +
    }));
 +
}
 +
 
 +
a2.fireEvent = function fireEvent(ev) {
 +
    var triggers = a2.createVirtualTriggers(ev);
 +
    for (var i=0; i<triggers.length; i++)
 +
        a2._fireEvent(triggers[i], ev);
 +
}
 +
 
 +
a2._fireEvent = function _fireEvent (ev, real) {
 +
 
 +
    if (a2.eventChain.length >= a2.EVENT_CHAIN_MAX_LENGTH) {
 +
        a2.debugError("Abbruch: zu viele Folge-Ereignisse.");
 +
        return;
 +
    }
 +
    var evstate = a2.stateEncode() + "|" + ev;
 +
    if (a2.eventChain.indexOf(evstate) > -1) {
 +
        a2.debugError("Abbruch: Ereignis-Rekursion.");
 +
        return;
 +
    }
 +
    a2.eventChain.push(evstate);
 +
 
 +
    if ( ev[0] == "enter" || ev[0] == "add" || ev[0] == "remove" )
 +
        a2.updateHash()
 +
 
 +
    event = ev.join(".");
 +
    a2.log("Fire", event, real);
 +
    a2.debugEvent(event);
 
     var e = a2.events;
 
     var e = a2.events;
     for(var i=0; i<e.length; i++)
+
     for(var i in e)
        if (e[i])
+
      try {
            for(var j=0; j<e[i].length; j++)
+
          for(j=0; e[i][event] !== undefined && j<e[i][event].length; j++){
                e[i][j]();
+
              a2.log("Event", i, event, j, e[i][event][j]);
 +
              e[i][event][j](real);
 +
          }
 +
      } catch (e) {
 +
          a2.log("Event Exception", e);
 +
      }
 
};
 
};
 +
 +
a2.makeUrl = function makeUrl(p){
 +
    var script = mw.config.get("wgScript");
 +
    var page = mw.config.get("wgPageName");
 +
    return [script, page, p].join("/");
 +
}
 +
 +
a2.updateHash = function updateHash() {
 +
    var hash = "#" + a2.crypt(a2.stateEncode(), true);
 +
    location.hash = hash;
 +
    a2.latestHash = hash;
 +
}
  
 
a2.loadPage = function loadPage(n){
 
a2.loadPage = function loadPage(n){
     response = $.ajax({
+
     if (isNaN(parseInt(n)) /* || a2.cpage == parseInt(n) */ )
         url: "/index.php/Kamel:J*/Test2/"+n+"?action=render",
+
        return;
 +
 
 +
 
 +
    var response = $.ajax({
 +
         url: a2.makeUrl(parseInt(n)+"?action=render"),
 
         async: false
 
         async: false
 
     });
 
     });
     $("#a2image").html(response.responseText);
+
 
 +
    if (response.status != 200) {
 +
        a2.debugError("Fehler beim Laden von Seite "+n+": "+response.statusText);
 +
        return;
 +
    }
 +
 
 +
    a2.fireEvent(["leave",a2.cpage]);
 +
    a2.clearScope(":page:");
 +
 +
    a2.cpage = n;
 +
    a2.debugPage(n);
 +
    var $content = $(response.responseText)
 +
    $content.append('<scr'+'ipt type="text/javascript">setTimeout(function(){a2.fireEvent(["enter",a2.cpage]); $("#a2loader").hide();}, 100);</scr'+'ipt>');
 +
 +
     $("#a2image").empty().append($content);
 
     console.log($("#a2image a"));
 
     console.log($("#a2image a"));
 +
 
     $("#a2image area").click(function (ev) {
 
     $("#a2image area").click(function (ev) {
         a2.fireEvent("click."+ev.target.hash.substr(1));
+
        a2.clearEventChain();
 +
         a2.fireEvent(["click",ev.currentTarget.hash.substr(1)]);
 +
        return false;
 +
    });
 +
 
 +
    $(".overlay").css("cursor","pointer").click(function (ev) {
 +
        a2.clearEventChain();
 +
        a2.fireEvent(["click",ev.currentTarget.id.split("_")[1]]);
 +
        return false;
 +
    });
 +
 
 +
    $("#_l, #_r, #_u, #_d").click(function (ev) {
 +
        a2.clearEventChain();
 +
        a2.fireEvent(["click",ev.currentTarget.id]);
 
         return false;
 
         return false;
 
     });
 
     });
 +
 +
    $("#a2image img").droppable({
 +
        drop: function (event, ui) {
 +
            var target = a2.ui.getDroparea($(this), ui);
 +
            a2.log("drop", target, event, ui);
 +
            for (var i=0; i<target.length; i++) {
 +
                a2.clearEventChain();
 +
                a2.fireEvent(["apply",ui.draggable.data("item"),target[i].hash.substr(1)]);
 +
            }
 +
        }
 +
    });
 +
 +
  $(".overlay").droppable({
 +
        drop: function (event, ui) {
 +
            a2.clearEventChain();
 +
            a2.fireEvent(["apply",ui.draggable.data("item"),this.id.split("_")[1]]);
 +
    }
 +
  });
 +
 +
};
 +
 +
a2.util = {
 +
    print: function (s, opts) {
 +
        $("#a2text").text(s);
 +
 +
        // print options for the ask method
 +
        if(opts) {
 +
            var functionBuilder = function (target) {
 +
                return function () {
 +
                    a2.util.print("");
 +
                    a2.fireEvent(["click", target]);
 +
                };
 +
            };
 +
 +
            var ul = $("<ul/>");
 +
            for(var i=0; i<opts.length; i++) {
 +
                var li = $("<li class='pseudolink'/>");
 +
                li.click(functionBuilder(opts[i][0]));
 +
                li.text(opts[i][1]);
 +
                ul.append(li);
 +
            }
 +
            $("#a2text").append(ul);
 +
        }
 +
    },
 +
    goto: function (p) {
 +
 +
        // prevent side effects
 +
        a2.timer.clear();
 +
 +
        // this was for old Widgets!
 +
        //$("audio").each(function (a,b) { b.autoplay = false; b.pause(); });
 +
 +
        // stop background noises, keep music
 +
        a2.audio.stop("background");
 +
 +
        // actually go to page
 +
        a2.loadPage(p);
 +
    },
 +
    timeoutIsSet: function () {
 +
        return ! isNaN(a2.timer.pt);
 +
    }
 +
};
 +
 +
 +
a2.items = {};
 +
a2.loadItem = function loadItem(n){
 +
    a2.log("load", n);
 +
 +
    var response = $.ajax({
 +
        url: a2.makeUrl("item/"+n+"?action=render"),
 +
        async: false
 +
    });
 +
 +
    if (response.status != 200) {
 +
        a2.debugError("Fehler beim Laden von Item "+n+": "+response.statusText);
 +
        return;
 +
    }
 +
 +
    a2.clearScope(n);
 +
 +
    a2.items[n] = response.responseText;
 +
    a2.log(a2.items);
 +
    a2.renderItems();
 +
    a2.fireEvent(["add",n]);
 +
};
 +
 +
a2.renderItems = function renderItems(){
 +
    $("#a2items, #a2pseudoitems").empty()
 +
    a2.debugItems();
 +
    for (var item in a2.items){
 +
        if (item[0] == "_") {
 +
            // skip "virtual" status items
 +
            $("#a2pseudoitems").append(a2.items[item]);
 +
            continue;
 +
        }
 +
 +
        var $flbox=$('<div class="a2itembox" />');
 +
        var $fl=$('<div class="a2item" />');
 +
        $flbox.append($fl);
 +
        $fl.append(a2.items[item]);
 +
        $("#a2items").append($flbox);
 +
        $fl.draggable({
 +
            // cursorAt: {top: -5, left: -5},
 +
            revert: true,
 +
            zIndex: 10000,
 +
            start: function(event, ui) {
 +
                ui.helper.bind("click.prevent", function(event) { event.preventDefault(); });
 +
            },
 +
            stop: function(event, ui) {
 +
                setTimeout(function(){ui.helper.unbind("click.prevent");}, 300);
 +
            }
 +
        });
 +
        $fl.data("item",item);
 +
        $fl.click(function () {
 +
            a2.clearEventChain();
 +
            a2.fireEvent(["activate",$(this).data("item")]);
 +
        });
 +
        $fl.droppable({
 +
            drop: function (event, ui) {
 +
                a2.clearEventChain();
 +
                a2.fireEvent(["combine",ui.draggable.data("item"),$(this).data("item")]);
 +
                return false;
 +
            }
 +
        });
 +
        a2.log($("#a2items"))
 +
    }
 +
}
 +
 +
a2.util.add = function add (i) {
 +
    a2.loadItem(i);
 +
};
 +
a2.util.remove = function remove(i) {
 +
    delete a2.items[i];
 +
    delete a2.events[i];
 +
    delete a2.virtuals[i];
 +
    a2.renderItems();
 +
    a2.fireEvent(["remove",i]);
 +
};
 +
 +
a2.util.removeAll = function removeAll(v) {
 +
    for (i in a2.virtuals)
 +
        if( a2.virtuals[i].indexOf(v) > -1 ) {
 +
            delete a2.items[i];
 +
            delete a2.events[i];
 +
            delete a2.virtuals[i];
 +
            a2.fireEvent(["remove",i]);
 +
    }
 +
    a2.renderItems();
 +
}
 +
 +
a2.util.hasVirtual = function hasVirtual (v) {
 +
    for (i in a2.virtuals)
 +
        if( a2.virtuals[i].indexOf(v) > -1 )
 +
            return i;
 +
    return false;
 +
}
 +
 +
a2.ui = {};
 +
a2.ui.getAreaBox = function getAreaBox (area) {
 +
    var $area = $(area);
 +
    var shape = $area.attr("shape");
 +
    var p = $area.attr("coords");
 +
    p = p.split(",")
 +
    p = $.map(p, function(x){ return parseInt(x);});
 +
 +
    if (shape == "circle"){
 +
        var x1 = p[0] - p[2];
 +
        var y1 = p[1] - p[2];
 +
        var x2 = p[0] + p[2];
 +
        var y2 = p[1] + p[2];
 +
    } else {
 +
        var x1 = Infinity;
 +
        var y1 = Infinity;
 +
        var x2 = -Infinity;
 +
        var y2 = -Infinity;
 +
        for(var i=0; i<p.length; i=i+2){
 +
            if (p[i] < x1) x1 = p[i];
 +
            if (p[i+1] < y1) y1 = p[i+1];
 +
            if (p[i] > x2) x2 = p[i];
 +
            if (p[i+1] > y2) y2 = p[i+1];
 +
        }
 +
    }
 +
 +
    return {x1:x1, y1:y1, x2:x2, y2:y2};
 +
};
 +
 +
a2.ui.getDroparea = function getDroparea (img, ui) {
 +
    var $areas = $("area");
 +
    return $areas.filter(function () {
 +
        var b = a2.ui.getAreaBox(this);
 +
        var s = 25; // half itemsize
 +
 +
        var xm = (b.x1 + b.x2) / 2;
 +
        var ym = (b.y1 + b.y2) / 2;
 +
 +
        var dx = ui.offset.left - $(img).offset().left + s;
 +
        var dy = ui.offset.top - $(img).offset().top + s;
 +
 +
        return (b.x1 < dx && dx < b.x2 &&
 +
                b.y1 < dy && dy < b.y2) ||
 +
              (dx - s < xm && xm < dx + s &&
 +
                dy - s < ym && ym < dy + s);           
 +
    });
 +
}
 +
 +
a2.stateEncode = function () {
 +
    var s = String(a2.cpage);
 +
    for (var i in a2.items)
 +
        s+="|"+i;
 +
    return s
 +
}
 +
 +
a2.stateDecode = function (s) {
 +
    a2.clearEventChain();
 +
    var c = s.split("|");
 +
    a2.items = {};
 +
    a2.virtuals = {};
 +
    a2.events = {}
 +
    for (var j=1; j<c.length; j++) {
 +
        a2.items[c[j]] = "<img src='/images/a/a6/A2loading.gif' alt='Loading …' />";
 +
    }
 +
    a2.renderItems();
 +
    for (var j=1; j<c.length; j++)
 +
        a2.loadItem(c[j]);
 +
    a2.loadPage(parseInt(c[0]));
 +
}
 +
 +
a2.crypt = function crypt (str, encode) {
 +
    if (encode){
 +
        var n = Math.floor((Math.random()*9))+1;
 +
        out = String(n);
 +
    } else {
 +
        var n = - parseInt(str.substr(0,1));
 +
        var out = "";
 +
        str = str.substr(1);
 +
    }
 +
    var chain = "pwoTä7eGNVk1SAldv0mJ9zIöPE4x8rF|B6ybüjZDC5cqfRhOXsQY23iUngLWuMHatK";
 +
    var mk = function(i){ return i % chain.length };
 +
 +
    for (var i=0; i<str.length; i++) {
 +
        var c = str.substr(i,1);
 +
        var ind = chain.indexOf(c);
 +
        if (ind == -1)
 +
            out += c;
 +
        else
 +
            out += chain.substr(mk(ind + n),1);
 +
    }
 +
    return out;
 +
}
 +
 +
/* DEBUGGER */
 +
 +
a2.debugEvent = function debugEvent (ev) {
 +
    if (!$("#a2dbgBottom").length)
 +
        return;
 +
 +
    $("#a2dbgEventLog").append($("<li/>").text(ev).append("<ul/>"));
 +
    $("#a2dbgBottom:visible").scrollTop($("#a2dbgBottom")[0].scrollHeight);
 +
}
 +
 +
a2.debugEventInstance = function debugEventInstance (sc,n,cond) {
 +
    if (!$("#a2dbgBottom").length)
 +
        return;
 +
 +
    var classname = cond ? "a2fired" : "a2notfired";
 +
    $("#a2dbgEventLog li ul").last().append($("<li/>").text(sc+"->"+n).addClass(classname));
 +
    $("#a2dbgBottom:visible").scrollTop($("#a2dbgBottom")[0].scrollHeight);
 +
}
 +
 +
a2.debugPage = function debugPage (p) {
 +
  $("#a2dbgGoto").val(p);
 +
}
 +
 +
a2.debugItems = function debugItems() {
 +
  var s = [];
 +
  for (i in a2.items)
 +
      s.push(i);
 +
  $("#a2dbgItems").val(s.join("\n"));
 +
}
 +
 +
a2.debugError = function debugError(text) {
 +
    if (!$("#a2dbgBottom").length)
 +
        return;
 +
 +
    a2.errorCount ++;
 +
    $("#a2errorCount").text(a2.errorCount);
 +
    $("#a2dbgEventLog").append($("<li/>").text(text).addClass("a2error"));
 +
    $("#a2dbgBottom:visible").scrollTop($("#a2dbgBottom")[0].scrollHeight);
 +
}
 +
 +
// provide timer functions
 +
a2.timer = {
 +
    time: 0,
 +
    pt: NaN,
 +
    fn: null,
 +
    set: function set(n, fn) {
 +
   
 +
        if (! isNaN(a2.timer.pt)) {
 +
    // do not set timer if timer already active
 +
            return;
 +
        }
 +
           
 +
        a2.timer.time = n;
 +
        a2.timer.fn = fn;
 +
       
 +
        a2.timer.pt = setInterval(function () {
 +
            a2.timer.time--;
 +
   
 +
            if (a2.timer.time <= 0) {
 +
                clearInterval(a2.timer.pt);
 +
                a2.timer.pt = NaN;
 +
                $("#_t").text("0:00").fadeOut('slow');
 +
                fn();
 +
                return;
 +
            }
 +
       
 +
            var sec = a2.timer.time % 60;
 +
       
 +
            if (sec < 10)
 +
                sec = "0" + sec;
 +
            $("#_t").show().text(String(Math.floor(a2.timer.time / 60)) + ":" + sec );
 +
        }, 1000);
 +
    },
 +
   
 +
    clear: function clear() {
 +
        if (! isNaN(a2.timer.pt)) {
 +
            clearInterval(a2.timer.pt);
 +
            a2.timer.pt = NaN;
 +
            $("#_t").fadeOut();
 +
        }
 +
    }
 
};
 
};
 +
 +
// provide audio functions
 +
a2.audio = {
 +
    cache: {},
 +
    current: [],
 +
 +
    fetch: function fetch(file) {
 +
            var data = $.ajax({
 +
            type: "GET",
 +
            url: "/api.php",
 +
            data: {
 +
                action: "parse",
 +
                format: "xml",
 +
                text: "{{filepath:"+file+"}}"
 +
            },
 +
            async: false
 +
        });
 +
       
 +
        var html = $(data.responseText).find("text").text();
 +
        var url = $(html).find("a")[0].href;
 +
        return url;
 +
    },
 +
 +
    getaudio: function getaudio(file) {
 +
        if (a2.audio.cache[file]) {
 +
            return a2.audio.cache[file];
 +
        } else {
 +
            var url = a2.audio.fetch(file);
 +
            a2.audio.cache[file] = url;
 +
            return url;
 +
        }
 +
    },
 +
 +
    play: function play(channel, file) {
 +
        var $player = $("#a2audio_channel_"+channel)[0];
 +
        var audiofile = a2.audio.getaudio(file);
 +
 +
        if (audiofile != a2.audio.current[channel]) {       
 +
            $player.pause();
 +
            $player.src = a2.audio.getaudio(file);
 +
            $player.load();
 +
            $player.play();
 +
            a2.audio.current[channel] = audiofile;
 +
        }
 +
    },
 +
 +
    stop: function stop(channel) {
 +
        var $player = $("#a2audio_channel_"+channel)[0];
 +
        $player.pause();
 +
        a2.audio.current[channel] = null;
 +
    }
 +
}

Aktuelle Version vom 22. Juli 2015, 22:05 Uhr

// A2lib

if (window.a2 === undefined)
	window.a2 = {};
a2.events = {};
a2.virtuals = {};
a2.errorCount = 0;

a2.EVENT_CHAIN_MAX_LENGTH = 20;
a2.eventChain = [];

a2.clearEventChain = function clearEventChain () {
    a2.eventChain = [];
};

a2.clearScope = function clearScope(sc) {
    delete a2.events[sc];
    delete a2.virtuals[sc];
};

a2.registerEventHandler = function registerEventHandler(e) {
    var sc = e.scope;

    if (!a2.events[sc])
        a2.events[sc]={};

    for(var i=0; i<e.trigger.length; i++){
        var tr = e.trigger[i];
        if (!a2.events[sc][tr])
            a2.events[sc][tr] = [];
    
        a2.events[sc][tr].push(function(real){
            a2.log("run", e.name);
            var cond = e.condition();
            a2.debugEventInstance(e.scope, e.name, cond);
            if (cond)
                e.action(real);
        });
    }
};

a2.log = function () {return;};
if (window.console && window.console.log && window.console.log.apply)
    a2.log = function() { console.log.apply(window.console, arguments) };


a2.virtualTriggerMap = {
    add: [1],
    remove: [1],
    activate: [1],
    apply: [1,0],
    combine: [1,1],
    enter: [1],
    leave: [1]
}

a2.xJoin = function xJoin (z){
    function _xj(arr, vals){
        var ret = [];
        for (var i=0; i<arr.length; i++)
            for (var j=0; j<vals.length; j++)
                ret.push(arr[i].concat(vals[j]));
        return ret;
    }
    var n = [[]];
    for (var i=0; i<z.length; i++)
        n = _xj(n,z[i]);
    return n;
}

a2.createVirtualTriggers = function createVirtualTriggers (tr) {
    var b = tr[0];
    return a2.xJoin($.map(tr, function (val, i) {
        if (i>0 && a2.virtualTriggerMap[b] && a2.virtualTriggerMap[b][i-1] && a2.virtuals[val])
            return [[val].concat(a2.virtuals[val])];
        else
            return [[val]];
    }));
}

a2.fireEvent = function fireEvent(ev) {
    var triggers = a2.createVirtualTriggers(ev);
    for (var i=0; i<triggers.length; i++)
        a2._fireEvent(triggers[i], ev);
}

a2._fireEvent = function _fireEvent (ev, real) {

    if (a2.eventChain.length >= a2.EVENT_CHAIN_MAX_LENGTH) {
        a2.debugError("Abbruch: zu viele Folge-Ereignisse.");
        return; 
    } 
    var evstate = a2.stateEncode() + "|" + ev;
    if (a2.eventChain.indexOf(evstate) > -1) {
        a2.debugError("Abbruch: Ereignis-Rekursion.");
        return; 
    }
    a2.eventChain.push(evstate);

    if ( ev[0] == "enter" || ev[0] == "add" || ev[0] == "remove" )
        a2.updateHash()

    event = ev.join(".");
    a2.log("Fire", event, real);
    a2.debugEvent(event);
    var e = a2.events;
    for(var i in e)
       try {
           for(j=0; e[i][event] !== undefined && j<e[i][event].length; j++){
               a2.log("Event", i, event, j, e[i][event][j]);
               e[i][event][j](real);
           }
       } catch (e) {
           a2.log("Event Exception", e);
       }
};

a2.makeUrl = function makeUrl(p){
    var script = mw.config.get("wgScript");
    var page = mw.config.get("wgPageName");
    return [script, page, p].join("/");
}

a2.updateHash = function updateHash() {
    var hash = "#" + a2.crypt(a2.stateEncode(), true);
    location.hash = hash;
    a2.latestHash = hash;
}

a2.loadPage = function loadPage(n){
    if (isNaN(parseInt(n)) /* || a2.cpage == parseInt(n) */ )
        return;


    var response = $.ajax({
        url: a2.makeUrl(parseInt(n)+"?action=render"),
        async: false
    });

    if (response.status != 200) {
        a2.debugError("Fehler beim Laden von Seite "+n+": "+response.statusText);
        return;
    }

    a2.fireEvent(["leave",a2.cpage]);
    a2.clearScope(":page:");
 
    a2.cpage = n;
    a2.debugPage(n);
    var $content = $(response.responseText)
    $content.append('<scr'+'ipt type="text/javascript">setTimeout(function(){a2.fireEvent(["enter",a2.cpage]); $("#a2loader").hide();}, 100);</scr'+'ipt>');
 
    $("#a2image").empty().append($content);
    console.log($("#a2image a"));

    $("#a2image area").click(function (ev) {
        a2.clearEventChain();
        a2.fireEvent(["click",ev.currentTarget.hash.substr(1)]);
        return false;
    });

    $(".overlay").css("cursor","pointer").click(function (ev) {
        a2.clearEventChain();
        a2.fireEvent(["click",ev.currentTarget.id.split("_")[1]]);
        return false;
    });

    $("#_l, #_r, #_u, #_d").click(function (ev) {
        a2.clearEventChain();
        a2.fireEvent(["click",ev.currentTarget.id]);
        return false;
    });

    $("#a2image img").droppable({
        drop: function (event, ui) {
            var target = a2.ui.getDroparea($(this), ui);
            a2.log("drop", target, event, ui);
            for (var i=0; i<target.length; i++) {
                a2.clearEventChain();
                a2.fireEvent(["apply",ui.draggable.data("item"),target[i].hash.substr(1)]);
            }
        }
    });

   $(".overlay").droppable({
        drop: function (event, ui) {
            a2.clearEventChain();
            a2.fireEvent(["apply",ui.draggable.data("item"),this.id.split("_")[1]]);
    }
  });

};

a2.util = {
    print: function (s, opts) { 
        $("#a2text").text(s);

        // print options for the ask method
        if(opts) {
            var functionBuilder = function (target) {
                return function () {
                    a2.util.print("");
                    a2.fireEvent(["click", target]);
                };
            };

            var ul = $("<ul/>");
            for(var i=0; i<opts.length; i++) {
                var li = $("<li class='pseudolink'/>");
                li.click(functionBuilder(opts[i][0]));
                li.text(opts[i][1]);
                ul.append(li);
            }
            $("#a2text").append(ul);
        }
    },
    goto: function (p) {

        // prevent side effects
        a2.timer.clear();

        // this was for old Widgets!
        //$("audio").each(function (a,b) { b.autoplay = false; b.pause(); });

        // stop background noises, keep music
        a2.audio.stop("background");

        // actually go to page
        a2.loadPage(p);
    },
    timeoutIsSet: function () {
        return ! isNaN(a2.timer.pt);
    }
};


a2.items = {};
a2.loadItem = function loadItem(n){
    a2.log("load", n);

    var response = $.ajax({
        url: a2.makeUrl("item/"+n+"?action=render"),
        async: false
    });

    if (response.status != 200) {
        a2.debugError("Fehler beim Laden von Item "+n+": "+response.statusText);
        return;
    }

    a2.clearScope(n);

    a2.items[n] = response.responseText;
    a2.log(a2.items);
    a2.renderItems();
    a2.fireEvent(["add",n]);
};

a2.renderItems = function renderItems(){
    $("#a2items, #a2pseudoitems").empty()
    a2.debugItems();
    for (var item in a2.items){
        if (item[0] == "_") {
            // skip "virtual" status items
            $("#a2pseudoitems").append(a2.items[item]);
            continue;
        }

        var $flbox=$('<div class="a2itembox" />');
        var $fl=$('<div class="a2item" />');
        $flbox.append($fl);
        $fl.append(a2.items[item]);
        $("#a2items").append($flbox);
        $fl.draggable({
            // cursorAt: {top: -5, left: -5},
            revert: true,
            zIndex: 10000,
            start: function(event, ui) {
                ui.helper.bind("click.prevent", function(event) { event.preventDefault(); });
            },
            stop: function(event, ui) {
                setTimeout(function(){ui.helper.unbind("click.prevent");}, 300);
            }
        });
        $fl.data("item",item);
        $fl.click(function () {
            a2.clearEventChain();
            a2.fireEvent(["activate",$(this).data("item")]);
        });
        $fl.droppable({
            drop: function (event, ui) {
                a2.clearEventChain();
                a2.fireEvent(["combine",ui.draggable.data("item"),$(this).data("item")]);
                return false;
            }
        });
        a2.log($("#a2items"))
    }
}

a2.util.add = function add (i) {
    a2.loadItem(i);
};
a2.util.remove = function remove(i) {
    delete a2.items[i]; 
    delete a2.events[i];
    delete a2.virtuals[i];
    a2.renderItems();
    a2.fireEvent(["remove",i]);
};

a2.util.removeAll = function removeAll(v) {
    for (i in a2.virtuals)
        if( a2.virtuals[i].indexOf(v) > -1 ) {
            delete a2.items[i]; 
            delete a2.events[i];
            delete a2.virtuals[i];
            a2.fireEvent(["remove",i]);
    }
    a2.renderItems();
}

a2.util.hasVirtual = function hasVirtual (v) {
    for (i in a2.virtuals)
        if( a2.virtuals[i].indexOf(v) > -1 )
            return i;
    return false;
}

a2.ui = {};
a2.ui.getAreaBox = function getAreaBox (area) {
    var $area = $(area);
    var shape = $area.attr("shape");
    var p = $area.attr("coords");
    p = p.split(",")
    p = $.map(p, function(x){ return parseInt(x);});

    if (shape == "circle"){
        var x1 = p[0] - p[2];
        var y1 = p[1] - p[2];
        var x2 = p[0] + p[2];
        var y2 = p[1] + p[2];
    } else {
        var x1 = Infinity;
        var y1 = Infinity;
        var x2 = -Infinity;
        var y2 = -Infinity;
        for(var i=0; i<p.length; i=i+2){
            if (p[i] < x1) x1 = p[i];
            if (p[i+1] < y1) y1 = p[i+1];
            if (p[i] > x2) x2 = p[i];
            if (p[i+1] > y2) y2 = p[i+1];
        }
    }

    return {x1:x1, y1:y1, x2:x2, y2:y2};
};

a2.ui.getDroparea = function getDroparea (img, ui) {
    var $areas = $("area");
    return $areas.filter(function () {
        var b = a2.ui.getAreaBox(this);
        var s = 25; // half itemsize

        var xm = (b.x1 + b.x2) / 2;
        var ym = (b.y1 + b.y2) / 2;

        var dx = ui.offset.left - $(img).offset().left + s;
        var dy = ui.offset.top - $(img).offset().top + s;

        return (b.x1 < dx && dx < b.x2 &&
                b.y1 < dy && dy < b.y2) ||
               (dx - s < xm && xm < dx + s &&
                dy - s < ym && ym < dy + s);            
    });
}

a2.stateEncode = function () {
    var s = String(a2.cpage);
    for (var i in a2.items)
        s+="|"+i;
    return s
}

a2.stateDecode = function (s) {
    a2.clearEventChain();
    var c = s.split("|");
    a2.items = {};
    a2.virtuals = {};
    a2.events = {}
    for (var j=1; j<c.length; j++) {
        a2.items[c[j]] = "<img src='/images/a/a6/A2loading.gif' alt='Loading …' />";
    }
    a2.renderItems();
    for (var j=1; j<c.length; j++)
        a2.loadItem(c[j]);
    a2.loadPage(parseInt(c[0]));
}

a2.crypt = function crypt (str, encode) {
    if (encode){
        var n = Math.floor((Math.random()*9))+1;
        out = String(n);
    } else {
        var n = - parseInt(str.substr(0,1));
        var out = "";
        str = str.substr(1);
    }
    var chain = "pwoTä7eGNVk1SAldv0mJ9zIöPE4x8rF|B6ybüjZDC5cqfRhOXsQY23iUngLWuMHatK";
    var mk = function(i){ return i % chain.length };

    for (var i=0; i<str.length; i++) {
        var c = str.substr(i,1);
        var ind = chain.indexOf(c);
        if (ind == -1)
            out += c;
        else
            out += chain.substr(mk(ind + n),1);
    }
    return out;
}

/* DEBUGGER */

a2.debugEvent = function debugEvent (ev) {
    if (!$("#a2dbgBottom").length)
        return;

    $("#a2dbgEventLog").append($("<li/>").text(ev).append("<ul/>"));
    $("#a2dbgBottom:visible").scrollTop($("#a2dbgBottom")[0].scrollHeight);
}

a2.debugEventInstance = function debugEventInstance (sc,n,cond) {
    if (!$("#a2dbgBottom").length)
        return;

    var classname = cond ? "a2fired" : "a2notfired";
    $("#a2dbgEventLog li ul").last().append($("<li/>").text(sc+"->"+n).addClass(classname));
    $("#a2dbgBottom:visible").scrollTop($("#a2dbgBottom")[0].scrollHeight);
}

a2.debugPage = function debugPage (p) {
   $("#a2dbgGoto").val(p);
}

a2.debugItems = function debugItems() {
   var s = [];
   for (i in a2.items)
       s.push(i);
   $("#a2dbgItems").val(s.join("\n"));
}

a2.debugError = function debugError(text) {
    if (!$("#a2dbgBottom").length)
        return;

    a2.errorCount ++;
    $("#a2errorCount").text(a2.errorCount);
    $("#a2dbgEventLog").append($("<li/>").text(text).addClass("a2error"));
    $("#a2dbgBottom:visible").scrollTop($("#a2dbgBottom")[0].scrollHeight);
}

// provide timer functions
a2.timer = {
    time: 0,
    pt: NaN,
    fn: null,
    set: function set(n, fn) {
    
        if (! isNaN(a2.timer.pt)) {
	    // do not set timer if timer already active
            return;
        }
            
        a2.timer.time = n;
        a2.timer.fn = fn;
        
        a2.timer.pt = setInterval(function () {
            a2.timer.time--;
    
            if (a2.timer.time <= 0) {
                clearInterval(a2.timer.pt);
                a2.timer.pt = NaN;
                $("#_t").text("0:00").fadeOut('slow');
                fn();
                return;
            }
        
            var sec = a2.timer.time % 60;
        
            if (sec < 10)
                sec = "0" + sec;
            $("#_t").show().text(String(Math.floor(a2.timer.time / 60)) + ":" + sec );
        }, 1000);
    },
    
    clear: function clear() {
        if (! isNaN(a2.timer.pt)) {
            clearInterval(a2.timer.pt);
            a2.timer.pt = NaN;
            $("#_t").fadeOut();
        }
    }
};

// provide audio functions
a2.audio = {
    cache: {},
    current: [],

    fetch: function fetch(file) {
            var data = $.ajax({
            type: "GET",
            url: "/api.php",
            data: {
                action: "parse",
                format: "xml",
                text: "{{filepath:"+file+"}}"
            }, 
            async: false
        });
        
        var html = $(data.responseText).find("text").text();
        var url = $(html).find("a")[0].href;
        return url;
    },

    getaudio: function getaudio(file) {
        if (a2.audio.cache[file]) {
            return a2.audio.cache[file];
        } else {
            var url = a2.audio.fetch(file);
            a2.audio.cache[file] = url;
            return url;
        }
    },

    play: function play(channel, file) {
        var $player = $("#a2audio_channel_"+channel)[0];
        var audiofile = a2.audio.getaudio(file);

        if (audiofile != a2.audio.current[channel]) {        
            $player.pause();
            $player.src = a2.audio.getaudio(file);
            $player.load();
            $player.play();
            a2.audio.current[channel] = audiofile;
        }
    },

    stop: function stop(channel) {
        var $player = $("#a2audio_channel_"+channel)[0];
        $player.pause();
        a2.audio.current[channel] = null;
    }
}