
Content         = Class.create();

Object.extend( Object.extend( Content.prototype, Swim.prototype ), {
  initialize: function( parent, container, data, options ){
    var child         = container.childElements(),
        test          = undefined;
    this.parent       = parent;
    this.container    = container;
    this.data         = data;

    this.id           = container.id;
    this.ajax         = container.readAttribute('ajax');
    this.open         = container.readAttribute('open');
    this.context      = container.readAttribute('context');
    this.hasfold      = container.readAttribute('hasfold') || 'true';

    this.container    = container;
    this.bar          = child[0];
    this.content      = child[1];
    this.view         = child[2];
    this.fold         = this.bar.select( 'img.Fold' )[0];
    this.caption      = this.bar.select( 'span.Caption' )[0];
    this.fan          = this.bar.select( 'img.Loading' )[0];
    this.foldmsg      = this.bar.select( 'span.FoldMsg' )[0];
    this.loaded       = false;
    this.foldState    = true;
    this.setOptions();

    if ( this.hasfold && this.hasfold == 'true' ){
      this.bar.addClassName( 'Fold' );
      Event.observe( this.bar, 'click',       this.foldClick.bind( this ) );
    }
    if ( this.context && this.context == 'true' )
      Event.observe( this.bar, 'contextmenu', 
                     this.displayContext.bindAsEventListener( this, true ) );

    if ( this.view ){

    }

    if ( this.ajax == 'true' ){
      this.requestResult();
      if ( ( this.open    && this.open    == 'true' ) ||
           ( this.hasfold && this.hasfold == 'false' ) ){
        this.foldState = false;
      }
    } else {
      this.loaded    = true;
      if ( this.fold )
        this.fold.src  = '/images/fold/plus.png';
      this.hideFan();
      if ( this.open    == 'true' ) {
        this.foldShow();
      } else if ( this.open    == 'false' ) {
        this.foldHide();
      } else if ( this.hasfold == 'false' ) {
        this.foldShow();
      } else {
        this.foldHide();
      }
    }
  },

  showFan: function() {
    Fan.show();
    if ( this.fan ) this.fan.show();
  },
  hideFan: function() {
    Fan.hide();
    if ( this.fan ) this.fan.hide();
  },

  getLink: function() {
    if ( this.link && this.link.indexOf( "/" ) == 0 ){
      return this.link;
    } else if ( this.id && this.id.indexOf( "/" ) == 0 ){
      return this.id;
    } else if ( this.parent ) {
      if ( this.link )
        return this.parent.getLink() + "/" + this.link;
      else if ( this.id )
        return this.parent.getLink() + "/" + this.id;
      else 
        return this.parent.getLink();
    } else {
      var path = ( document.location.pathname == '/' ?
                       '/index' :
                       document.location.pathname );
      if ( this.link )
        return path + "/" + this.link;
      else if ( this.id )
        return path + "/" + this.id;
      else
        return path;
    }
  },

  reloadContent: function() {
    this.requestResult();
  },

  getId: function() {
    if ( this.id && this.id.indexOf( "/" ) == 0 ){
      return this.id;
    } else if ( this.parent ) {
      if ( this.id && this.id.indexOf( "?" ) == 0 )
        return this.parent.getId() + this.id;
      else if ( this.id )
        return this.parent.getId() + "/" + this.id;
      else 
        return this.parent.getId();
    } else {
      var path = ( document.location.pathname == '/' ?
                       '/index' :
                       document.location.pathname );
      if ( this.id && this.id.indexOf( "?" ) == 0 )
        return path + this.id;
      else if ( this.id )
        return path + "/" + this.id;
      else
        return path;
    }
  },

  setBar: function( msg, bold ){
    if ( msg && this.foldmsg )
      this.foldmsg.update( msg );
    if ( bold && this.bar )
      this.bar.setStyle( { fontWeight: 'bold' } );
  },

  foldClick: function() {
    if ( this.loaded ){
      this.foldState ? this.foldShow() : this.foldHide();
    }
  },
  foldShow: function() {
    this.foldState = false;
    if ( this.loaded ){
      if ( this.bar )
        this.bar.addClassName( 'FoldHigh' );
      if ( this.fold )
        this.fold.src  = '/images/fold/minus.png';
      this.content.show();
    }
  },
  foldHide: function() {
    this.foldState = true;
    if ( this.loaded ){
      if ( this.bar )
        this.bar.removeClassName( 'FoldHigh' );
      if ( this.fold )
        this.fold.src  = '/images/fold/plus.png';
      this.content.hide();
    }
  },

  anchorAction: function( value ){
    value == 1 ? this.foldShow() : this.foldHide();
  },

  displayContext: function(event,reload) {
    var items = [ { Title: '... ändern',
                    Mode:  'detail' },
                  { Title: '... drucken',
                    Mode:  'print' } ];
    if ( reload && this.loaded )
      items.unshift( { Title: '... neu laden',
                       Mode:  'reload' } );
    Context.add( this, 'Ansicht', items );
  },
  handleContext: function( config ) {
    var mode = config.Mode;
    if ( mode == 'reload' ){
      this.reloadContent();
    } else if ( mode == 'detail' ){
      document.location.href = this.getLink();
    } else if ( mode == 'print' ){
      window.open( this.getLink() + '?print=true',
                   '_blank' );
    }
  },

  resetId: function(id){
    this.id = id;
    this.reloadContent();
  },

  requestPath: function(path, query){
    this.showFan();
    this.content.addClassName( 'Loading' );
    this.content.update( 'Daten werden geladen! <img src=\'/images/loading.gif\' />' );
    this.content.show();
    if ( query ){
      this.ajaxRequest( path, query );
    } else {
      this.ajaxRequest( path + 
                        ( window.document.location.search || '' ) );
    }
  },

  requestResult: function(query) {
    this.requestPath( this.getId(), query );
  },

  ajaxRequestType: function() {
    return 'detail';
  },

  ajaxResponse: function( json, req ){
    if ( ! json ){

    } else if ( this.options.ajax &&
         this.options.ajax[json.id] ){
      var func = this.options.ajax[json.id],
          call = func.bind( this );
      call( json.response, json );
    } else {
      this.handleResult( json.response, json, req );
    }

    this.ajaxRunning = false;
  },

  handleResult: function( json, res, req ) {
    var newElem = null;
    this.loaded = true;
    this.content.removeClassName( 'Loading' );
    this.content.update();

    switch ( json.type ){
      case 'html':
        this.content.update( json.content );
        break;
      case 'table':
        newElem = new Content.Table( this, this.content, json.data, json.options );
        break;
      case 'tabs':
        newElem = new Content.Tabs( this, this.content, json.data, json.options );
        break;
      case 'form':
        newElem = new Content.Form( this, this.content, json.data, json.options );
        break;
      case 'database':
        newElem = new Content.Database( this, this.content, json.data, json.options );
        break;
      case 'chart':
        newElem = new Content.Chart( this, this.content, json.data, json.options );
        break;
      case 'split':
        newElem = new Content.Split( this, this.content, json.data, json.options );
        break;
      case 'output':
        newElem = new Content.Output( this, this.content, json.data, json.options );
        break;
      case 'cols':
        newElem = new Content.Cols( this, this.content, json.data, json.options );
        break;
      case 'layout':
        newElem = new Content.Layout( this, this.content, json.data, json.options );
        break;
      case 'drop':
        newElem = new Content.Drop( this, this.content, json.data, json.options );
        break;
      case 'selection':
        newElem = new Content.Selection( this, this.content, json.data, json.options );
        break;
      case 'result':
        newElem = new Content.Result( this, this.content, json.data, json.options );
        this.loaded = false;
        break;
      case 'object':
        try {
          newElem = eval( "new " + json.object + "(this, this.content, json.data, json.options );" );
        } catch(e) {
          Log.write( "Object-Error", e );
        }
        break;
      default:
        this.content.update( json );
        break;
    }

    this.hideFan();
    // Help.hide();

    if ( ! this.tabItem )
      this.foldState ? this.foldHide() : this.foldShow();

    if ( this.postResult )
      this.postResult();

    if ( newElem &&
         newElem.handleUpdate &&
         json.options &&
         json.options.Update )
      newElem.handleUpdate( json.options.Update );
  },

  handleUpdate: function(update){
    window.setTimeout( this._handleUpdate.bind(this,update), ( update.Timeout || 0 ) );
  },
  _handleUpdate: function(update){
    if ( update.Element ){
      var par = this.findParent( update.Element );
      if ( par &&
           par[update.Func] ){
        par[update.Func]( update.Data );
      } 
    } else {
      var par = this.findFunction( update.Func );
      if ( par ) {
        par[update.Func]( update.Data );
      }
    }
  },

  findParent: function( count ){ 
    var par   = this;
        c     = count || 0,
        found = true;
    for ( var i = 0; i < count; i++ ){
      if ( par.parent )
        par = par.parent;
      else
        found = false;
    }
    return ( found ? par : null );
  },

  findFunction: function( func ){
    var par   = this;
    while ( par ){
      if ( par[func] )
        return par;
      par = par.parent;
    }
  }

} );

Window.start( function () {
  $('Content').select('div.Content').each(
     function(elem) { new Content( null, elem, null ) } );
} );

Content.Vars = {};
Content.Vars.Nation =
  [ [ 'de', 'Deutschland' ],
    [ 'at', 'Österreich' ],
    [ 'ch', 'Schweiz' ],
    [ 'x1', '-' ],
    [ 'au', 'Australien' ],
    [ 'br', 'Brasilien' ],
    [ 'cn', 'China' ],
    [ 'es', 'Spanien' ],
    [ 'fi', 'Finnland' ],
    [ 'fr', 'Frankreich' ],
    [ 'gr', 'Griechenland' ],
    [ 'hu', 'Ungarn' ],
    [ 'it', 'Italien' ],
    [ 'ru', 'Russland' ],
    [ 'se', 'Schweden' ],
    [ 'sg', 'Singapur' ],
    [ 'sl', 'Slowenien' ],
    [ 'us', 'Vereinigte Staaten von Amerika' ],
    [ 'za', 'Südafrika' ],
    [ 'x2', '-' ],
    [ 'x3', 'others' ]
  ];
 
Content.Tabs      = Class.create();
Content.Tabs.Item = Class.create();

Object.extend( Object.extend( Content.Tabs.prototype, Content.prototype ), {
  initialize: function( parent, container, data, options ) {
    this.parent    = parent;
    this.container = container;
    this.data      = data;
    this.loaded    = false;
    this.currTab   = null;
    this.setOptions( options );

    this.create();
  },

  create: function() {
    var divTab  = new Element( 'div', { className: 'TabsBar' } ),
        divCont = new Element( 'div', { className: 'TabsContent' } ),
        def     = null,
        first   = null;
    this.container.update();
    for ( var i = 0; i < this.data.length; i++ ){
      var item = this.data[i];
          elem = new Content.Tabs.Item( this, null, item, this.options );
      if ( ! first && ! item.Hide && ! item.Text )
        first = elem;
      if ( item.StartTab && ! def )
        def = elem;
      divTab.insert( elem.tabDiv );
      divCont.insert( elem.content );
    }
    this.container.insert( divTab );
    this.container.insert( divCont );
    if ( def )
      this.activate( def );
    else if ( first )
      this.activate( first );
  },

  activate: function( item ){
    if ( this.currTab )
      this.currTab.unactivate();
    this.currTab = item;
    this.currTab.activate();
  }
});

