SP_ZIndex         = 100;
Window            = {};
Window.startFuncs = [];

Window.start = function( func, timeout ){
  Window.startFuncs.push( [ func, timeout || null ] );
};

Window.onStart = function(){
  for( var i = 0; i < Window.startFuncs.length; i++ ){
    var item = Window.startFuncs[i];
    if ( item[1] == null ) {
      Window.runOnLoad( i );
    } else {
      window.setTimeout( "Window.runOnLoad(" + i + ");", item[1] );
    }
  }
};

Window.runOnLoad = function( nr ){
  Window.startFuncs[nr][0]();
};

window.onload = Window.onStart;

Element.create = function( elem, text, style, attr ){
  var e = $(document.createElement( elem ));
  Element.extend(e);
  // Element.makePositioned(e);
  if ( text != null )
    e.update( text );
  if ( style )
    e.setStyle( style );
  if ( attr )
    for (var name in attr)
      Element.setAttribute( e, name, attr[name] );
  return e;
};

Element.setAttribute = function( elem, key, value ){
  var translation = { colspan:   "colSpan",
                      rowspan:   "rowSpan",
                      valign:    "vAlign",
                      datetime:  "dateTime",
                      accesskey: "accessKey",
                      tabindex:  "tabIndex",
                      enctype:   "encType",
                      maxlength: "maxLength",
                      readonly:  "readOnly",
                      longdesc:  "longDesc",
                      className: function(e,k,v){$A(v.split(' ')).each( function(item){Element.addClassName(e,item)})}
                    },
      keyName = translation[key.toLowerCase()] || key;
  if ( typeof keyName == 'function' ){
    keyName( elem, key, value );
  } else {
    elem.setAttribute( keyName, value );
    elem[keyName] = value;
  }
};

Element.change = function( elem, text, style, attr ){
  var e = elem;
  if (typeof e == 'string')
    e = document.getElementById(e);
  if ( text )
    e.innerHTML = text;
  if ( style )
    for (var name in style)
      e.style[ name.camelize() ] = style[name];
  if ( attr )
    for (var name in attr)
      Element.setAttribute( e, name, attr[name] );
  return $(e);
};

Element.append = function() {
  var args = arguments;
  if ( ! ( args[0] instanceof Array ) ){
    var elem = args[0];
    for ( var j = 1; j < args.length; j++ ){
      var arg = args[j];
      if ( typeof arg != 'string' ){
        elem.appendChild( arg );
      } else {
        var span = Element.create( 'span', arg );
        elem.appendChild( span );
      }
    }
  } else {
    for ( var i = 0; i < args.length; i++ ){
      var arg  = args[i],
          elem = arg.shift();
      for ( var j = 0; j < arg.length; j++ ){
        if ( typeof arg[j] != 'string' ){
          elem.appendChild( arg[j] );
        } else {
          var span = Element.create( 'span', arg[j] );
          elem.appendChild( span );
        }
      }
    }
  }
};

Element.appendBefore = function() {
  var arguments = Element.appendBefore.arguments;
  if ( ! ( arguments[0] instanceof Array ) ){
    var elem   = arguments[0],
        parent = elem.parentNode;
    for ( var j = 1; j < arguments.length; j++ ){
      var arg = arguments[j];
      if ( typeof arg != 'string' ){
        parent.insertBefore( arg, elem );
      } else {
        var span = Element.create( 'span', arg );
        parent.insertBefore( span, elem );
      }
    }
  } else {
    for ( var i = 0; i < arguments.length; i++ ){
      var arg    = arguments[i],
          elem   = arg.shift(),
          parent = elem.parentNode;
      for ( var j = 0; j < arg.length; j++ ){
        if ( typeof arg[j] != 'string' ){
          parent.insertBefore( arg[j], elem );
        } else {
          var span = Element.create( 'span', arg[j] );
          parent.insertBefore( span, elem );
        }
      }
    }
  }
};

