//
// COMMUNITOR SiteWare 2.0 Site Server
// Copyright by COMMUNITOR Internetservice GmbH, 2001-2010
//


/*************************************/
/*  Popup Klasse SWpopupCollection   */
/*************************************/
var SWpopupCollection = Class.create();
Object.extend(SWpopupCollection.prototype, {
  initialize: function(container) {
    this.all = [];
    this.images = new Hash();
    this.forms = new Hash();
    this.container = $(container);
    this.options = Object.extend({
      selector: ['a[rel]','area[rel]','input[type="image"]'],
      quirksMode: false
    }, arguments[1] || { });
    // data is stored in rel attribute
    this.container.select(this.options.selector).each(this.setup.bind(this));
  },
  setup: function(link){
    var data,admin,
        rel = link.readAttribute('rel'),
        pos = this.all.length;
    if (!rel) return;
    // ignore double-dots in url as this is our delimiter
    //rel="SWpopup:imgID,Container_Connector_Url,HighRes_FileName_url,HighRes_Size_w,HighRes_Size_h"
    //rel="SWrollover:idButRequest,but_anfrageformular1.gif:SWpopup:idButRequest,DirectRequestButton.html?partial=true<%= CGIsessionp1 %>,#html#,500,600"
    rel = rel.replace('http://','http_//').split(':');
    if (rel[0] == 'SWpopup' || rel[0] == 'SWadminPopup') {
      data = rel[1].split(',');
      admin = 0;
    } else if (rel[2] == 'SWpopup' || rel[2] == 'SWadminPopup') {
      data = rel[3].split(',');
      admin = 2;
    } else
      return;
    // create form popup if not already created
    if (Object.isUndefined(this.forms.get(data[0]))) {
      this.all[pos] = new SWpopup(
        data[0],
        data[1].replace('http_//','http://'),
        data[2].replace('http_//','http://'),
        data[3],data[4],
        {adminMode:(rel[admin] == 'SWadminPopup'), collection:this, index:pos}
      );
      if (data[2] == '#html#')
        this.forms.set(data[0],pos);
      else
        this.images.set(data[0],pos);
    } else
      pos = this.forms.get(data[0]);
    link.observe('click', this.show.bindAsEventListener(this,pos));
  },
  _getPosition: function(id,prev_next) {
    if (!isNaN(id) && !prev_next)
      return id;
    var pos = this.images.get(id);
    if (Object.isUndefined(pos))
      pos = this.forms.get(id);
    else if (prev_next) {
      var i = this.all.length;
      while (i > 0) {
        if (prev_next.position == 'previous')
          --pos;
        else if (prev_next.position == 'next')
          ++pos;
        pos = (pos < 0 ? this.all.length -1 : (pos >= this.all.length ? 0 : pos));
        // return if valid image is found
        if (this.all[pos] && this.all[pos].id && !Object.isUndefined(this.images.get(this.all[pos].id)))
          return pos;
        --i;
      }
      return this._notfound(prev_next.position);
    }
    if (Object.isUndefined(pos) || !this.all[pos])
      return this._notfound(id);
    return pos;
  },
  _notfound: function(id) {
    alert('id '+id+' has no related popup!');
    return;
  },
  show: function(e,id,prev_next) {
    if (e) e.stop();
    var pos = this._getPosition(id,prev_next);
    if (!isNaN(pos))
      return this.all[pos].show();
  },
  hide: function(e,id) {
    if (e) e.stop();
    var pos = this._getPosition(id);
    if (!isNaN(pos))
      return this.all[pos].hide();
  },
  visible: null
});