Object.extend( Object.extend( Content.Tabs.Item.prototype, Content.prototype ), {
  initialize: function( parent, container, data, options ) {
    this.parent    = parent;
    this.container = container;
    this.data      = data;
    this.active    = false;
    this.setOptions( options );
    this.tabItem   = true;

    this.id        = data.Link;
    this.print     = null;

    this.create();
  },

  create: function() {
    var item     = this.data,
        content  = item.Content;
    this.tabDiv  = new Element( 'div', { className: 'TabBar' } ).setStyle( item.TabStyle  || {} );
    this.content = new Element( 'div', { className: 'TabContent' } ).setStyle( item.ContStyle || {} );

    this.content.hide();

    if ( content )
      this.handleResult( content );

    if ( item.Text ){
      this.tabDiv.update( item.Text );
      this.tabDiv.addClassName( 'Text' );
    } else {
      this.tabDiv.update( item.Caption );
      if ( item.Hide ){
        this.tabDiv.addClassName( 'Hide' );
      } else {
        var reload = false;
        if ( this.data.Reload )
          reload = true;
        else if ( ! content )
          reload = true;
        Event.observe( this.tabDiv, 'click',       this.tabClick.bind(this));
        Event.observe( this.tabDiv, 'mouseover',   this.tabOver.bind(this));
        Event.observe( this.tabDiv, 'mouseout',    this.tabOut.bind(this));
        if ( this.id )
          Event.observe( this.tabDiv, 'contextmenu', this.displayContext.bindAsEventListener( this, reload ) );
      }
    }
  },

  tabClick: function(){
    this.parent.activate( this );
  },
  tabOver: function( event ){
    if ( ! this.active )
      this.tabDiv.addClassName( 'Hover' );
  },
  tabOut: function( event ){
    this.tabDiv.removeClassName( 'Hover' );
  },
  activate: function( item ){
    this.tabDiv.addClassName( 'Active' );
    this.tabDiv.removeClassName( 'Hover' );
    this.content.show();
    this.showContent( item );
  },
  unactivate: function(){
    this.tabDiv.removeClassName( 'Active' );
    this.content.hide();
  },
  showContent: function( item ){
    if ( ! this.loaded ){
      // this.content.setStyle( { height: "50px" } );
      this.requestResult();
    }
  },
  postResult: function() {
    // this.content.setStyle( { height: "" } );
  },
  displayContext: function(event,reload) {
    var items = [ { Title: '... ändern',
                    Mode:  'detail' },
                  { Title: '... öffnen',
                    Mode:  'open' },
                  { Title: '... drucken',
                    Mode:  'print' } ];
    if ( reload && this.loaded )
      items.unshift( { Title: '... neu laden',
                       Mode:  'reload' } );
    Context.add( this, 'Ansicht', items );
  },
  handleContext: function( config ) {
    var mode = config.Mode;
    if ( mode == 'reload' ){
      this.reloadContent();
    } else if ( mode == 'detail' ){
      document.location.href = this.getId();
    } else if ( mode == 'open' ){
      window.open( this.getId(), '_blank' );
    } else if ( mode == 'print' ){
      window.open( this.getId() + '?print=true', 
                   '_blank' );
    }
  }
});


Content.Cols      = Class.create();
Content.Cols.Item = Class.create();


Object.extend( Object.extend( Content.Cols.prototype, Content.prototype ), {
  initialize: function( parent, container, data, options ) {
    this.parent    = parent;
    this.container = container;
    this.data      = data;
    this.setOptions( options );
    this.create();
  },

  create: function() {
    for ( var i = 0; i < this.data.length; i++ ) {
      var item = this.data[i];
          elem = new Content.Cols.Item( this, null, item, this.options );
      this.container.insert( elem.container );
    }
    this.container.insert( new Element( 'br', { className: 'Clear' } ));
  }
});

Object.extend( Object.extend( Content.Cols.Item.prototype, Content.prototype ), {
  initialize: function( parent, container, data, options ) {
    this.parent    = parent;
    this.container = container;
    this.data      = data;
    this.setOptions( options );

    this.id        = data.Link;
    this.print     = null;

    this.create();
  },

  create: function() {
    var title   = this.data.Title,
        content = this.data.Content;
 
    this.container = new Element( 'div', { className: 'Cols' } );
    this.colBar  = new Element( 'div', { className: 'ColBar' } );
    this.content = new Element( 'div', { className: 'ColDiv' } );

    this.colBar.update( title );
    this.container.setStyle( { width: this.data.Width + 'px'} );

    this.container.insert( this.colBar );
    this.container.insert( this.content );

    if ( content )
      this.handleResult( content );
    else
      this.requestResult();
  },
  reloadCol: function() {
    var content = this.data.Content;
    if ( content )
      this.handleResult( content );
    else
      this.requestResult();
  }
});

Content.Layout      = Class.create();
Content.Layout.Item = Class.create();


Object.extend( Object.extend( Content.Layout.prototype, Content.prototype ), {
  initialize: function( parent, container, data, options ) {
    this.parent    = parent;
    this.container = container;
    this.data      = data;
    this.setOptions( options );
    this.create();
  },

  create: function() {
    var table = new Element( 'table' ).setStyle( { tableLayout: 'fixed', overflow: 'auto' } ),
        tbody = new Element( 'tbody' );
        
    for ( var x = 0; x < this.data.length; x++ ) {
      var cols = this.data[x],
          tr   = new Element( 'tr' ).setStyle( { verticalAlign: 'top' } );
      for ( var y = 0; y < cols.length; y++ ) {
        var data  = this.data[x][y],
            td    = new Element( 'td' ).setStyle( { verticalAlign: 'top' } ),
            style = {},
            elem  = null;

        if ( data.Width )
          style.width = data.Width;
        if ( data.Height )
          style.height = data.Height;

        td.setStyle( style );

        if ( data.RowSpan )
          td.writeAttribute( 'rowspan', data.RowSpan );
        if ( data.ColSpan )
          td.writeAttribute( 'colspan', data.ColSpan );

        elem = new Content.Layout.Item( this, td, data, this.options );
        tr.insert( td );
      }
      tbody.insert( tr );
    }
    table.insert( tbody );
    this.container.insert(table);
  }
});

Object.extend( Object.extend( Content.Layout.Item.prototype, Content.Layout.prototype ), {
  initialize: function( parent, container, data, options ) {
    this.parent    = parent;
    this.container = container;
    this.data      = data;
    this.setOptions( options );

    this.id        = data.Link;
    this.print     = null;

    this.create();
  },

  create: function() {
    var title   = this.data.Title,
        content = this.data.Content,
        container = new Element( 'div', { className: 'Cols' } );
 
    this.colBar  = new Element( 'div', { className: 'ColBar' } );
    this.content = new Element( 'div', { className: 'ColDiv' } );

    this.colBar.update( title );

    container.setStyle( { width: this.data.Width } );
    container.insert( this.colBar );
    container.insert( this.content );
    this.container.insert( container );

    if ( content )
      this.handleResult( content );
    else
      this.requestResult();
  }
});


Content.Table        = Class.create();
Object.extend( Object.extend( Content.Table.prototype, Content.prototype ), {
  initialize: function( parent, container, data, options ){
    this.parent    = parent;
    this.container = container;
    this.data      = data;
    this.setOptions( options );

    this.childs    = {};
    this.rowMarked    = false;
    this.rowMarkStart = null;
    this.rowMarkEnd   = null;

    this.InAction     = null;
    this.ActionItems  = [];

    this.create();
  },
  create: function() {
    var form  = this.options.Form,
        data  = [],
        count = 0,
        container = null,
        i     = null;

    this.container.update();
    this.parent.setBar( this.options.BarMsg, this.options.BarBold );

    if ( ! form ) {
      container = this.container;
    } else {
      this.id      = form.Link || 'store';
      this.form    = new Element( 'form' );
      var submit   = new Element( 'input', { type: 'button', value: form.Value,
                                             className: 'Submit' } );
      this.content = new Element( 'div' );
      submit.setStyle( { marginTop:    '10px',
                         marginBottom: '10px',
                         marginLeft:   ( form.Padding || 300 ) + 'px' } );

      this.container.insert( this.form );
      this.container.insert( submit );
      this.container.insert( this.content );
      Event.observe( submit, 'click', this.submitForm.bind( this ) );
      container = this.form;
    }

    while ( i = this.data.shift() ){
      var item = new Content.Table.Item( this, container, i, this.options );
      item.setCount( count++ );
      item.insert();

      if ( item.id )
        this.childs[item.id] = item;

      data.push( item );
    }
    this.data = data;
  },
  reOrder: function( head, rowtype, col, order ){
    if ( this.sorting ) {
      return false;
    } else {
      var oldData  = {},
          sortData = [],
          putSort  = false,
          count    = 0,
          item;
      this.sorting      = true;
      this.col          = col;
      this.rowMarked    = true;
      this.rowMarkStart = null;
      this.rowMarkEnd   = null;

      this.showFan();

      while ( item = this.data.shift() ){
        item.unmark();
        if ( item.type != rowtype ){
          oldData[count] = item;
        } else {
          sortData.push( item );
        }
        count++;
      }

      sortData.sort( this.reOrderSort.bind(this) );
      if ( order == 'desc' ) 
        sortData.reverse();

      $H(oldData).each( function(pair) { 
        sortData.splice( pair.key, 0, pair.value );
      } );

      count = 0;
      sortData.each( function(e){ 
        e.setCount( count++ );
        e.insert(); 
      } );

      this.data    = sortData;
      this.hideFan();
      this.sorting = false;
      return true;
    }
  },
  reOrderSort: function( elem1, elem2 ){
    var val1 = elem1.sortValue(this.col),
        val2 = elem2.sortValue(this.col);
    if ( val1 < val2 ){
      return -1;
    } else if ( val1 == val2 ){
      var val11 = elem1.sortDefault(),
          val21 = elem2.sortDefault();
      if ( val11 < val21 ){
        return -1;
      } else if ( val11 == val21 ){
        return 0;
      } else if ( val11 > val21 ){
        return 1;
      }
    } else if ( val1 > val2 ){
      return 1;
    }
  },

  showContent: function( mode, type ){
    this.data.each( function(e){ 
      if ( e.type == type ) {
        if ( mode == 'show' ){
          e.bar.addClassName( 'ContentHigh' );
          e.content.show();
        } else {
          e.bar.removeClassName( 'ContentHigh' );
          e.bar.show();
          e.content.hide();
        }
      }
    } );
  },

  submitForm: function() {
    this.requestResult( this.form.serialize() );
  },

  removeChilds: function( childs ){
    for ( var i = 0; i < childs.length; i++ ){
      var item = this.childs[childs[i]];
      if ( item )
        item.remove();
    }
  },

  disableChilds: function( childs ){
    for ( var i = 0; i < childs.length; i++ ){
      var item = this.childs[childs[i]];
      if ( item )
        item.disable();
    }
  },

  removeItem: function( item ){
    var item = this.childs[item.id];
    if ( item )
      delete this.childs[item.id];
    this.data = this.data.without( item );
  },

  setRowMarker: function( col ){
    if ( this.rowMarkStart == null ){
      this.rowMarkStart = col;
      this.rowMarked    = false;
    } else if ( this.rowMarkEnd != null ) {
      this.unmarkRow();
      this.rowMarkStart = col;
      this.rowMarkEnd   = null;
      this.rowMarked    = false;
    } else {
      this.rowMarkEnd   = col;
      this.markRow();
      this.rowMarked    = true;
    }
  },
  markRow: function() {
    var min = Math.min( this.rowMarkStart, this.rowMarkEnd ),
        max = Math.max( this.rowMarkStart, this.rowMarkEnd );
    for ( var i = min; i <= max; i++ ){
      this.data[i].mark();
    }
  },
  unmarkRow: function() {
    this.rowMarkStart = null;
    this.rowMarkEnd   = null;
    this.rowMarked    = false;
    this.data.each( function(e){ e.unmark() } );
  },
  handleAction: function(nr){
    if ( this.InAction != null ){
      alert( 'IsInAction' );
    } else {
      this.ActionItems = [];
      this.InAction    = nr;
      for ( var i = 0, len = this.data.length; i < len; i++ ){
        var item = this.data[i];
        if ( item.marked &&
             item.actions[nr] )
          this.ActionItems.push(item);
      }
      this.handleActionTrigger();
    }
  },
  handleActionTrigger: function(){
    if ( this.ActionItems.length ){
      var item = this.ActionItems.shift();
      item.actions[this.InAction].handleAction();
    } else {
      this.InAction    = null;
    }
  }
} );

