unitLoad('boxeffects', null, function (unitObj) {

 function getTickCount () {
  var T = new Date();
  return T.getMilliseconds() + T.getSeconds() * 1000 + T.getMinutes() * 60000 + T.getHours() * 3600000 + T.getDay() * 86400000;
 }

 function cssEffect (el, duration, behaviour, from, to, callback) { // Style-effekt:  behaviour=Funktion:[0..1]-->[0..1]  from,to=Objekt mit Style-Eigenschaften
  function splitNum (s) {
   var a = new Array('');
   for (var i = 0; i < s.length; i++) {
    if ((s.charCodeAt(i) >= 48 && s.charCodeAt(i) <= 57 || s.charCodeAt(i) == 45) || (s.charAt(i) == '.' && a[a.length-1].charAt(0) == '0')) { if (a[a.length-1].charAt(0) != '0') a.push('0'); }
    else { if (a[a.length-1].charAt(0) == '0') { a[a.length-1] = parseFloat(a[a.length-1].substring(1)); a.push(''); } }
    a[a.length-1] += s.charAt(i);
   }
   if (a[a.length-1].charAt(0) == '0') a[a.length-1] = parseFloat(a[a.length-1].substring(1));
   return a;
  }
  duration = parseInt(duration);
  if (behaviour == null) behaviour = function (s) { return s; };
  if (!from) from = window.getComputedStyle(el);
  else for (var key in from) el.style[key] = from[key];
  for (var key in to) {
   from[key] = splitNum(from[key]);
   to[key] = splitNum(to[key]);
  }
  var startTime = getTickCount();
  var stop = false;
  function f (end) {
   if (stop) return;
   var t = getTickCount();
   if ((end == 0) || (end == 1) && (startTime + duration > t)) {
    s = behaviour((t - startTime) / duration);
    for (var key in to) {
     var v = '';
     var r = 0;
     for (var i = 0; i < to[key].length; i++) {
      if (typeof to[key][i] == 'string') { if (to[key][i].indexOf('rgb') != -1) r = 3; v += to[key][i]; }
      else if (r > 0) { v += (from[key][i] * (1-s) + to[key][i] * s); r--; }
      else v += (from[key][i] * (1-s) + to[key][i] * s);
     }
     el.style[key] = v;
    }
    window.setTimeout(f, 10, 1);
   } else {
    stop = true;
    for (var key in to) el.style[key] = to[key].join('');
    if (callback) callback();
   }
  }
  f(0);
  if (duration == 0) window.setTimeout(f, 0, 2);
  else window.setTimeout(f, 10, 1);
  return function (finish) {
   if (stop) return;
   if (finish) f(2);
   else {
    stop = true;
    if (callback) callback();
   }
  };
 }

 function move (el, duration, behaviour, blendIn, callback, dir) {
  var p = el.offsetParent;
  var d = 0;
  var t;
  switch (dir) {
   case 1 :
    t = 'top';
    d = el.offsetTop + el.offsetHeight;
    break;
   case 2 :
    t = 'left';
    d = el.offsetLeft + el.offsetWidth;
    break;
   case 3 :
    t = 'left';
    d = - p.offsetWidth + el.offsetLeft;
    break;
   case 4 :
    t = 'top';
    d = - p.offsetHeight + el.offsetTop;
    break;
  }
  var s = window.getComputedStyle(el);
  if (s.position != 'fixed' && s.position != 'absolute' && s.position != 'relative') el.style.position = 'relative';
  var from = new Object();
  var to = new Object();
  from[t] = parseFloat(s[t]) - ((blendIn)?d:0) + 'px';
  to[t] = parseFloat(s[t]) - ((blendIn)?0:d) + 'px';
  return cssEffect(el, duration, behaviour, from, to, callback);
 }
 
 function clip (el, duration, behaviour, blendIn, callback, dir) {
  var st = window.getComputedStyle(el);
  var oldOverflow = el.style.overflow;
  var oldPosition = el.style.position;
  var oldTop = el.style.top;
  var oldLeft = el.style.left;
  var oldWidth = el.style.width;
  var oldHeight = el.style.height;
  el.style.overflow = 'hidden';
  if (st.position != 'absolute' && st.position != 'fixed') {
   var x = el.offsetLeft;
   var y = el.offsetTop;
   var w = el.offsetWidth;
   var h = el.offsetHeight;
   el.style.position = 'absolute';
   el.style.top = y+'px';
   el.style.left = x+'px';
   el.style.height = h+'px';
   el.style.width = w+'px';
  }
  switch (dir) {
   case 1:
    var from = { clip:'rect(0px,'+el.offsetWidth+'px,'+el.offsetHeight+'px,0px)' };
    var to = { clip:'rect('+(el.offsetHeight/2)+'px,'+el.offsetWidth+'px,'+(el.offsetHeight/2)+'px,0px)' };
    break;
   case 2:
    var from = { clip:'rect(0px,'+el.offsetWidth+'px,'+el.offsetHeight+'px,0px)' };
    var to = { clip:'rect(0px,'+(el.offsetWidth/2)+'px,'+el.offsetHeight+'px,'+(el.offsetWidth/2)+'px)' };
    break;
  }
  if (blendIn) { var r = from; from = to; to = r; }
  return cssEffect(el, duration, behaviour, from, to, function () {
   el.style.position = oldPosition;
   el.style.top = oldTop;
   el.style.left = oldLeft;
   el.style.width = oldWidth;
   el.style.height = oldHeight;
   el.style.overflow = oldOverflow;
   el.style.clip = 'auto';
   if (callback) callback();
  });
 }

 function torteFillFilter (el, duration, b, i, callback) {
  var startTime = getTickCount();
  var stop = false;
  function f (end) {
   if (stop) return;
   var t = getTickCount();
   var s = (t - startTime) / duration;
   if ((end == 0) || (end == 1) && (s < 1)) {
    var angle = 2 * Math.PI * s;
    if (s < 0.25) el.style.clipPath = 'polygon(50% 50%, 50% -250%, '+(50 + 300*Math.sin(angle))+'% '+(50 - 300*Math.cos(angle))+'%)';
    else if (s < 0.5) el.style.clipPath = 'polygon(50% 50%, 50% -250%, 350% 50%, '+(50 + 300*Math.sin(angle))+'% '+(50 - 300*Math.cos(angle))+'%)';
    else if (s < 0.75) el.style.clipPath = 'polygon(50% 50%, 50% -250%, 350% 50%, 50% 350%, '+(50 + 300*Math.sin(angle))+'% '+(50 - 300*Math.cos(angle))+'%)';
    else el.style.clipPath = 'polygon(50% 50%, 50% -250%, 350% 50%, 50% 350%, -250% 50%, '+(50 + 300*Math.sin(angle))+'% '+(50 - 300*Math.cos(angle))+'%)';
    window.setTimeout(f, 10, 1);
   } else {
    stop = true;
    el.style.clipPath = 'initial';
    if (callback) callback();
   }
  }
  f(0);
  if (duration == 0) window.setTimeout(f, 0, 2);
  else window.setTimeout(f, 10, 1);
  return function (finish) {
   if (stop) return;
   if (finish) f(2);
   else {
    stop = true;
    if (callback) callback();
   }
  };
 }

 /*
  el : element to perform the effect on
  d : duration
  b : behaviour - a function [0,1] -> [0,1] to modify the progress speed
  i : true for blend in, false for blend out
  c : callback
 */
 this.boxEffects = {
  torteFill : function (el, d, b, i, c) { return torteFillFilter(el, d, b, i, c); },
  blend : function (el, d, b, i, c) { return cssEffect(el, d, b, {opacity:(i)?'0':'1'}, {opacity:(i)?'1':'0'}, c); },
  moveTop : function (el, d, b, i, c) { return move(el, d, b, i, c, 1); },
  moveLeft : function (el, d, b, i, c) { return move(el, d, b, i, c, 2); },
  moveRight : function (el, d, b, i, c) { return move(el, d, b, i, c, 3); },
  moveBottom : function (el, d, b, i, c) { return move(el, d, b, i, c, 4); },
  clipHorizontal : function (el, d, b, i, c) { return clip(el, d, b, i, c, 1); },
  clipVertical : function (el, d, b, i, c) { return clip(el, d, b, i, c, 2); },
  evaporate : function (el, d, b, i, c) { return cssEffect(el, d, b, {opacity:'1', transform:'translate(0px,0px) scale(1,1)', filter:'blur(0px)'}, {opacity:'0', transform:'translate(0px,-50px) scale(1.5,1.7)', filter:'blur(5px)'}, c); }
 };

 // unit loaded
 unitObj.unit = this;
 unitObj.onload();
});
