Effect.FastShake = function(element) {
  element = $(element);
  var oldStyle = {
    top: element.getStyle('top'),
    left: element.getStyle('left') };
    return new Effect.Move(element, 
      { x:  5, y: 0, duration: 0.02, afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x: -10, y: 0, duration: 0.04,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x:  10, y: 0, duration: 0.04,  afterFinishInternal: function(effect) {
    new Effect.Move(effect.element,
      { x: -5, y: 0, duration: 0.02, afterFinishInternal: function(effect) {
        effect.element.undoPositioned();
        effect.element.setStyle(oldStyle);
  }}) }}) }}) }});
}

function arrayShuffle(){
  var tmp, rand;
  for(var i =0; i < this.length; i++){
    rand = Math.floor(Math.random() * this.length);
    tmp = this[i]; 
    this[i] = this[rand]; 
    this[rand] =tmp;
  }
}

Array.prototype.shuffle =arrayShuffle;

function memory_init(node)
{
    node.appendChild(document.createTextNode('\xa0'));
    node._memory_side = 0;
}

function memory_show(node)
{
    node.removeChild(node.childNodes[0]);
    var text = document.createTextNode(node._memory_value);
    var inner = document.createElement('span');
    inner.appendChild(text);
    node.appendChild(inner);
    node.className = 'clicked';
    node._memory_side = 1;
}

function memory_hide(node)
{
    node.className = '';
    node.removeChild(node.childNodes[0]);
    memory_init(node);
}

function memory_status(stat)
{
    //stat.innerHTML = stat._memory_correct+' richtig, '+stat._memory_wrong+' falsch';
    stat.innerHTML = stat._memory_correct+' von '+stat._memory_total+' richtig gelöst';
}
function memory_wrong(stat)
{
    stat._memory_wrong++;
    memory_status(stat);
}
function memory_correct(stat)
{
    stat._memory_correct++;
    memory_status(stat);
}

function memory_create(where, stat, data)
{
    var i;
    var divs = [];

    stat._memory_correct = 0;
    stat._memory_wrong = 0;
    stat._memory_total = data.length;

    for (i=0;i<data.length;i++)
    {
        var div;
        div  = document.createElement('div');
        divs[2*i] = div;
        //div.appendChild(document.createTextNode(data[i][0]));
        div._memory_id = i;
        div._memory_value = data[i][0];
        memory_init(div);

        div = document.createElement('div');
        divs[2*i+1] = div;
        //div.appendChild(document.createTextNode(data[i][1]));
        div._memory_id = i;
        div._memory_value = data[i][1];
        memory_init(div);
    }
    divs.shuffle();
    for (i=0;i<divs.length;i++)
    {
        divs[i].onclick = function(event)
        {
            if (!event) var event = window.event;
            var target = event.target;  
            if (!target) target = event.srcElement;
            var parent = target.parentNode;
            if (target._memory_side == undefined)
            {
                target = target.parentNode;
                parent = parent.parentNode;
            }
            //alert(target._memory_side);
            if (target._memory_side == 1 && parent._memory_status != 2) return; // already visible

            if (parent._memory_status < 2)
            {
                memory_show(target);
                if (parent._memory_status == 0)
                    parent._memory_1 = target;
                else // 1
                    parent._memory_2 = target;
            }
            parent._memory_status++;
            if (parent._memory_status == 3)
            {
                // no match, hide the cards
                memory_hide(parent._memory_1);
                memory_hide(parent._memory_2);
                parent._memory_status = 0;
            }
            if (parent._memory_status == 2)
            {
                if (parent._memory_1._memory_id == parent._memory_2._memory_id)
                { // match, keep the cards visible
                    parent._memory_status = 0;
                    memory_correct(stat);
                    new Effect.Highlight(parent._memory_1, {endcolor:'#ffffcc', restorecolor:'#ffffcc'});
                    new Effect.Highlight(parent._memory_2, {endcolor:'#ffffcc', restorecolor:'#ffffcc'});
                }
                else
                {
                    // no match, shake the cards
                    memory_wrong(stat);
                    new Effect.FastShake(parent._memory_1, {startcolor:'#ff9999'});
                    new Effect.FastShake(parent._memory_2, {startcolor:'#ff9999'});
                }
            }
        }
        where.appendChild(divs[i]);
    }
    where._memory_status = 0;
}