Content.Table.Item = Class.create();
Object.extend( Object.extend( Content.Table.Item.prototype, 
                              Content.prototype ), {
  initialize: function( parent, container, data, options ){

    this.parent       = parent;
    this.container    = container;
    this.data         = data;
    this.setOptions(options);

    if ( data.Link == '-' ) {
      this.id           = data.Id;
    } else { 
      this.link         = data.Link;
      this.id           = data.Id || data.Link;
    }

    this.type         = data.Type;
    this.loaded       = false;
    this.marked       = false;
    this.foldState    = true;
    this.foldAllowed  = true;
    this.mousedownOn  = false;
    this.details      = {};
    this.actions      = {};
    this.sort         = {};
    this.cols         = [];
    this.funcToggle   = false;
    this.context      = null;
    this.print        = null;

    this._foldClick   = this.foldClick.bindAsEventListener( this );
    this._multiClick  = this.multiClick.bindAsEventListener( this );
    this._mousedown   = this.mousedown.bindAsEventListener( this );

    this.create();
  },

  create: function() {
    var type     = this.data.Type,
        defi     = this.options[type],
        row      = this.data.Row,
        sel      = this.data.Select,
        drag     = this.data.Drag,
        open     = this.data.Open,
        link     = this.data.Link,
        noLink   = this.data.NoLink,
        disabled = this.data.Disabled,
        style    = this.data.Style,
        details  = this.data.Details,
        results  = this.data.Results,
        actions  = this.data.Actions,
        editable = this.data.Editable,
        sortRow  = this.data.SortRow,
        funcCol  = this.data.Func,
        loadDir  = this.data.Load,
        sortVal  = this.data.SortVal,
        content  = this.data.Content,
        sortDef  = this.options.Sort,
        foldDiv  = new Element( 'div', { className: 'Item' } ).setStyle( { width: '16px' } );

    this.bar          = new Element( 'div', { className: 'BarContent' } ).setStyle( style );
    this.fold         = new Element( 'img', { src: '/images/smfold/plus.png' } );
    this.content      = new Element( 'div', { className: 'ListContent' } ).hide();
    this.content.hide();

    if ( drag ) {
      new Draggable( this.bar, { ghosting:   true, 
                                 revert:     true, 
                                 constraint: 'vertical',
                                 quiet:      true, 
                                 scroll:     $('Middle'),
                                 scrollSensitivity: 20,
                                 scrollSpeed: 25 } );
      this.bar.writeAttribute( { drag: drag } );
    }

    if ( sel ) {
      this.mousedownOn  = true;
      Event.observe( this.bar, 'mousedown', this._mousedown );
      Event.observe( this.bar, 'dblclick', this.dblclick.bindAsEventListener( this ) );
    }

    if ( open ){
      this.bar.addClassName( 'Open' );
      Event.observe( this.bar, 'click', this.openClick.bind( this ) );
    } 

    if ( ( link && link == '-' ) ||
         ( noLink ) ) {
      foldDiv.update( '&nbsp;' );
      foldDiv.addClassName( 'SmallFold' );
      this.bar.insert( foldDiv );
    } else if ( link ){
      foldDiv.insert( this.fold );
      this.bar.insert( foldDiv );
      this.bar.addClassName( 'Link' );
      foldDiv.addClassName( 'SmallFold' );
      this.mousedownOn  = true;
      Event.observe( this.bar, 'click',     this._foldClick );
      Event.observe( this.bar, 'mousedown', this._mousedown );
      Event.observe( this.bar, 'contextmenu', 
                     this.displayContext.bindAsEventListener( this, content ? false : true ) );

      if ( loadDir )
        this.foldClick();
    } else if ( this.options.MultiAction ){
      this.mousedownOn  = true;
      Event.observe( this.bar, 'click',     this._multiClick );
      Event.observe( this.bar, 'mousedown', this._mousedown );
    }

    for( var j = 0; j < defi.length; j++ ){
      var def   = defi[j] || {},
          col   = new Element( 'div', { className: 'Item', colNr: j } ),
          styl  = {},
          func  = def.Func,
          value = '&nbsp;';

      if ( row && row[j] != null && row[j] !== '' )
        value = new String( row[j] );
      else if ( def.Value )
        value = new String( def.Value );

      if ( def.Width ) 
        styl.width      = ( def.Width - 5 ) + 'px';
      if ( def.Center )
        styl.textAlign  = 'center';
      if ( def.Right )
        styl.textAlign  = 'right';
      if ( def.Bold ) 
        styl.fontWeight = 'bold';
      if ( def.Bright )
        styl.color      = '#888888';
      if ( def.Small )
        styl.fontSize   = '10px';

      if ( def.Padding && def.Right ){
        styl.width      = ( def.Width - 5 - def.Padding ) + 'px';
        styl.paddingRight = ( def.Padding + 2 ) + 'px';
      } else if ( def.Padding ){
        styl.width      = ( def.Width - 5 - def.Padding ) + 'px';
        styl.paddingLeft = ( def.Padding + 2 ) + 'px';
      }

      if ( def.TblData ){
        styl.border     = '1px solid #aaaaaa';
        styl.fontSize   = '80%';
      }

      col.setStyle( styl );
      col.update( value );

      this.cols.push( col );
      this.bar.insert( col );
    }

    if ( sortRow ){
      for( var j = 0; j < defi.length; j++ ){
        var def   = defi[j] || {},
            col  = this.cols[j];
        if ( def.HideBorder )
          col.addClassName( 'HideBorder' );
        else
          col.addClassName( 'Border' );
        if ( sortRow.include(j) ){
          var def  = defi[j] || {},
              img  = new Element( 'img', { src: '/images/smfold/sort.png' } );
          col.addClassName( 'Sort' );
          col.insert( img );
          col.writeAttribute( { sort: j, order: sortDef.Default == j ? 'desc' : 'asc' } );
          Event.observe( col, 'click', this.sortClick.bindAsEventListener( this ) );
        }
      }
    } else if ( sortDef && sortDef.Type == type ) {
      for( var j = 0; j < defi.length; j++ ){
        var def = defi[j] || {},
            col = this.cols[j];
        if ( sortDef[j] ){
          var type  = sortDef[j][0],
              sort  = sortDef[j][1],
              bord  = sortDef[j][2],
              value = '&nbsp;';

          if ( row && row[j] != null && row[j] !== '' )
            value = new String( row[j] );
          else if ( def.Value )
            value = new String( def.Value );

          if ( bord ) {
            this.cols[bord].addClassName( 'Border' );
            this.cols[j].addClassName( 'HideBorder' );
          } else {
            if ( def.HideBorder )
              col.addClassName( 'HideBorder' );
            else
              col.addClassName( 'Border' );
          }
          if ( sortVal && sortVal[j] != null ){
            this.sort[sort] = sortVal[j];
          } else if ( type == 'A' ){
            this.sort[sort] = value + "";
          } else {
            var num = value.replace( /[\D\.-]/, "" );
            this.sort[sort] = num * 1;
          }
        } else {
          if ( def.HideBorder )
            col.addClassName( 'HideBorder' );
          else
            col.addClassName( 'Border' );
        }
      }
    } else {
      for( var j = 0; j < defi.length; j++ ){
        var def = defi[j] || {},
            col = this.cols[j];
        if ( def.HideBorder )
          col.addClassName( 'HideBorder' );
        else
          col.addClassName( 'Border' );
      }
    }

    if ( content )
      this.handleResult( content );

    if ( disabled )
      this.disable();

    for ( var i in details ){
      var conf = details[i],
          col  = this.cols[i];
      conf.DetailNr = i;
      this.details[i] = new Content.Table.Item.Detail( this, col, conf, this.options );
    }

    for ( var i in actions ){
      var conf = actions[i],
          col  = this.cols[i];
      conf.ActionNr = i;
      this.actions[i] = new Content.Table.Item.Action( this, col, conf, this.options );
    }

    for ( var i in editable ){
      var conf  = editable[i],
          col   = this.cols[i];
          def   = defi[i],
          width = ( def.Width || 80 ) - 10;
      conf.EditableNr = i;
      conf.Width      = width;
      this.actions[i] = new Content.Table.Item.Editable( this, col, conf, this.options );
    }

    if ( funcCol &&
         this[funcCol.Function] ){
      var col   = new Element( 'div', { className: 'Float Func' } );
      this.funcImage  = new Element( 'img', { src: '/images/smfold/' + funcCol.Image + '-off.png' } );
      col.insert( this.funcImage );
      this.bar.insert( col );
      Event.observe( col, 'click', this[funcCol.Function].bind( this ) );
    }

    this.bar.insert( new Element( 'br', { className: 'Clear' } ) );
  },

  insert: function() {
    this.container.insert( this.bar );
    this.container.insert( this.content );
  },

  setCount: function( count ){
    this.count = count;
  },

  displayContext: function(event,reload) {
    var items = [ { Title: '... ändern',
                    Mode:  'disView' },
                  { Title: '... öffnen',
                    Mode:  'disOpen' },
                  { Title: '... drucken',
                    Mode:  'disPrint' } ];
    if ( reload && this.loaded )
      items.unshift( { Title: '... neu laden',
                       Mode:  'disReload' } );
    Context.add( this, 'Ansicht', items );
  },

  handleContext: function( config ) {
    var mode = config.Mode;
    if ( mode == 'disReload' ){
      this.reloadContent();
    } else if ( mode == 'disView' ){
      document.location.href = this.getLink();
    } else if ( mode == 'disOpen' ){
      window.open( this.getLink(), '_blank' );
    } else if ( mode == 'disPrint' ){
      window.open( this.getLink() + '?print=true',
                   '_blank' );
    }
  },

  sortClick: function( event ){
    var elem  = Event.findElement( event, 'DIV' ),
        col   = elem.readAttribute( 'sort' ),
        order = elem.readAttribute( 'order' ),
        type  = this.options.Sort.Type;
    if ( this.parent.reOrder( this, type, col, order ) )
      elem.writeAttribute( 'order', order == 'asc' ? 'desc' : 'asc' );
  },
  sortValue: function( col ){
    return this.sort[col];
  },
  sortDefault: function(){
    return this.sort[this.options.Sort.Default];
  },

  showContent: function(){
    var image = this.data.Func.Image,
        type  = this.data.Func.Type;
    if ( this.funcValue ){
      this.funcImage.src = '/images/smfold/' + image + '-off.png';
      this.parent.showContent( 'hide', type );
      this.funcValue = false;
    } else {
      this.funcImage.src = '/images/smfold/' + image + '-on.png';
      this.parent.showContent( 'show', type );
      this.funcValue = true;
    }
  },

  updateData: function( data ){
    var sortDef  = this.options.Sort;
    for ( var i = 0; i < data.length; i++ ){
      if ( data[i] != undefined &&
           ! this.actions[i]    &&
           ! this.details[i] ){
        this.cols[i].update( data[i] );
        if ( sortDef[i] ){
          var value = data[i],
              type  = sortDef[i][0],
              sort  = sortDef[i][1];
          if ( type == 'A' ){
            this.sort[sort] = value + "";
          } else {
            var num = value.replace( /[\D\.-]/, "" );
            this.sort[sort] = num * 1;
          }
        }
      }
    }
  },

  openClick: function() {
    window.location.href = this.data.Open;
  },
  foldClick: function( event ) {
    if ( ! this.foldAllowed ){

    } else if ( this.options.MultiAction &&
         event && event.shiftKey ){
      this.parent.setRowMarker( this.count );
    } else if ( ! this.loaded ){
      this.foldShow(true);
      this.requestResult();
    } else {
      this.foldState ? this.foldShow() : this.foldHide();
    }
  },
  foldShow: function(mode) {
    this.foldState = false;
    if ( this.loaded || mode ){
      this.bar.addClassName( 'LinkHigh' );
      if ( this.fold )
        this.fold.src  = '/images/smfold/minus.png';
      this.content.show();
    }
  },
  foldHide: function() {
    this.foldState = true;
    if ( this.loaded ){
      this.bar.removeClassName( 'LinkHigh' );
      if ( this.fold )
        this.fold.src  = '/images/smfold/plus.png';
      this.content.hide();
    }
  },
  foldContext: function(event) {
    Event.stop(event);
  },
  allowFolding: function() {
    if ( this.mousedownOn )
      Event.observe( this.bar, 'mousedown', this._mousedown );
    this.foldAllowed = true;
  },
  stopFolding: function() {
    if ( this.mousedownOn )
      Event.stopObserving( this.bar, 'mousedown', this._mousedown );
    this.foldAllowed = false;
  },

  multiClick: function( event ) {
    if ( this.options.MultiAction &&
         event && event.shiftKey ){
      this.parent.setRowMarker( this.count );
    } 
  },

  mousedown: function(event){
    Event.stop( event );
  },
  dblclick: function(event) {
    var par = this.findFunction( 'setSelection' );
    if ( par )
      par.setSelection( this.data.Select );
    Event.stop( event );
  },

  remove: function() {
    this.bar.remove();
    this.content.remove();
    this.parent.removeItem( this );
  },
  disable: function() {
    this.bar.addClassName('Disable');
    this.content.addClassName('Disable');
  },
  enable: function() {
    this.bar.removeClassName('Disable');
    this.content.removeClassName('Disable');
  },
  mark: function() {
    this.marked = true;
    this.bar.addClassName('Marked');
  },
  unmark: function() {
    this.marked = false;
    this.bar.removeClassName('Marked');
  },
  focus: function() {
    this.bar.addClassName('Focus');
  },
  blur: function() {
    this.bar.removeClassName('Focus');
  }
} );