Element.appendAfter = function() {
  var arguments = Element.appendAfter.arguments;
  if ( ! ( arguments[0] instanceof Array ) ){
    var elem   = arguments[0],
        parent = elem.parentNode;
    for ( var j = 1; j < arguments.length; j++ ){
      var arg = arguments[j];
      if ( typeof arg != 'string' ){
        parent.insertBefore( arg, elem.nextSibling );
      } else {
        var span = Element.create( 'span', arg );
        parent.insertBefore( span, elem.nextSibling );
      }
    }
  } else {
    for ( var i = 0; i < arguments.length; i++ ){
      var arg    = arguments[i],
          elem   = arg.shift(),
          parent = elem.parentNode;
      for ( var j = 0; j < arg.length; j++ ){
        if ( typeof arg[j] != 'string' ){
          parent.insertBefore( arg[j], elem.nextSibling );
        } else {
          var span = Element.create( 'span', arg[j] );
          parent.insertBefore( span, elem.nextSibling );
        }
      }
    }
  }
};


Element.clear = function( elem ) {
  var e = $(elem);
  $A(e.childNodes).each( function( elem ){ e.removeChild( elem ) } );
};

String.prototype.sprintf = function() {
    var pad = function(str,ch,len){ 
      var ps='';
      for(var i=0; i<Math.abs(len); i++) ps+=ch;
      return len>0?str+ps:ps+str;
    };
    var processFlags = function(flags,width,rs,arg){ 
      var pn = function(flags,arg,rs)
        { if(arg>=0)
            { if(flags.indexOf(' ')>=0) rs = ' ' + rs;
              else if(flags.indexOf('+')>=0) rs = '+' + rs;
            }
          else
              rs = '-' + rs;
          return rs;
        }
      var iWidth = parseInt(width,10);
      if(width.charAt(0) == '0')
        { var ec=0;
          if(flags.indexOf(' ')>=0 || flags.indexOf('+')>=0) ec++;
          if(rs.length<(iWidth-ec)) rs = pad(rs,'0',rs.length-(iWidth-ec));
          return pn(flags,arg,rs);
        }
      rs = pn(flags,arg,rs);
      if(rs.length<iWidth)
        { if(flags.indexOf('-')<0) rs = pad(rs,' ',rs.length-iWidth);
          else rs = pad(rs,' ',iWidth - rs.length);
        }
      return rs;
    };
    var converters = { 
      c: function(flags,width,precision,arg){ 
        if ( typeof(arg) == 'number' ) return String.fromCharCode(arg);
        if ( typeof(arg) == 'string' ) return arg.charAt(0);
        return '';
      },
      d: function(flags,width,precision,arg){ 
        return converters['i'](flags,width,precision,arg);
      },
      u: function(flags,width,precision,arg){ 
        return converters['i'](flags,width,precision,Math.abs(arg));
      },
      i: function(flags,width,precision,arg) { 
        var iPrecision=parseInt(precision);
        var rs = ((Math.abs(arg)).toString().split('.'))[0];
        if(rs.length<iPrecision) rs=pad(rs,' ',iPrecision - rs.length);
        return processFlags(flags,width,rs,arg);
      },
      E: function(flags,width,precision,arg){ 
        return (converters['e'](flags,width,precision,arg)).toUpperCase();
      },
      e: function(flags,width,precision,arg){
        iPrecision = parseInt(precision);
        if(isNaN(iPrecision)) iPrecision = 6;
        rs = (Math.abs(arg)).toExponential(iPrecision);
        if(rs.indexOf('.')<0 && flags.indexOf('#')>=0) rs = rs.replace(/^(.*)(e.*)$/,'$1.$2');
        return processFlags(flags,width,rs,arg);
      },
      f: function(flags,width,precision,arg){ 
        iPrecision = parseInt( precision );
        if( isNaN(iPrecision) ) iPrecision = 6;
        rs = ( Math.abs(arg) ).toFixed(iPrecision);
        if( rs.indexOf('.') < 0 && flags.indexOf('#') >= 0 ) rs = rs + '.';
        return processFlags(flags,width,rs,arg);
      },
      G: function(flags,width,precision,arg) { 
        return (converters['g'](flags,width,precision,arg)).toUpperCase();
      },
      g: function(flags,width,precision,arg) { 
        iPrecision = parseInt(precision);
        absArg = Math.abs(arg);
        rse = absArg.toExponential();
        rsf = absArg.toFixed(6);
        if(!isNaN(iPrecision))
          { rsep = absArg.toExponential(iPrecision);
            rse = rsep.length < rse.length ? rsep : rse;
            rsfp = absArg.toFixed(iPrecision);
            rsf = rsfp.length < rsf.length ? rsfp : rsf;
          }
        if(rse.indexOf('.')<0 && flags.indexOf('#')>=0) rse = rse.replace(/^(.*)(e.*)$/,'$1.$2');
        if(rsf.indexOf('.')<0 && flags.indexOf('#')>=0) rsf = rsf + '.';
        rs = rse.length<rsf.length ? rse : rsf;
        return processFlags(flags,width,rs,arg);
      },
      o: function(flags,width,precision,arg) { 
        var iPrecision=parseInt(precision);
        var rs = Math.round(Math.abs(arg)).toString(8);
        if(rs.length<iPrecision) rs=pad(rs,' ',iPrecision - rs.length);
        if(flags.indexOf('#')>=0) rs='0'+rs;
        return processFlags(flags,width,rs,arg);
      },
      X: function(flags,width,precision,arg){
        return (converters['x'](flags,width,precision,arg)).toUpperCase();
      },
      x: function(flags,width,precision,arg) { 
        var iPrecision=parseInt(precision);
        arg = Math.abs(arg);
        var rs = Math.round(arg).toString(16);
        if(rs.length<iPrecision) rs=pad(rs,' ',iPrecision - rs.length);
        if(flags.indexOf('#')>=0) rs='0x'+rs;
        return processFlags(flags,width,rs,arg);
      },
      s: function(flags,width,precision,arg){ 
        var iPrecision=parseInt(precision),
            rs = arg;
        if(rs.length > iPrecision) rs = rs.substring(0,iPrecision);
        return processFlags(flags,width,rs,0);
      }
    };
    farr   = this.split("%");
    retstr = farr[0];
    fpRE   = /^([-+ #]*)(\d*)\.?(\d*)([cdieEfFgGosuxX])(.*)$/;
    for ( var i = 1;  i < farr.length; i++ ){ 
      fps = fpRE.exec( farr[i] );
      if ( ! fps ) 
        continue;
      if ( arguments[i-1] != null) 
        retstr += converters[fps[4]](fps[1],fps[2],fps[3],arguments[i-1]);
      retstr += fps[5];
    }
    return retstr;
};


var TimeStamp = Class.create();

Object.extend( TimeStamp.prototype, {
  initialize: function( year, month, day, hour, min, sec ){
    this.year    = year  == null ? 1900 : year  * 1;
    this.month   = month == null ?    1 : month * 1;
    this.day     = day   == null ?    1 : day   * 1;
    this.hour    = hour  == null ?    0 : hour  * 1;
    this.min     = min   == null ?    0 : min   * 1;
    this.sec     = sec   == null ?    0 : sec   * 1;
    this.dateObj = new Date( year, month - 1, day, hour, min, sec );
  },

  date: function() {
    return "%02d.%02d.%04d".sprintf( this.day, this.month, this.year );
  },
  time: function() {
    return "%02d:%02d:%02d".sprintf( this.hour, this.min, this.sec );
  },
  isoDate: function() {
    return "%04d-%02d-%02d".sprintf( this.year, this.month, this.day );
  },
  toString: function() {
    return this.isoDate() + " " + this.time();
  }
} );

Date.prototype.strftime = function( template ){
  var language = navigator.language || navigator.userLanguage,
      date     = this,
      captions = { de: { Week:  { Short:  [ 'So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa' ],
                                  Long:   [ 'Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag' ] },
                         Month: { Short:  [ 'Jan', 'Feb', 'Mrz', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez' ],
                                  Long:   [ 'Januar', 'Febuar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember' ] } },
                   en: { Week:  { Short:  [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ],
                                  Long:   [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ] },
                         Month: { Short:  [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ],
                                  Long:   [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ] } }
                 },
      dconv = { a: function(){ 
                     return captions[language]['Week']['Short'][date.getDay()];
                   },
                A: function(){ 
                     return captions[language]['Week']['Long'][date.getDay()];
                   },
                b: function(){ 
                     return captions[language]['Month']['Short'][date.getMonth()];
                   },
                B: function(){ 
                     return captions[language]['Month']['Long'][date.getMonth()];
                   },
                c: function(){
                     return date.toLocaleString();
                   },
                C: function(){
                     return "%02d".sprintf( date.getFullYear() % 100 );
                   },
                d: function(){
                     return "%02d".sprintf( date.getDate() );
                   },
                D: function(){
                     return "%s/%s/%s".sprintf( dconv.m(), dconv.d(), dconv.y() );
                   },
                e: function(){
                     return "%2s".sprintf( date.getDate() );
                   },
                c: function(){
                     return date.toGMTString();
                   },
                h: function(){ 
                     return captions[language]['Month']['Short'][date.getMonth()];
                   },
                H: function(){ 
                     return "%02d".sprintf( date.getHours() );
                   },
                I: function(){ 
                     return "%02d".sprintf( date.getHours() % 12 );
                   },
                j: function(){ 
                     return "%03d".sprintf( date.getDayOfYear() );
                   },
                m: function(){ 
                     return "%02d".sprintf( date.getMonth() );
                   },
                M: function(){ 
                     return date.getMinutes();
                   },
                n: function(){ 
                     return "\n";
                   },
                p: function(){ 
                     return date.getHours() <= 11 ? 'AM' : 'PM';
                   },
                r: function(){ 
                     return "%s:%s:%s %s".sprintf( dconv.I(), dconv.M(), dconv.S(), dconv.p() );
                   },
                R: function(){ 
                     return "%s:%s".sprintf( dconv.H(), dconv.M() );
                   },
                S: function(){ 
                     return date.getSeconds();
                   },
                t: function(){ 
                     return "\t";
                   },
                T: function(){ 
                     return "%s:%s:%s".sprintf( dconv.H(), dconv.M(), dconv.S() );
                   },
                w: function(){ 
                     return date.getDay();
                   },
                W: function(){ 
                     return date.getCalWeek();
                   },
                y: function(){ 
                     return "%02d".sprintf( date.getFullYear() % 100 );
                   },
                Y: function(){ 
                     return "%04d".sprintf( date.getFullYear() );
                   },
                Z: function(){ 
                     return "GMT%s%d".sprintf( date.getTimezoneOffset() < 0 ? '-' : '+', Math.abs( date.getTimezoneOffset() ) / 60 );
                   },
                '%': function(){ 
                     return "%";
                   }
              },
      darr   = template.split("%"),
      drc    = darr[0],
      dre    = /(%([aAbBcCdDefFhHIjmMnprRStTuUVwWxXyYZ%]))/,
      dps    = null;

  while ( dps = dre.exec( template ) ){
    var result = '',
        re     = new RegExp( dps[1] );
    if ( dconv[dps[2]] )
      result = dconv[dps[2]]();
    template = template.replace( re, result );
  }
  return template;
};

// %g - wie %G, aber ohne Jahrhundert.
// %G - Das vierstellige Jahr entsprechend der ISO Wochennummer (siehe %V). 
//      Das gleiche Format und der gleiche Wert wie bei %Y. Besonderheit: entspricht die ISO Wochennummer dem vorhergehenden oder folgenden Jahr, wird dieses Jahr verwendet.
// %U - Nummer der Woche des aktuellen Jahres als Dezimal-Wert, beginnend mit dem ersten Sonntag als erstem Tag der ersten Woche.
// %V - Kalenderwoche (nach ISO 8601:1988) des aktuellen Jahres. Als Dezimal-Zahl mit dem Wertebereich 01 bis 53, wobei die Woche 01 die erste Woche mit mindestens 
//      4 Tagen im aktuellen Jahr ist. Die Woche beginnt montags (nicht sonntags). (Benutzen Sie %G or %g für die Jahreskomponente, die der Wochennummer für den gegebenen Timestamp entspricht.)
// %W - Nummer der Woche des aktuellen Jahres, beginnend mit dem ersten Montag als erstem Tag der ersten Woche.
// %x - bevorzugte Datumswiedergabe (ohne Zeit), abhängig von der gesetzten Umgebung.
// %X - bevorzugte Zeitwiedergabe (ohne Datum), abhängig von der gesetzten Umgebung.

Date.prototype.getDayOfYear = function(){
  return(Math.ceil((this.getTime()-(new Date(this.getFullYear(),0,1)).getTime())/86400000));
};

Date.prototype.getCalWeek = function(){
  function getThursday( date ){
    var thursday = new Date();
    thursday.setTime( date.getTime() + ( 3 - ((date.getDay() + 6 ) % 7 )) * 86400000);
    return thursday;
  };
  var thursday = getThursday( this ),
      calyear  = thursday.getFullYear(),
      thcw1    = getThursday( new Date( calyear, 0, 4 ) );
  return Math.floor( 1.5 + (thursday.getTime() - thcw1.getTime()) / 86400000/7);
};