/*************************************/
/*  Popup Klasse SWpopup             */
/*************************************/
var SWpopup = Class.create();
Object.extend(SWpopup.prototype, {
  initialize: function(caller_id,container_url,content_url_or_function,width,height,options) {
    this.id = caller_id;
    this.caller = $(caller_id);
    this.loaded = false;
    // if url is of type function use it as callback handler
    if (Object.isFunction(content_url_or_function)) {
      this.afterFormatHandler = content_url_or_function;
    } else if (content_url_or_function != '#html#')
      this.contentUrl = content_url_or_function;
    // parseInt to get ints
    this.contentWidth = parseInt(width);
    this.contentHeight = parseInt(height);
    this.minScaleFactor = 0.0;
    this.callerDimensions = this.caller.getDimensions();
    // optional configuration options
// google map after zoom: checkResize()
    this.options = Object.extend({
      borderClasses: ['shTopLeft','shTopRight','shBottomLeft','shBottomRight'],
      contentClass: 'shContent',
      animationDuration: 1,
      animationAnchor: 'bottom-left',
      adminMode: false,
      collection: null,
      index: null,
      afterResizeHandler: null
    }, options || { });
    // create containing div and position it bottom-left on top of caller
    this.div = new Element("div");
    this.div.identify();
    this.contentDiv = null;
    this.borders = {top:0,right:0,bottom:0,left:0,width:0,height:0,contentLeft:0,contentRight:0,contentTop:0,contentBottom:0};
    this.buttons = {};
    this.contentElements = new Array();
    var offsets = document.viewport.getScrollOffsets(),
        positions = this.caller.viewportOffset();
    this.storedPosition = new SWdimensions({
      left:(offsets[0] + positions[0]) < 0 ? 0 : offsets[0] + positions[0],
      top: ((offsets[1] + positions[1]) < 0 ? 0 : offsets[1] + positions[1]) + this.callerDimensions.height
    });
    this.div.setStyle(Object.extend({
      position:  'absolute',
      zIndex:    ($(document.getElementsByTagName("body")[0]).getMaxZIndex()+100),
      visibility:'hidden',
      opacity:   1
    }, this.storedPosition.getStyle()));
    // load content of popup
    container_url = container_url.applyBaseHref(container_url.indexOf('./') == 0 ? window.location.href : this.caller.src);
    // compatibility: we use & instead of ; to be able to connect to non-siteware servers
    var params = 'partial=true&admin='+this.options.adminMode;
    if (container_url.indexOf('?') > -1) {
      container_url = container_url.split('?');
      container_url = container_url[0] + '?' + params + '&' + container_url[1].split(';').join('&');
    } else
      container_url += '?' + params;
    new Ajax.Request(container_url, {
      asynchronous: true,
      method: 'get',
      evalScripts: true,
      onSuccess: this.handleResponse.bind(this),
      onFailure:SWErrorHandler
    });
  },
  handleResponse: function(t) {
    // process XML response
    var xmlDoc = t.responseXML.documentElement;
    var nodes=xmlDoc.childNodes;
    for (var i=0;i<nodes.length;i++) {
      if (nodes[i].nodeName) {
        var tagName = nodes[i].nodeName.split(":");
        if (tagName[0] == "siteware") {
          try {
            this.div.update(nodes[i].firstChild.nodeValue.replace(/\]\]->/g, "]]"+">")).cleanWhitespace();
          } catch (e) {
            alert("Update failed with message: "+e);
          }
        }
      }
    }
    $(document.getElementsByTagName("body")[0]).insert(this.div);
    try {
      this.formatSize();
      this.setBoxDimensions();
      // initialize rollover images
      new SWrollover(this.div,this.contentUrl ? {selector:'img[rel]'} : {});
      // call content handling function
      if (this.afterFormatHandler) this.afterFormatHandler(this.contentDiv,this);
      // register descendants
      this.getDescendants(
        this.contentDiv,
        new Array(this.buttons.btnClose,this.buttons.btnNext,this.buttons.btnPrev)
      ).flatten().compact().each(this.setupDescendants.bind(this));
    } catch (e) {
      alert("Formatting failed with message: "+e);
    }
    // mark as loaded
    this.loaded = true;
    if (Prototype.Browser.IE)
      this.opacityElements = [this.buttons.btnClose,this.buttons.btnNext,this.buttons.btnPrev,
        this.borders.topLeft,this.borders.topRight,this.borders.bottomLeft,this.borders.bottomRight].flatten().compact();
  },
  formatSize: function() {
    // adjust border dimensions: left-width, right-width, top-height, bottom-height, min-width, min-height
    var myDiv = this.div, borderDiv, offsets, pos, size, borders = this.borders, zIndex = myDiv.getMaxZIndex(), hasBorders = false;
    // top-left corner
    borderDiv = myDiv.select('.'+this.options.borderClasses[0])[0];
    if (borderDiv) {
      borders.topLeft = borderDiv;
      hasBorders = true;
      pos = parseInt(borderDiv.getStyle('left') || 0);
      size = parseInt(borderDiv.getStyle('width') || 0);
      borders.left = -pos;
      borders.contentLeft = size - borders.left;
      pos = parseInt(borderDiv.getStyle('top') || 0);
      size = parseInt(borderDiv.getStyle('height') || 0);
      borders.top = -pos;
      borders.contentTop = size - borders.top;
      borderDiv.setStyle({ top: '0px', left: '0px', zIndex: -1 });
    }
    // top-right corner
    borderDiv = myDiv.select('.'+this.options.borderClasses[1])[0];
    if (borderDiv) {
      borders.topRight = borderDiv;
      hasBorders = true;
      pos = parseInt(borderDiv.getStyle('right') || 0);
      size = parseInt(borderDiv.getStyle('width') || 0);
      borders.right = -pos;
      borders.contentRight = size - borders.right;
      borderDiv.setStyle({ top: '0px', right: '0px', zIndex: -1 });
    }
    // bottom-left corner
    borderDiv = myDiv.select('.'+this.options.borderClasses[2])[0];
    if (borderDiv) {
      borders.bottomLeft = borderDiv;
      hasBorders = true;
      pos = parseInt(borderDiv.getStyle('bottom') || 0);
      size = parseInt(borderDiv.getStyle('height') || 0);
      borders.bottom = -pos;
      borders.contentBottom = size - borders.bottom;
      borderDiv.setStyle({ bottom: '0px', left: '0px', zIndex: -1 });
    }
    // bottom-right corner
    borderDiv = myDiv.select('.'+this.options.borderClasses[3])[0];
    if (borderDiv) {
      borders.bottomRight = borderDiv;
      hasBorders = true;
      borderDiv.setStyle({ bottom: '0px', right: '0px', zIndex: -1 });
    }
    // get definitions of content container
    var contentDiv = myDiv.select('.'+this.options.contentClass)[0];
    this.contentDiv = contentDiv;
    contentDiv.setStyle({
      position:'absolute',
      overflow:'visible',
      zIndex:  (zIndex-4),
      left:    borders.left+'px',
      top:     borders.top+'px',
      right:   '',
      bottom:  '',
      width:   this.contentWidth  + 'px',
      height:  this.contentHeight + 'px'
    });
    // configure image only if we have an image
    if (this.contentUrl) {
      var img = contentDiv.select('.shImage')[0];
      if (img) {
        img.src = this.contentUrl.applyBaseHref(
          (this.contentUrl.indexOf('./') == 0 || !this.caller.src) ? window.location.href : this.caller.src
        );
        img.setStyle({
          position:'absolute',
          width:   this.contentWidth  + 'px',
          height:  this.contentHeight + 'px',
          top:     '0px',
          left:    '0px',
          bottom:  '',
          right:   ''
        });
      }
    } else {
      var myPopup = this;
      this.contentDiv.select('form').each(function(form) {
        form.closeButton = myDiv.select('.btnClose')[0];
        form.closePopup = myPopup.hide.bind(myPopup);
      });
    }
    // correct dimensions container div
    this.storedPosition.top -= (this.contentHeight + borders.top);
    this.storedPosition.left -= borders.left;
    this.storedPosition.width  = this.contentWidth + borders.left + borders.right;
    this.storedPosition.height = this.contentHeight + borders.top + borders.bottom;
    this.minScaleFactor = Math.min(1,Math.max(
      (borders.contentLeft + borders.contentRight) / this.contentWidth,
      (borders.contentTop + borders.contentBottom) / this.contentHeight,
      img ? this.callerDimensions.width / this.contentWidth : 0,
      img ? this.callerDimensions.height / this.contentHeight : 0
    )) * 100;
    // configure Buttons
    this.buttons.btnClose = myDiv.select('.btnClose');
    this.buttons.btnClose.invoke('observe','click', this.hide.bindAsEventListener(this));
    var collection = this.options.collection;
    if (collection && collection.images.keys().length > 1) {
      this.buttons.btnNext = myDiv.select('.btnNext');
      this.buttons.btnNext.invoke(
        'observe',
        'click',
        collection.show.bindAsEventListener(collection,this.id,{position:'next'})
      );
      this.buttons.btnPrev = myDiv.select('.btnPrev');
      this.buttons.btnPrev.invoke(
        'observe',
        'click',
        collection.show.bindAsEventListener(collection,this.id,{position:'previous'})
      );
    } else {
      myDiv.select('.btnNext').invoke('hide');
      myDiv.select('.btnPrev').invoke('hide');
    }
  },
  setBoxDimensions: function(movements,effect) {
    // get sizes or set sizes
    var contentSize;
    if (movements && effect)
      contentSize = this.getContentBoxSize();
    else
      contentSize = this.setContentBoxSize();
    if (this.borders.topLeft || this.borders.topRight || this.borders.bottomLeft || this.borders.bottomRight)
      contentSize = this.setBorderBoxes(contentSize);
    this.setContainerDimensions(contentSize.width,contentSize.height,movements,effect);
  },
  setContentBoxSize: function() {
    this.contentDiv.setStyle({width:this.contentWidth+'px',height:this.contentHeight+'px'});
    return { width: this.contentWidth, height: this.contentHeight }
  },
  getContentBoxSize: function() {
    return {
      width:  parseInt(this.contentDiv.getStyle('width') || 0),
      height: parseInt(this.contentDiv.getStyle('height') || 0)
    }
  },
  setBorderBoxes: function(contentSize) {
    var topHeight = Math.ceil(contentSize.height/2) + this.borders.top,
        rightWidth = Math.ceil(contentSize.width/2) + this.borders.right,
        bottomHeight = Math.floor(contentSize.height/2) + this.borders.bottom,
        leftWidth = Math.floor(contentSize.width/2) + this.borders.left;
    if (this.borders.topLeft)
      this.borders.topLeft.setStyle({ width: leftWidth+'px', height: topHeight+'px' });
    if (this.borders.topRight)
      this.borders.topRight.setStyle({ width: rightWidth+'px', height: topHeight+'px' });
    if (this.borders.bottomLeft)
      this.borders.bottomLeft.setStyle({ width: leftWidth+'px', height: bottomHeight+'px' });
    if (this.borders.bottomRight)
      this.borders.bottomRight.setStyle({ width: rightWidth+'px', height: bottomHeight+'px' });
    return {
      width: contentSize.width + this.borders.left + this.borders.right,
      height: contentSize.height + this.borders.top + this.borders.bottom
    };
  },
  setContainerDimensions: function(width,height,movements,effect) {
    var dimensions, direction = this.options.animationAnchor.split('-');
    if (movements && movements.position)
      dimensions = new SWdimensions(movements.position);
    else
      dimensions = new SWdimensions(this.storedPosition);
    if (movements && effect && effect.position) {
      dimensions.left += (parseInt(movements.x || 0) * effect.position).round();
      dimensions.top  += (parseInt(movements.y || 0) * effect.position).round();
    }
    switch (direction[0]) {
      case 'bottom':
        dimensions.top += (dimensions.height - height);
        break;
      case 'center':
        dimensions.top += ((dimensions.height - height)/2).round();
        dimensions.left += ((dimensions.width - width)/2).round();
        break;
    }
    if (direction[1] && direction[1] == 'right')
      dimensions.left += (dimensions.width - width);
    dimensions.width = width;
    dimensions.height = height;
    this.div.setStyle(dimensions.getStyle());
  },
  setContentPosition: function(item,effect) {
    if (Object.isNumber(item.top) && Object.isNumber(item.left)) {
      if (item.top != 0 || item.left != 0) {
        var currentScale = (effect.options.scaleFrom/100.0) + (effect.factor * effect.position);
        item.element.setStyle({
          top: (item.top * currentScale).round()+'px',
          left:(item.left * currentScale).round()+'px'
        });
      }
    }
  },
  getCenteredOffsets: function() {
    // move image box to actual center of screen and correct scroll-position with offset
    var dimensions = document.viewport.getDimensions(),
        offsets = document.viewport.getScrollOffsets(),
        left = (dimensions.width/2  + offsets.left - this.storedPosition.width/2).round(),
        top  = (dimensions.height/2 + offsets.top  - this.storedPosition.height/2).round();
    if (top < 0) top = 0;
    if (left < 0) left = 0;
    return {
      x: left - this.storedPosition.left,
      y: top - this.storedPosition.top,
      position: this.storedPosition
    };
  },
  getStoredOffsets: function() {
    // move image box to stored position
    var currentPosition = new SWdimensions(this.div);
    return {
      x: this.storedPosition.left - currentPosition.left,
      y: this.storedPosition.top - currentPosition.top,
      position: currentPosition
    };
  },
  getDescendants: function(parent,descendants,skipMode) {
    // clear array of any obsolete nodes that will not get resized
    var myself = this;
    parent.childElements().each(function(node) {
      switch (node.nodeName) {
        case 'DIV':
          node.absolutize();
        case 'INPUT':
          if ((node.type == 'checkbox') || (node.type == 'radio'))
            return;
        case 'IMG':
        case 'TEXTAREA':
        case 'SELECT':
          if (!skipMode) {
            if (node.hasClassName('skipResizing'))
              skipMode = true;
            descendants.push(node);
            myself.getDescendants.bind(myself,node,descendants,skipMode);
          }
      }
    });
    return descendants;
  },
  setupDescendants: function(node) {
    // getting and setting of font-size is to prevent multiple propagation of scaled font sizes in FF
    var offsets = node.positionedOffset(),
        dimensions = node.getDimensions(),
        fontSize = node.getStyle('font-size') || '100%';
    node.setStyle({
      top: offsets.top+'px',
      left: offsets.left+'px',
      right: '',
      bottom: '',
      width: dimensions.width+'px',
      height: dimensions.height+'px',
      fontSize: fontSize
    });
    this.contentElements.push({
      element: node,
      scaleMode: {
        originalHeight: dimensions.height,
        originalWidth: dimensions.width
      },
      top: offsets.top,
      left: offsets.left
    });
  },
  show: function(e) {
    if (!this.loaded) {
      var str = "Das vergr"+unescape('%F6')+unescape('%DF')+"erte Bild ist noch nicht fertig geladen.\n";
      str += "Bitte klicken Sie in K"+unescape('%FC')+"rze erneut!"
      alert(str);
      return;
    }
    var oldPopup;
    if (this.options.collection)
      oldPopup = this.options.collection.visible;
    if (!oldPopup)
      this.zoomIn();
    else if (oldPopup != this) {
      this.blendIn(oldPopup.blendOut({toggle:true}));
    }
    if (this.options.collection)
      this.options.collection.visible = this;
  },
  hide: function(e) {
    if (this.options.collection && this.options.collection.visible == this)
      this.options.collection.visible = null;
    this.zoomOut();
  },
  zoomIn: function() {
    // start animation: zoom in from thumb size to full size, move to center and blend in
    var myself = this, container = this.div, effects = [new Effect.Scale(this.contentDiv, 100, {
      sync: true,
      scaleFrom: this.minScaleFactor,
      scaleMode: { originalHeight: this.contentHeight, originalWidth: this.contentWidth },
      afterUpdate: this.setBoxDimensions.bind(this,this.getCenteredOffsets())
    })];
    // protect PNG borders from wrong rendering in IE: use 1/0 transition and only for borders. limit standard opacity transition to content div
    if (Prototype.Browser.IE && this.opacityElements) {
      this.opacityElements.each(function(div){
        effects.push(new Effect.Opacity(div, { sync: true, from: 0, to: 1, transition: Effect.Transitions.twenty }));
      });
      container = this.contentDiv;
    }
    // resize content elements
    this.contentElements.each(function(item,index){
      effects.push(new Effect.Scale(item.element, 100, {
        sync: true,
        scaleFrom: myself.minScaleFactor,
        scaleMode: item.scaleMode,
        afterUpdate: myself.setContentPosition.bind(myself,item)
      }));
    });
    effects.push(new Effect.Opacity(container, {
      sync: true,
      from: 0.2,
      to: 1,
      transition: Effect.Transitions.linear,
      afterSetup: Element.setStyle.bind(this,this.div,{visibility:'visible'})
    }));
    new Effect.Parallel(effects, {
      duration: this.options.animationDuration
    });
  },
  zoomOut: function() {
    // start animation: zoom in from thumb size to full size, move to center and blend in
    var myself = this, container = this.div, effects = [new Effect.Scale(this.contentDiv, this.minScaleFactor, {
      sync: true,
      scaleMode: { originalHeight: this.contentHeight, originalWidth: this.contentWidth },
      afterUpdate: this.setBoxDimensions.bind(this,this.getStoredOffsets()),
      afterFinish: Element.setStyle.bind(this,this.div,{visibility:'hidden'}),
      restoreAfterFinish: true
    })];
    // protect PNG borders from wrong rendering in IE: use 1/0 transition and only for borders. limit standard opacity transition to content div
    if (Prototype.Browser.IE && this.opacityElements) {
      this.opacityElements.each(function(div){
        effects.push(new Effect.Opacity(div, { sync: true, from: 1, to: 0, transition: Effect.Transitions.eighty }));
      });
      container = this.contentDiv;
    }
    // resize content elements
    this.contentElements.each(function(item){
      effects.push(new Effect.Scale(item.element, myself.minScaleFactor, {
        sync: true,
        scaleMode: item.scaleMode,
        restoreAfterFinish: true,
        afterUpdate: myself.setContentPosition.bind(myself,item)
      }));
    });
    effects.push(new Effect.Opacity(container, { sync: true, from: 1, to: 0.2, transition: Effect.Transitions.linear }));
    new Effect.Parallel(effects, {
      duration: this.options.animationDuration,
      afterFinish: this.setBoxDimensions.bind(this)
    });
  },
  blendIn: function(options) {
    // start animation: move to center and blend in at full size
    var effects = [], newOptions = {}, container = this.div, offsets = this.getCenteredOffsets();
    container.setStyle({
      left: (offsets.position.left + offsets.x)+'px',
      top:  (offsets.position.top + offsets.y)+'px'
    });
    // protect PNG borders from wrong rendering in IE: use 1/0 transition and only for borders. limit standard opacity transition to content div
    if (Prototype.Browser.IE && this.opacityElements) {
      this.opacityElements.each(function(div){
        effects.push(new Effect.Opacity(div, { sync: true, from: 0, to: 1, transition: Effect.Transitions.round }));
      });
      container = this.contentDiv;
    }
    effects.push(new Effect.Opacity(container, { sync: true, from: 0, to: 1, transition: Effect.Transitions.linear }));
    if (options && options.toggle) {
      if (Object.isArray(options.effects))
        effects = options.effects.concat(effects);
      Object.extend(newOptions, options.options || {});
    }
    new Effect.Parallel(effects, Object.extend(newOptions, {
      afterSetup: Element.setStyle.bind(this,this.div,{visibility:'visible'}),
      duration: this.options.animationDuration
    }));
  },
  blendOut: function(options) {
    // start animation: blend out at full size and move to stored position 
    var effects = [], newOptions = {}, container = this.div;
    // protect PNG borders from wrong rendering in IE: use 1/0 transition and only for borders. limit standard opacity transition to content div
    if (Prototype.Browser.IE && this.opacityElements) {
      this.opacityElements.each(function(div){
        effects.push(new Effect.Opacity(div, { sync: true, from: 1, to: 0, transition: Effect.Transitions.round }));
      });
      container = this.contentDiv;
    }
    effects.push(new Effect.Opacity(container, { sync: true, from: 1, to: 0, transition: Effect.Transitions.linear }));
    newOptions = {
      afterFinish: (function() {
        var myself = this;
        // delay is to prevent a flicker in IE
        Element.setStyle.delay(0,myself.div,{visibility:'hidden'});
        myself.setBoxDimensions.bind(myself).delay(0);
      }).bind(this),
      duration: this.options.animationDuration
    }
    // in toggle mode only pass setup to next parallel effect
    if (options && options.toggle)
      return { effects: effects, options: newOptions, toggle: true};
    else
      new Effect.Parallel(effects, newOptions);
  }
});