Content.Table.Item.Detail = Class.create();
Object.extend( Object.extend( Content.Table.Item.Detail.prototype, Content.Table.Item.prototype ), {
  initialize: function( parent, container, data, options ){
    this.parent       = parent;
    this.container    = container;
    this.data         = data;
    this.setOptions(options);

    this.cols         = [];

    if ( this.data.Type == 'detail' ){
      this.imgOn  = new Element( 'img', { src: '/images/smfold/details-on.png' } );
      this.imgOff = new Element( 'img', { src: '/images/smfold/details-off.png' } );
      this.help   = "Für Details zu \'%s\' bitte <img src=\'/images/smfold/details-on.png\' /> anklicken!".sprintf( this.data.Help );
    } else if ( this.data.Type == 'result' ){
      this.imgOn  = new Element( 'img', { src: '/images/smfold/results-on.png' } );
      this.imgOff = new Element( 'img', { src: '/images/smfold/results-off.png' } );
      this.help   = "Zur Ergebnis-Ansicht von \'%s\' bitte <img src=\'/images/smfold/results-on.png\' /> anklicken!".sprintf( this.data.Help );
    } else if ( this.data.Type == 'admin' ){
      this.imgOn  = new Element( 'img', { src: '/images/smfold/admin-on.png' } );
      this.imgOff = new Element( 'img', { src: '/images/smfold/admin-off.png' } );
      this.help   = "Zur Administration von \'%s\' bitte <img src=\'/images/smfold/admin-on.png\' /> anklicken!".sprintf( this.data.Help );
    } else {
      Log.write( "Details-Type '%s' is unknown".sprintf( this.data.Type ));
    }
    this.container.addClassName( 'SmallDetail' );
    this.container.update( this.imgOff );

    for ( var j = 0; j < this.data.Cols.length; j++ ){
      var nr  = this.data.Cols[j],
          col = this.parent.cols[nr];
      this.cols.push( col );
      Event.observe( col, 'click',       this.click.bindAsEventListener( this ) );
      Event.observe( col, 'mouseover',   this.mouseover.bindAsEventListener( this ) );
      Event.observe( col, 'mouseout',    this.mouseout.bindAsEventListener( this ) );
      Event.observe( col, 'contextmenu', this.contextmenu.bindAsEventListener( this ) );
    }
  },
  click: function(event) {
    Event.stop( event );
    document.location.href = this.data.Link;
  },
  mouseover: function( event ){
    this.container.update( this.imgOn );
    this.cols.each( function(col) { 
      col.addClassName( 'SmallDetailHover' );
    } );
    Help.show( this.help );
  },
  mouseout: function( event ){
    this.container.update( this.imgOff );
    this.cols.each( function(col) { 
      col.removeClassName( 'SmallDetailHover' );
    } );
    Help.hide();
  },
  contextmenu: function(event) {
    Context.add( this, 'Detail',
                 [ { Title: '... anzeigen',
                     Mode:  'detShow' },
                   { Title: '... öffnen',
                     Mode:  'detOpen' } ] );
  },
  handleContext: function( config ) {
    var mode = config.Mode;
    if ( mode == 'detOpen' ){
      window.open( this.data.Link, '_blank' );
    } else if ( mode == 'detShow' ){
      document.location.href = this.data.Link;
    }
  }
});

Content.Table.Item.Action = Class.create();
Object.extend( Object.extend( Content.Table.Item.Action.prototype, Content.Table.Item.prototype ), {
  initialize: function( parent, container, data, options ){
    this.parent       = parent;
    this.container    = container;
    this.data         = data;
    this.setOptions(options);

    this.id           = data.Link;

    if ( ! this.container ){
      // Log.write( this.getId() );
    } else {
      this.container.addClassName( 'Action' );
      this.container.update( this.data.Value );
      Event.observe( this.container, 'click', this.click.bindAsEventListener( this ) );
    }

    if ( this.data.Focused )
      this.focus();
    if ( this.data.Focus )
      this.focusId = this.data.Focus;
  },
  click: function(event) {
    if ( event )
      Event.stop(event);

    if ( this.options.MultiAction &&
         this.parent.marked ){
      if ( confirm( 'Wollen Sie diese Action für alle markierten Zeilen durchführen?' ) )
        this.parent.parent.handleAction(this.data.ActionNr);
    } else {
      if ( this.data.Confirm )
        if ( ! confirm( this.data.Confirm ) )
          return;

      this.handleAction();
    }
  },
  handleAction: function() {
    if ( this[this.data.Action] ){
      this[this.data.Action]();
    } else if ( this.data.Link ){
      var link = this.getId() + ( this.data.Param ? "=" + this.data.Param : '' );
      this.ajaxRequest( link );
    }
  },
  handleParam: function( json ){
    Object.extend( this.data, json );
    this.container.update( this.data.Value );
    if ( json.Content ){
      this.parent.handleResult(json.Content);
      this.parent.foldShow();
    }
    if ( json.Remove )
      this.parent.remove();
    if ( json.Disable )
      this.parent.disable();
    if ( json.Enable )
      this.parent.enable();
    if ( json.Update )
      this.handleUpdate( json.Update );
    this.parent.parent.handleActionTrigger();
  },

  clickAll: function() {
    var col   = this.data.Col,
        param = this.data.Param,
        item  = this.parent,
        data  = this.parent.parent.data;

    for ( var i = 0; i < data.length; i++ ){
      if ( data[i] != item &&
           data[i].actions[col] &&
           data[i].actions[col].data.Param == param ){
        data[i].actions[col].click();
      }
    }
  },

  focusRow: function() {
    if ( this.focused ){
      this.ajaxRequest( this.getId() + "=" + 0 );
      this.blur();
    } else {
      this.ajaxRequest( this.getId() + "=" + 1 );
    };
  },
  handleFocus: function(json){
    if ( Content.Focus )
      Content.Focus.blur();
    if ( json.Result == 'focus' )
      this.focus();
    else if ( json.Result == 'blur' )
      this.blur();
  },
  focus: function() {
    this.focused = true;
    this.parent.bar.addClassName('Focus');
    Content.Focus = this;
  },
  blur: function() {
    this.focused = false;
    this.parent.bar.removeClassName('Focus');
    Content.Focus = null;
  },
  getFocus: function() {
    return this.focusId;
  },

  getOptions: function() {
    return { ajax: { handleParam:  this.handleParam.bind( this ),
                     handleFocus:  this.handleFocus.bind( this ) } };
  }
});

Content.Table.Item.Editable = Class.create();
Object.extend( Object.extend( Content.Table.Item.Editable.prototype, Content.Table.Item.prototype ), {
  initialize: function( parent, container, data, options ){
    this.parent       = parent;
    this.container    = container;
    this.data         = data;
    this.setOptions(options);

    this.value        = this.container.innerHTML;
    this.isInput      = false;
    this.input        = new Element( 'input', { className: 'Input' } );
    this.input.setStyle( { width: this.data.Width + 'px' } );
    this.input.value  = this.value;
    this.id           = this.data.Link;

    this._stopEvent   = this.stopEvent.bindAsEventListener( this );

    Event.observe( this.container, 'mousedown', this._stopEvent );
    Event.observe( this.container, 'click',     this._stopEvent );
    Event.observe( this.container, 'dblclick',  this.dblclick.bindAsEventListener( this ) );
    Event.observe( this.input,     'keypress',  this.keypress.bindAsEventListener( this ) );
  },
  dblclick: function(event) {
    Event.stop( event );
    if ( this.isInput )
      this.hideInput();
    else
      this.showInput();
  },
  keypress: function(event) {
    if ( event.keyCode == Event.KEY_RETURN ) {
      this.value = this.input.getValue();
      this.submitValue();
    } else if ( event.keyCode == Event.KEY_ESC ) {
      this.hideInput();
    }
  },
  stopEvent: function(event){
    Event.stop( event );
  },

  submitValue: function() {
    this.showFan();
    this.ajaxRequest( this.getId() + '=' + this.value );
  },
  handleEditable: function( json ){
    this.hideFan();
    this.value = json.Result;
    this.hideInput();
  },

  showInput: function() {
    this.isInput = true;
    this.container.update( this.input );
    this.input.focus();
    this.parent.stopFolding();
    Event.stopObserving( this.container, 'click',     this._stopEvent );
    Event.stopObserving( this.container, 'mousedown', this._stopEvent );
  },
  hideInput: function() {
    this.isInput = false;
    this.container.update( this.value );
    this.parent.allowFolding();
    Event.observe( this.container, 'click',     this._stopEvent );
    Event.observe( this.container, 'mousedown', this._stopEvent );
  },

  getOptions: function() {
    return { ajax: { handleEditable:  this.handleEditable.bind( this ) } };
  }
});


Content.Chart    = Class.create();

Object.extend( Object.extend( Content.Chart.prototype, Content.prototype ), {
  initialize: function( parent, container, data, options ){
    this.parent       = parent;
    this.container    = container;
    this.data         = data;
    this.lastType     = [];
    this.setOptions(options);

    this.oldHigh = null;

    this.create();
  },

  create: function() {
    var canElem = new Element( 'canvas', 
                      { name:      'canvas',
                        className: 'Chart',
                        width:     this.options.Width  + 50,
                        height:    this.options.Height + 20 } ),
        div     = new Element( 'div', 
                      { className: 'Chart' } ).setStyle( 
                      { width:   ( ( this.container.getWidth() || 830 ) - this.options.Width - 100 ) + "px",
                        height:  ( this.options.Height + 20 ) + "px" } ),
        that    = this;
    this.container.setStyle( { height: ( this.options.Height + 50 ) + "px" } );
    this.container.insert( canElem );
    this.container.insert( div );
    this.container.insert( new Element( 'br', { className: 'Clear' } ));

    if ( Prototype.Browser.IE )
      G_vmlCanvasManager.initElement(canElem);
    else
      Event.observe( canElem, 'click', this.clickCanvas.bindAsEventListener(this) );

    this.canvas  = canElem;
    this.descDiv = div;
    this.draw();
    this.data.Points.each( function(e, index){ 
      var div = new Element( 'div', { index: index } ).update( e[2] );
      if ( e[3] )
        div.setStyle( { backgroundColor: '#7297b2' } );
      e[4] = div;
      that.descDiv.insert( div );
      if ( ! Prototype.Browser.IE ){
        Event.observe( div, 'mouseover', that._highlight.bind(that) );
        Event.observe( div, 'mouseout',  that._deHighlight.bind(that) );
      }
    } );
  },

  draw: function() {
    var ctx = this.canvas.getContext('2d');
    ctx.clearRect(0,0,this.options.Width,this.options.Height);
    this.drawLabel();
    this.drawChart();
  },
  drawChart: function() {
    var last      = this.data.Points[0],
        canvas    = this.canvas.getContext('2d'),
        that      = this,
        height    = this.options.Height,
        lastType  = [];
    canvas.lineWidth    = 2;
    canvas.lineCap      = "round"; 
    canvas.fillStyle    = "#f0f0f0"; 

    this.data.Points.each( function(e){ 
      var type = e[3];
      canvas.strokeStyle  = "#7297b2"; 
      canvas.beginPath();
      canvas.moveTo(last[0],last[1] );
      canvas.lineTo(e[0],e[1]) 
      canvas.stroke();  
      last = e;
    });

    this.data.Points.each( function(e){ 
      var type = e[3];
      if ( type != 0 ){
        if ( ! lastType[type] ){
          lastType[type] = e;
        } else {
          canvas.beginPath();
          canvas.strokeStyle  = '#ff0000';
          canvas.moveTo(lastType[type][0],lastType[type][1] );
          canvas.lineTo(e[0],e[1]) 
          canvas.stroke();  
          lastType[type] = e;
        }
      }
    } );

    this.data.Points.each( function(e){ 
      that.drawPoint( e, '#f0f0f0', ( e[3] == 1 ? 'red' : '#7297b2' ) );
    } );
  },

  drawLabel: function() {
    var canvas  = this.canvas.getContext('2d'),
        height  = this.options.Height,
        width   = this.options.Width,
        yswitch = this.data.YLabel.length / 2,
        that    = this;
    this.data.XLabel.each( function(e){ 
      canvas.beginPath();
      canvas.lineWidth    = 1;
      canvas.fillStyle    = "#000000";
      canvas.strokeStyle  = "#aaaaaa"; 
      canvas.moveTo(e[0],0) 
      canvas.lineTo(e[0],height) 
      canvas.stroke();  
    } );
    this.data.YLabel.each( function(e){ 
      canvas.beginPath();
      canvas.lineWidth    = 1;
      canvas.fillStyle    = "#000000";
      canvas.strokeStyle  = "#aaaaaa"; 
      canvas.moveTo(0,e[0]) 
      canvas.lineTo(width,e[0]) 
      canvas.stroke();
    } );
    this.data.XLabel.each( function(e){ 
      that.drawText( [ e[0] + 1, height + 2 ], e[1] );
    } );
    this.data.YLabel.each( function(e){ 
      that.drawText( [ width + 2, e[0] - 10 ], e[1] );
    } );
  },

  _highlight: function( event ) {
    var elem   = Event.findElement( event, 'DIV' ),
        index  = elem.readAttribute( 'index' );
    this.highlight( index );
  },

  highlight: function( index ) {
    var data   = this.data.Points[index],
        type   = data[3];
    if ( this.oldHigh != index )
      this.deHighlight( this.oldHigh );
    data[4].setStyle( { color: 'red' } );
    this.drawPoint( data, 'red', ( type == 1 ? 'red' : '#7297b2' ) );
    this.oldHigh = index;
  },

  _deHighlight: function( event ){
    var elem   = Event.findElement( event, 'DIV' ),
        index  = elem.readAttribute( 'index' );
    this.deHighlight( index );
  },
  deHighlight: function( index ){
    var data   = this.data.Points[index];
    if ( data ){
      data[4].setStyle( { color: '' } );
      this.draw();
      this.oldHigh = null;
    }
  },
 
  drawPoint: function( point, fill, stroke ) {
    var canvas = this.canvas.getContext('2d');
    canvas.lineWidth    = 2;
    canvas.lineCap      = "round"; 
    canvas.fillStyle    = fill; 
    canvas.strokeStyle  = stroke; 
    canvas.moveTo(point[0],point[1]) 
    canvas.beginPath();
    canvas.arc(point[0],point[1],4,0,Math.PI*2,false);
    canvas.fill();  
    canvas.beginPath();
    canvas.arc(point[0],point[1],4,0,Math.PI*2,false);
    canvas.stroke();  
  },
  drawText: function( point, text ){
    var canvas = this.canvas.getContext('2d');
    if ( text ) {
      if ( canvas.mozDrawText ){
        canvas.mozTextStyle = '10px Arial';
        canvas.save();
        canvas.translate(point[0], point[1] + 8 );
        canvas.mozDrawText(text);
        canvas.restore();
      } else {
        var img = document.createElement('img');
        img.onload = function() {
          canvas.drawImage( img, point[0], point[1] );
        };
        img.src = '/DynImage/ChartText?text=' + text;
      }
    }
  },

  clickCanvas: function(event) {
    var canvas = this.canvas.getContext('2d');
        scroll = $('Middle').cumulativeScrollOffset(),
        offset = this.canvas.cumulativeOffset(),
        mousex = Event.pointerX( event ) - offset[0] + scroll[0] - 5,
        mousey = Event.pointerY( event ) - offset[1] + scroll[1] - 5,
        x1     = mousex - 4,
        x2     = mousex + 4,
        y1     = mousey - 4,
        y2     = mousey + 4,
        that   = this,
        elem   = null;

    this.data.Points.each( function(e, index){
      if ( e[0] >= x1 && e[0] <= x2 &&
           e[1] >= y1 && e[1] <= y2 ){
        elem = index;
        if ( index != this.oldHigh )
          that.highlight(index);
      }
    } );
    if ( elem == null )
      this.deHighlight(this.oldHigh);
  },

  //
  // Internet Explorer VML
  //
  createIE: function() {
    this.container.update( "Chart-Error!!!<br /> (Supported Browser: Firefox &ge; 3.0; Chrome; Opera; Safari)");
  }
} );


Content.Split = Class.create();

Object.extend( Object.extend( Content.Split.prototype, Content.prototype ), {
  initialize: function( parent, container, data, options ){
    this.parent    = parent;
    this.container = container;
    this.data      = data;
    this.setOptions( options );
    this.container.addClassName( 'SplitContent' );
    if ( this.options.Single )
      this.createSingle();
    else if ( this.options.Relay )
      this.createRelay();
  },
  createSingle: function() {
    var container = this.container,
        count     = 0;
    $A(this.data).each( function(item){
      var split = new Element( 'div', { className: 'Split' } );
      split.insert( new Element( 'span', { className: 'Len' } ).update( item[0] ));
      split.insert( new Element( 'span', { className: 'Time' } ).update( item[1] ));
      split.insert( new Element( 'span', { className: 'Diff' } ).update( item[2] ? "(" + item[2] + ")" : '' ));
      if ( item[3] )
        split.addClassName( 'Official' );
      container.insert(split);
      count++;
    } );
    container.insert(new Element( 'br', { className: 'Clear' } ));
  },
  createRelay: function() {
    var container = this.container,
        count     = 0,
        oldName   = '';
    $A(this.data).each( function(item){
      var split = new Element( 'div', { className: 'Split' } );
      if ( count++ != 0 &&
           oldName != item[0] )
        container.insert(new Element( 'br', { className: 'Clear' } ));
      if ( oldName != item[0] ){
        var span = new Element( 'span', { className: 'Name' } ).update( item[0] );
        split.insert( span );
      }
      split.insert( new Element( 'span', { className: 'Len' } ).update( item[2] ));
      split.insert( new Element( 'span', { className: 'Time' } ).update( item[3] ));
      split.insert( new Element( 'span', { className: 'Diff' } ).update( item[4] ? "(" + item[4] + ")" : '' ));
      if ( item[5] )
        split.addClassName( 'Official' );
      container.insert(split);
      oldName = item[0];
    } );
    container.insert(new Element( 'br', { className: 'Clear' } ));
  }
} );


Content.Result = Class.create();

Object.extend( Object.extend( Content.Result.prototype, Content.prototype ), {
  initialize: function( parent, container, data, options ){
    var child;
    this.parent      = parent;
    this.scrollContent = $('Middle');
    this.container   = $('Result');
    this.data        = data;
    this.setOptions( options );

    child         = this.container.childElements(),
    this.bar      = child[0];
    this.content  = child[1];
    this.content.update();
    this.content.update(this.data);  
    // Log.write( this.container.cumulativeScrollOffset() );
    // Log.write( this.container.cumulativeOffset() );
    // Log.write( this.container.positionedOffset() );
    this.scrollContent.scrollTop = this.container.cumulativeOffset()[1] - 170;
  }
} );


Content.Form      = Class.create();
Object.extend( Object.extend( Content.Form.prototype, Content.prototype ), {
  initialize: function( parent, container, data, options ){
    this.parent      = parent;
    this.container   = container;
    this.data        = data;
    this.setOptions( options );

    this.elems       = [];
    this.submits     = [];
    this.elemName    = {};
    this.controls    = { text:     [ 'Text',     false, false ],
                         head:     [ 'Head',     false, false ],
                         subhead:  [ 'SubHead',  false, false ],
                         spacer:   [ 'Spacer',   false, false ],
                         link:     [ 'Link',     false, false ],
                         input:    [ 'Input',    true,  true  ],
                         textarea: [ 'Textarea', true,  true  ],
                         password: [ 'Password', true,  true  ],
                         select:   [ 'Select',   true,  true  ],
                         button:   [ 'Button',   true,  false ],
                         submit:   [ 'Submit',   true,  false ],
                         radio:    [ 'Radio',    true,  true  ],
                         sex:      [ 'Sex',      true,  true  ],
                         nation:   [ 'Nation',   true,  true  ],
                         yesno:    [ 'YesNo',    true,  true  ],
                         hidden:   [ 'Hidden',   true,  true  ]
                       };

    this.create();
  },

  create: function() {
    var table  = new Element( 'table', { className: this.options.TableClass || 'Form' } ),
        tbody  = new Element( 'tbody' ),
        inputs = false;

    this.container.update();

    table.insert( tbody );

    for ( var i = 0; i < this.data.length; i++ ){
      var data  = this.data[i],
          type  = data.Type || 'text';

      if ( ! this.controls[type] ){
        Log.write( "Form-type '%s' is unknown".sprintf( type ) );
      } else {
        var form    = this.controls[type][0],
            isForm  = this.controls[type][1],
            elem    = new Content.Form[form]( this, tbody, data, this.options );
        data.elem = elem;
        this.elems.push( elem );
        if ( elem.Name )
          this.elemName[elem.Name] = elem;

        if ( type == 'submit' )
          this.submits.push( elem );

        if ( isForm )
          inputs = true;
      }
    }

    if ( inputs ){
      this.content = new Element( 'div', { className: 'FormMessage' } );
      this.form    = new Element( 'form' );
      this.form.insert( table );
      this.container.insert( this.form );
      this.container.insert( this.content );
    } else {
      this.container.insert( table );
    }
  },

  submitForm: function(elem) {
    var path = this.getId() + '/';
    if ( this.options.Link )
      path += this.options.Link + "=";
    else
      path += "store=";
    path += this.options.Ident || '';

    this.content.removeClassName( 'FormMessage' );
    this.content.addClassName( 'Loading' );
    this.content.update( 'Daten werden übertragen! <img src=\'/images/loading.gif\' />' );
    this.submits.each( function( e ){ e.disable() } );
    this.ajaxRequest( path, this.getQuery() );
  },

  getQuery: function() {
    var query = {};
    for ( var i = 0; i < this.data.length; i++ ){
      var data  = this.data[i];
          type  = data.Type || 'text',
          elem  = data.elem;

      if ( this.controls[type] ){
        var form    = this.controls[type][0],
            isInput = this.controls[type][2];
        if ( isInput ){
          if ( query[elem.Name] == null ){
            query[elem.Name] = elem.getValue();
          } else if ( typeof( query[elem.Name] ) == 'object' ){
            query[elem.Name].push( elem.getValue() );
          } else {
            query[elem.Name] = [ query[elem.Name], elem.getValue() ];
          }
        }
      }
    }
    return query;
  },

  handleSubmit: function(json) {
    this.content.addClassName( 'FormMessage' );
    this.content.removeClassName( 'Loading' );
    this.content.update( json.Result );
    if ( json.HideResult )
      window.setTimeout( this.clearMessage.bind( this ), 2000 );
    if ( json.Enable )
      this.submits.each( function( e ){ e.enable() } );
    if ( json.Disable &&
         this.elemName[json.Disable] )
      this.elemName[json.Disable].disable();
    if ( json.Update )
      this.handleUpdate( json.Update );
  },
  clearMessage: function() {
    this.content.update();
  },
  getOptions: function() {
    return { ajax: { handleSubmit: this.handleSubmit } };
  }
} );

Content.Form.Base = Class.create();
Object.extend( Object.extend( Content.Form.Base.prototype, 
                              Content.prototype ), {
  initialize: function( parent, table, data, options ){
    this.parent = parent;
    this.table  = table;
    this.data   = data;
    this.setOptions( options );

    this.Label = data.Label;
    this.Value = data.Value;
    this.Name  = data.Name;
    this.Ident = data.Ident;
 
    this.tr    = new Element( 'tr' );
    this.th    = new Element( 'th' ).update( this.Label + ( this.options.HideColon ? '' : ":" ) );
    this.td    = new Element( 'td' );
    this.create();
    this.table.insert( this.tr );
  },
  check: function() {
    return true;
  },
  submitForm: function() {
    this.parent.submitForm(this);
  }
} );

Content.Form.Text = Class.create();
Object.extend( Object.extend( Content.Form.Text.prototype, 
                              Content.Form.Base.prototype ), {
  create: function() {
    this.td.update( this.Value );
    this.tr.insert( this.th );
    this.tr.insert( this.td );
    if ( this.data.Detail ){
      this.td2 = new Element( 'td' );
      this.td2.update( this.data.Detail );
      this.tr.insert( this.td2 );
    }
  }
});

Content.Form.Head = Class.create();
Object.extend( Object.extend( Content.Form.Head.prototype, 
                              Content.Form.Base.prototype ), {
  create: function() {
    this.th.addClassName( 'Head' );
    this.th.writeAttribute( { colspan: 3 } )
    this.th.update( this.Label );
    this.tr.insert( this.th );
  }
});

Content.Form.SubHead = Class.create();
Object.extend( Object.extend( Content.Form.SubHead.prototype, 
                              Content.Form.Base.prototype ), {
  create: function() {
    this.th.addClassName( 'SubHead' );
    this.th.writeAttribute( { colspan: 3 } )
    this.th.update( this.Label );
    this.tr.insert( this.th );
  }
});


Content.Form.Spacer = Class.create();
Object.extend( Object.extend( Content.Form.Spacer.prototype, 
                              Content.Form.Base.prototype ), {
  create: function() {
    this.th.addClassName( 'Head' );
    this.th.writeAttribute( { colspan: 3 } )
    this.th.update();
    this.th.setStyle( { height: ( this.Height ? this.Height + 'px' : '10px' ) } );
    this.tr.insert( this.th );
  }
});

Content.Form.Link = Class.create();
Object.extend( Object.extend( Content.Form.Link.prototype,
                              Content.Form.Base.prototype ), {
  create: function() {
    var a  = new Element( 'a', { href: this.data.Link } ).update( this.Value );
    this.td.insert( a );
    this.tr.insert( this.th );
    this.tr.insert( this.td );
  }
});


Content.Form.Input = Class.create();
Object.extend( Object.extend( Content.Form.Input.prototype, 
                              Content.Form.Base.prototype ), {
  create: function() {
    this.input = new Element( 'input', 
                              { name: this.Name, 
                                value: ( this.Value == null ? '' : this.Value ), 
                                className: 'Input', 
                                type: 'input' } );
    if ( this.data.MaxLength )
      this.input.writeAttribute( 'maxlength', this.data.MaxLength );
    if ( this.options.Width )
      this.input.setStyle( { width: this.options.Width + 'px' } );
    this.td.insert( this.input );
    this.tr.insert( this.th );
    this.tr.insert( this.td );
    Event.observe( this.input, 'keydown', this.inputKeyDown.bindAsEventListener( this ) );

    if ( this.data.Action ){
      this.td2 = new Element( 'td' ).setStyle( { cursor: 'pointer' } );
      this.td2.update( '[Action]' );
      this.tr.insert( this.td2 );
      Event.observe( this.td2, 'click', this.handleAction.bindAsEventListener( this ) );
    }

  },
  inputKeyDown: function( event ){
    if ( event.keyCode == Event.KEY_RETURN ) {
      this.submitForm();
      Event.stop( event );
    }
  },
  getValue: function() {
    return this.input.value;
  },
  setValue: function(value) {
    this.input.value = value;
  },
  getValue: function() {
    return this.input.value;
  },
  check: function() {

  },
  handleAction: function() {
    if ( this.data.Action == 'setZeroTime' )
      this.input.value = '00h00:00,000';
  }
});

Content.Form.Textarea = Class.create();
Object.extend( Object.extend( Content.Form.Textarea.prototype, 
                              Content.Form.Base.prototype ), {
  create: function() {
    this.input = new Element( 'textarea', { name: this.Name, className: 'Textarea' } );
    this.input.update( this.Value || '' );
    if ( this.options.Width )
      this.input.setStyle( { width: ( this.options.Width + 2 ) + 'px' } );
    this.td.insert( this.input );
    this.tr.insert( this.th );
    this.tr.insert( this.td );
  },
  inputKeyDown: function( event ){
    if ( event.keyCode == Event.KEY_RETURN ) {
      this.submitForm();
      Event.stop( event );
    }
  },
  getValue: function() {
    return this.input.value;
  },
  setValue: function(value) {
    this.input.value = value;
  }
});

Content.Form.Password = Class.create();
Object.extend( Object.extend( Content.Form.Password.prototype, 
                              Content.Form.Base.prototype ), {
  create: function() {
    this.input = new Element( 'input', { name:      this.Name, 
                                         value:     ( this.Value == null ? '' : this.Value ), 
                                         className: 'Input', 
                                         type:      'password' } );
    if ( this.options.Width )
      this.input.setStyle( { width: this.options.Width + 'px' } );
    this.td.insert( this.input );
    this.tr.insert( this.th );
    this.tr.insert( this.td );
    Event.observe( this.input, 'keydown', this.inputKeyDown.bindAsEventListener( this ) );
  },
  inputKeyDown: function( event ){
    if ( event.keyCode == Event.KEY_RETURN ) {
      this.submitForm();
      Event.stop( event );
    }
  },
  getValue: function() {
    return this.input.value;
  },
  setValue: function(value) {
    this.input.value = value;
  }
});


Content.Form.Button = Class.create();
Object.extend( Object.extend( Content.Form.Button.prototype, 
                              Content.Form.Base.prototype ), {
  create: function() {
    this.input = new Element( 'input', { type: 'button', name: this.Name, 
                                         className: 'Button', value: this.Label } );
    this.th.update();
    this.td.insert( this.input );
    this.tr.insert( this.th );
    this.tr.insert( this.td );
    Event.observe( this.input, 'click', this.buttonClick.bindAsEventListener( this ) );
  },
  buttonClick: function( event ){
    if ( this.data.Action &&
         this[this.data.Action] ){
      this[this.data.Action]();
    } else {
      this.ajaxRequest( this.getId() + '/' + this.Name + '=' + 
                        ( this.Ident || this.options.Ident || '' ) );
    }
    Event.stop( event );
    return false;
  },
  toggleInputs: function() {
    var n1 = this.data.Inputs[0],
        n2 = this.data.Inputs[1],
        i1 = this.parent.elemName[n1],
        i2 = this.parent.elemName[n2],
        v1 = i1.getValue(),
        v2 = i2.getValue();
    i1.setValue( v2 );
    i2.setValue( v1 );
  },
  reload: function() {
    var par = this.findParent( this.data.Level );
    if ( par ){
      par.requestResult();
    } else {
      Log.write( "No Parent" );
    }
  },
  cancel: function() {
    var par = this.findParent( this.data.Level );
    if ( par ){
      par.create();
    } else {
      Log.write( "No Parent" );
    }
  },
  disableButton: function() {
    this.input.blur();
    this.input.disable();
    this.ajaxRequest( this.getId() + '/' + this.Name + '=' + 
                      ( this.Ident || this.options.Ident || '' ) );
  },
  enableButton: function(json) {
    this.input.enable();
  },
  handleButton: function(json) {
    this.handleUpdate( json );
  },
  getOptions: function() {
    return { ajax: { handleButton: this.handleButton } };
  }
});

Content.Form.Submit = Class.create();
Object.extend( Object.extend( Content.Form.Submit.prototype, 
                              Content.Form.Base.prototype ), {
  create: function() {
    this.input = new Element( 'input', { type: 'button', name: this.Name, 
                                         className: 'Button', value: this.Label } );
    this.th.update();
    this.td.insert( this.input );
    this.tr.insert( this.th );
    this.tr.insert( this.td );
    Event.observe( this.input, 'click', this.click.bind( this ) );
    if ( ! Prototype.Browser.IE )
      Event.observe( this.input, 'focus', this.input.blur.bind( this.input ) );
  },
  click: function() {
    this.submitForm();
  },
  enable: function() {
    this.input.enable();
  },
  disable: function() {
    this.input.disable();
  }
});

Content.Form.Radio = Class.create();
Object.extend( Object.extend( Content.Form.Radio.prototype, 
                              Content.Form.Base.prototype ), {
  create: function() {
    var values = this.getValues();
    this.radios = [];
    for ( var i = 0; i < values.length; i++ ){
      var item  = values[i],
          id    = this.Name + ":" + item[0],
          radio = new Element( 'input', { type: 'radio', name: this.Name, id: id,
                                          className: 'Radio', value: item[0] } ),
          label = new Element( 'label', { 'for': id } ).update( item[1] );

      if ( this.Value == item[0] )
        radio.checked = true;

      this.radios.push( radio );

      this.td.insert( radio );
      this.td.insert( label );
      this.td.insert( '<br />' );
      Event.observe( radio, 'focus', radio.blur.bind( radio ) );
    }
    this.tr.insert( this.th );
    this.tr.insert( this.td );
  },
  getValue: function() {
    var values = '';
    this.radios.each( function(e) {
      if ( e.checked )
        values = e.value;
    });
    return values;
  },
  getValues: function() {
    return this.data.Values;
  }
} );

Content.Form.YesNo = Class.create();
Object.extend( Object.extend( Content.Form.YesNo.prototype, 
                              Content.Form.Radio.prototype ), {
  getValues: function() {
    return [ [ 'Y', 'Ja' ],
             [ 'N', 'Nein' ] ];
  }
});

Content.Form.Sex = Class.create();
Object.extend( Object.extend( Content.Form.Sex.prototype, 
                              Content.Form.Radio.prototype ), {
  getValues: function() {
    return [ [ 'M', 'Männlich' ],
             [ 'F', 'Weiblich' ],
             [ 'X', 'Unbekannt' ] ];
  }
});

Content.Form.Select = Class.create();
Object.extend( Object.extend( Content.Form.Select.prototype, 
                              Content.Form.Base.prototype ), {
  create: function() {
    this.renderSelect();
    this.td.insert( this.select );
    if ( this.others ){
      this.td.insert( '<br />' );
      this.td.insert( this.others );
    }

    this.tr.insert( this.th );
    this.tr.insert( this.td );
  },
  opts: function() {
    return this.data.Options;
  },
  renderSelect: function() {
    var select   = new Element( 'select', { className: 'Select', name: this.Name } ),
        options  = this.opts(),
        selected = false,
        others   = null;
    if ( this.options.Width )
      select.setStyle( { width: ( this.options.Width + 20 ) + 'px' } );

    for ( var i = 0; i < options.length; i++ ){
      var item   = options[i][0],
          value  = options[i][1],
          option = null;
      if ( value == '-' ){
        option = new Element( 'option', { disabled: 'disabled' } ).update( '<hr />' );
      } else if ( value == 'others' ){
        others = option = new Element( 'option', { value: '##others##' } ).update( 'Andere' );
      } else {
        option = this.renderOption( item, value );
      }

      if ( option ) {
        if ( item == this.Value )
          selected = option.selected = true;
        select.insert( option );
      }
    }

    this.select = select;

    if ( others ){
      this.others = new Element( 'input', { name: this.Name + "_other", 
                                            value: this.Value, className: 'Input' } );
      if ( this.options.Width )
        this.others.setStyle( { width: this.options.Width + 'px' } );
      if ( ! selected ) {
        others.selected = true;
        this.others.show();
      } else {
        this.others.hide();
      }
      Event.observe( this.select, 'change', this.change.bind( this ) );
    } 
    return select;
  },
  renderOption: function( value, content ){
    return new Element( 'option', { value: value } ).update( content );
  },
  getValue: function() {
    if ( this.select.value == '##others##' ){
      return this.others.value;
    } else {
      return this.select.value;
    }
  },
  change: function() {
    if ( this.select.value == '##others##' ){
      this.others.show();
    } else {
      this.others.hide();
    }
  }
});

Content.Form.Nation = Class.create();
Object.extend( Object.extend( Content.Form.Nation.prototype, 
                              Content.Form.Select.prototype ), {
  opts: function() {
    return Content.Vars.Nation;
  },
  renderOption: function( value, content ){
    var option = new Element( 'option', { value: value } ),
        img    = new Element( 'img', { src: '/images/flags/' + value + '.png' } );
    option.insert( img );
    option.insert( content );
    return option;
  }
});

Content.Form.Hidden = Class.create();
Object.extend( Object.extend( Content.Form.Hidden.prototype, 
                              Content.Form.Base.prototype ), {
  create: function() {
    this.input = new Element( 'input', { name:  this.Name, 
                                         value: ( this.Value == null ? '' : this.Value ), 
                                         type:  'hidden' } );
    this.td.insert( this.input );
    this.tr.insert( this.td );
  },
  getValue: function() {
    return this.input.value;
  }
});


Content.Output = Class.create();

Object.extend( Object.extend( Content.Output.prototype, Content.prototype ), {
  initialize: function( parent, container, data, options ) {
    this.parent    = parent;
    this.container = container;
    this.data      = data;
    this.setOptions( options );

    this.id        = data.Link;

    this.subcont   = new Element( 'div', { className: 'Output' } );
    this.colBar    = new Element( 'div', { className: 'OutputBar' } );
    this.content   = new Element( 'div', { className: 'OutputDiv' } );

    this.colBar.update( this.data.Title );

    this.subcont.insert( this.colBar );
    this.subcont.insert( this.content );
    this.container.insert( this.subcont );

    if ( this.data.Content )
      this.handleResult( this.data.Content );
    else
      this.requestResult();
  }
});


Content.Database        = Class.create();
Content.Database.Form   = Class.create();
Content.Database.Result = Class.create();

Object.extend( Object.extend( Content.Database.prototype, Content.prototype ), {
  initialize: function( parent, container, data, options ){
    this.parent      = parent;
    this.container   = container;
    this.data        = data;
    this.setOptions( options );

    this.container.addClassName( 'Database' );
    this.formDiv     = new Element( 'div' );
    this.resultDiv   = new Element( 'div' );

    this.form        = new Content.Database.Form( this, this.formDiv, this.data, this.options );
    this.result      = new Content.Database.Result( this, this.resultDiv, this.data, this.options );

    this.container.insert( this.formDiv );
    this.container.insert( this.resultDiv );
  },
  submitForm: function() {
    this.id = '';
    this.result.sendRequest( this.form.getQuery() );
  },
  createEntry: function() {
    this.id = 'create';
    this.result.sendRequest();
  }
});

Object.extend( Object.extend( Content.Database.Form.prototype, Content.Database.prototype ), {
  initialize: function( parent, container, data, options ){
    this.parent      = parent;
    this.container   = container;
    this.data        = data;
    this.setOptions( options );

    this.create();
  },
  create: function() {
    var fields  = this.data.Fields,
        wrap    = this.options.Wrap || 5;
    this.form   = new Element( 'form' );
    this.submit = new Element( 'input', { type: 'button', className: 'Button', value: 'Suchen' } );
    this.create = new Element( 'input', { type: 'button', className: 'Button', value: 'Erstellen' } );
    this.reset  = new Element( 'input', { type: 'button', className: 'Button', value: 'Reset' } );

    Event.observe( this.submit, 'click', this.clickSubmit.bind( this ) );
    Event.observe( this.create, 'click', this.clickCreate.bind( this ) );
    Event.observe( this.reset,  'click', this.clickReset.bind( this ) );

    for ( var i = 0; i < fields.length; i++ ){
      var field = fields[i],
          frame = new Element( 'div', { className: 'Frame' }),
          label = new Element( 'div', { className: 'Label' }).update( field.Label ),
          input = new Element( 'input', { className: 'Input', name: field.Name });
      if ( this.options.ColWidth )
        frame.setStyle( { width: this.options.ColWidth + 'px' } );
      frame.insert( label );
      frame.insert( input );
      Event.observe( input, 'keydown', this.inputKeyDown.bindAsEventListener( this ) );
      this.form.insert( frame );

      if ( ( i + 1 ) % wrap == 0 )
        this.form.insert( new Element( 'br', { className: 'Clear' } ));
    }

    this.form.insert( new Element( 'br', { className: 'Clear' } ));
    this.form.insert( this.submit );
    if ( this.options.Create )
      this.form.insert( this.create );
    if ( this.options.Reset )
      this.form.insert( this.reset );
    this.form.insert( new Element( 'br', { className: 'Clear' } ));

    this.container.insert( this.form );
  },
  clickSubmit: function() {
    this.submit.blur();
    this.parent.submitForm();
  },
  clickCreate: function() {
    this.create.blur();
    this.parent.createEntry();
  },
  clickReset: function() {
    this.reset.blur();
    this.resetForm();
  },
  inputKeyDown: function( event ){
    if ( event.keyCode == Event.KEY_RETURN ) {
      this.parent.submitForm();
      Event.stop( event );
    }
  },
  getQuery: function() {
    return this.form.serialize();
  },
  resetForm: function() {
    this.form.reset();
  }
});

Object.extend( Object.extend( Content.Database.Result.prototype, Content.Database.prototype ), {
  initialize: function( parent, container, data, options ){
    var cont = new Element( 'div', { className: 'Output' } );
    this.parent      = parent;
    this.container   = container;
    this.data        = data;
    this.setOptions( options );

    this.colBar  = new Element( 'div', { className: 'OutputBar' } );
    this.content = new Element( 'div', { className: 'OutputDiv' } );

    this.colBar.update( 'Ergebnis' );

    cont.insert( this.colBar );
    cont.insert( this.content );
    this.container.insert( cont );
  },
  sendRequest: function( query ){
    this.requestResult( query );
  },
  setBar: function( msg ) {
    this.colBar.update( 'Ergebnis' + ( msg ? ' - ' + msg : '' ));
  }
});

Content.Drop      = Class.create();
Content.Drop.Item = Class.create();

Object.extend( Object.extend( Content.Drop.prototype, Content.prototype ), {
  initialize: function( parent, container, data, options ) {
    this.parent    = parent;
    this.container = container;
    this.data      = data;
    this.setOptions( options );

    this.drags     = [];

    this.create();
  },
  create: function() {

    this.dropZone  = new Element( 'div', { className: 'Drop' } );
    this.subcont   = new Element( 'div', { className: 'Output' } );
    this.colBar    = new Element( 'div', { className: 'OutputBar' } );
    this.content   = new Element( 'div', { className: 'OutputDiv' } );
    this.submit    = new Element( 'input', { type: 'button', value: 'Übertragen', className: 'Submit' } );
    this.del       = new Element( 'input', { type: 'button', value: 'Löschen', className: 'Button' } );

    this.submit.setStyle( { marginBottom: '10px',
                            marginRight:  '30px' } );
    this.del.setStyle( { marginBottom: '10px' } );

    this.colBar.update( this.data.Title );

    Droppables.add( this.dropZone, 
                    { onDrop: this.drop.bind( this ) } );
    Event.observe( this.submit, 'click', this.submitClick.bind( this ));
    Event.observe( this.del, 'click', this.delClick.bind( this ));

    this.container.insert( new Element( 'div' ).update( this.data.Text ) );
    this.container.insert( this.dropZone );
    this.container.insert( this.submit );
    this.container.insert( this.del );

    this.subcont.insert( this.colBar );
    this.subcont.insert( this.content );

    this.container.insert( this.subcont );

    this.handleResult( this.data.Content );
  },
  drop: function( elem ){
    this.drags.push( new Content.Drop.Item( this, this.dropZone, elem, this.options ) );
  },
  submitClick: function() {
    if ( this.drags.length ){
      var hash = {};
      this.submit.disable();
      this.del.disable();
      this.drags.each( function( e ) { hash[e.elemId] = 1; e.submited() } );
      this.ajaxRequest( this.getId() + '/' + this.options.Link, hash );
    }
  },
  delClick: function() {
    var arr  = [],
        that = this;
    this.drags.each( function( e ) { if ( e.marked ){ e.remove(); arr.push( e ); }} );
    arr.each( function( e ){ that.drags = that.drags.without( e ); } );
  }
});

Object.extend( Object.extend( Content.Drop.Item.prototype, Content.Drop.prototype ), {
  initialize: function( parent, container, elem, options ) {
    this.parent    = parent;
    this.container = container;
    this.elem      = elem;
    this.setOptions( options );
    this.submit    = false;
    this.marked    = false;

    this.elemId    = elem.readAttribute( 'drag' );

    this.id        = this.options.Info;

    this.info      = new Element( 'div' );
    this.ajaxRequest( this.getId() + '=' + this.elemId );
    this.info.update( this.elemId );
    this.container.insert( this.info );

    Event.observe( this.info, 'click', this.click.bind( this ));
  },
  click: function() {
    if ( this.submit ){
    } else if ( this.marked ){
      this.info.removeClassName( 'Marked' );
      this.marked = false;
    } else {
      this.info.addClassName( 'Marked' );
      this.marked = true;
    }
  },
  remove: function() {
    this.info.remove();
  },
  submited: function() {
    this.submit = true;
    this.info.addClassName( 'Disabled' );
  },
  handleInfo: function( json ){
    this.info.update( json.Result );
  },
  getOptions: function() {
    return { ajax: { handleInfo: this.handleInfo.bind( this ) } };
  }
});


Content.Selection      = Class.create();
Content.Selection.Item = Class.create();

Object.extend( Object.extend( Content.Selection.prototype, Content.prototype ), {
  initialize: function( parent, container, data, options ) {
    this.parent    = parent;
    this.container = container;
    this.data      = data;
    this.setOptions( options );

    this.selection = [];

    this.create();
  },
  create: function() {
    this.colBar     = new Element( 'div', { className: 'OutputBar' } );
    this.content    = new Element( 'div', { className: 'OutputDiv' } );
    this.submit     = new Element( 'input', { type: 'button', value: 'Übertragen', className: 'Submit' } );
    this.subcont    = new Element( 'div', { className: 'Output' } );
    Event.observe( this.submit, 'click', this.submitClick.bind( this ));

    this.submit.setStyle( { marginBottom: '10px',
                            marginRight:  '30px' } );

    this.colBar.update( 'Auswahl per Doppel-Klick' );

    if ( this.data.Mode == 'source' ){
      this.sourceElem = new Element( 'div', { className: 'Selection' } );
      this.targetElem = new Element( 'div', { className: 'Selection' } ).update( 'Auswahl per Doppel-Klick' );

      this.source     = new Content.Selection.Item( this, this.sourceElem, this.data.Source, this.options );
      this.source.disableDelete();

      this.container.update();
      this.container.insert( new Element( 'div' ).update( this.data.Text1 ) );
      this.container.insert( this.sourceElem );
      this.container.insert( new Element( 'div' ).update( this.data.Text2 ) );
      this.container.insert( this.targetElem );
      this.container.insert( new Element( 'div' ).update( this.data.Text3 ) );
      this.container.insert( this.submit );
    } else if ( this.data.Mode == 'focus' ) {
      this.targetElem = new Element( 'div', { className: 'Selection' } ).update( 'Auswahl per Doppel-Klick' );

      this.container.update();
      this.container.insert( new Element( 'div' ).update( this.data.Text1 ) );
      this.container.insert( this.targetElem );
      this.container.insert( new Element( 'div' ).update( this.data.Text2 ) );
      this.container.insert( this.submit );
    } else {
      Log.write( "Mode '%s' is unknown".sprintf( this.data.Mode ) );
    }

    this.subcont.insert( this.colBar );
    this.subcont.insert( this.content );

    this.container.insert( this.subcont );

    this.handleResult( this.data.Content );
  },
  setSelection: function( id ){
    if ( this.selection.length == 0 )
      this.targetElem.update();
    if ( ! this.selection.find( function(e){ return id == e.data } ) )
      this.selection.push( new Content.Selection.Item( this, this.targetElem, id, this.options ) );
  },
  remove: function( elem ){
    this.selection = this.selection.without( elem );
    elem.remove();
    if ( this.selection.length == 0 )
      this.targetElem.update( 'Auswahl per Doppel-Klick' );
  },
  submitClick: function() {
    if ( this.selection.length ){
      var hash = {},
          link = null;
      if ( this.data.Mode == 'source' ){
        link = this.getId() + '/' + this.options.Link;
      } else if ( this.data.Mode == 'focus' ){
        if ( Content.Focus )
          link = this.getId() + '/' + this.options.Link + '=' + Content.Focus.getFocus();
        else
          alert( this.options.NoFocusText );
      }
      if ( link ) {
        this.showFan();
        this.submit.disable();
        this.selection.each( function( e ) { hash[e.data] = 1; e.submited() } );
        this.ajaxRequest( link, hash );
      }
    }
  }
});

Object.extend( Object.extend( Content.Selection.Item.prototype, Content.Selection.prototype ), {
  initialize: function( parent, container, data, options ) {
    this.parent    = parent;
    this.container = container;
    this.data      = data;
    this.setOptions( options );
    this.submit    = false;
    this.marked    = false;

    this.row = new Element( 'div', { className: 'BarContent' } ).update( this.data );
    this.container.insert( this.row );
    this._mousedown = this.mousedown.bindAsEventListener( this );
    this._dblclick  = this.dblclick.bindAsEventListener( this );

    Event.observe( this.row, 'mousedown', this._mousedown );
    Event.observe( this.row, 'dblclick',  this._dblclick );

    this.ajaxRequest( this.getId() + '/' + this.options.Info + '=' + this.data );
  },

  disableDelete: function() {
    Event.stopObserving( this.row, 'mousedown', this._mousedown );
    Event.stopObserving( this.row, 'dblclick',  this._dblclick );
  },

  handleInfo: function( json ){
    this.create( json.Row );
  },

  create: function( row ) {
    var defi    = this.options.RowDef;

    this.row.update();

    for ( var i = 0; i < defi.length; i++ ){
      var def  = defi[i],
          col  = new Element( 'div', { className: 'Item' } ),
          val  = new String( ( row ? row[i] : def.Value ) || '&nbsp;' ),
          styl = {};

      if ( def.Width )
        styl.width      = ( def.Width - 5 ) + 'px';
      if ( def.Center )
        styl.textAlign  = 'center';
      if ( def.Right )
        styl.textAlign  = 'right';
      if ( def.Bold )
        styl.fontWeight = 'bold';
      if ( def.Bright )
        styl.color      = '#888888';

      if ( def.Padding && def.Right ){
        styl.width      = ( def.Width - 5 - def.Padding ) + 'px';
        styl.paddingRight = ( def.Padding + 2 ) + 'px';
      } else if ( def.Padding ){
        styl.width      = ( def.Width - 5 - def.Padding ) + 'px';
        styl.paddingLeft = ( def.Padding + 2 ) + 'px';
      }

      col.setStyle( styl );
      col.update( val );

      if ( def.HideBorder )
        col.addClassName( 'HideBorder' );
      else
        col.addClassName( 'Border' );

      this.row.insert( col );
    }
    this.row.insert( new Element( 'br', { className: 'Clear' } ) );
  },

  remove: function() {
    this.row.remove();
  },
  submited: function() {
    this.submit = true;
    this.row.addClassName( 'Disable' );
  },
  mousedown: function(event){
    Event.stop( event );
  },
  dblclick: function(event) {
    this.parent.remove( this );
    Event.stop( event );
  },
  getOptions: function() {
    return { ajax: { handleInfo: this.handleInfo.bind( this ) } };
  }
});


Content.Actions    = Class.create();

Object.extend( Object.extend( Content.Actions.prototype, Content.prototype ), {
  initialize: function( parent, container, data, options ){

    this.parent       = parent;
    this.container    = container;
    this.data         = data;
    this.setOptions(options);

    this.id           = data.Link;

  },
  handleAction: function(json) {

  },
  getOptions: function() {
    return { ajax: { handleAction: this.handleAction.bind( this ) } };
  }
});


