/*
Script: popup.js
  
Copyright:
  copyright (c) 2007 wollzelle GmbH, <http://www.wollzelle.com>

Group: popup
  collects base functions for popups used in the printmaster application
*/

/*
Class: Popup
  collects functions for popups

Note:
  static class  
*/

var Popup = {
  
  /*
  Property: initialize
    sets initial values for a popup
  
  Arguments:
    sheetBaseURL - defines where requests for sheets will go, e.g '/overview/sheets' => '/overview/sheets/sheet_edit'
  */
  

  initialize: function(sheetBaseURL) {
    this.popup = $('popup').setOpacity(0);
    this.sheetBaseURL = sheetBaseURL;
    
    this.openCloseEffect = new Fx.Style(this.popup, 'opacity', {
      duration: 500,
      transition: Fx.Transitions.Quart.easeInOut,
      onComplete: function() {
      	$('overlay').setStyle('height', window.getInnerDimensions().height).toggle();
      }
    });
  },
  
  /*
  Property: open
    requests a sheet; animates the appearance of the requested sheet
    
  Arguments:
    path - the URL for the request
    product - optional, the HTML element that represents the product you have clicked on  
  */
  
  open: function(path, product) { //bound to event object
       
    if (product) this.activeProduct = $(product);
    var sheetsRequest = new Ajax(path, { 
      method: 'GET', 
      onComplete: this.afterOpen.bind(this),
      evalScripts: true
    });
    sheetsRequest.request();
  },
  
  /*
  Property: switchTo
    requests a sheet; unlike open it doesn't animate the appearance. just switches to another popup
    
  Arguments:
    path - the URL for the request
    product - optional, the HTML element that represents the product you have clicked on  
  */
  
  switchTo: function(path, product) { //bound to event object
    if (product) this.activeProduct = $(product);
    that=this;
    var sheetsRequest = new Ajax(path, { 
      method: 'GET', 
      onComplete: 
          this.afterSwitchTo.bind(this),
      evalScripts: true
    });
    sheetsRequest.request();
  },
  
  /*
  Property: checkForResize
    checks if a popup needs to be resized to fit its content
  
  Arguments:
    forceReset - optional, boolean, forces a resize  
  */

  checkForResize: function(forceReset,minHeight,windowClosed) {
    var pelement = $('sheets').getElement('div.active');
    var cols = pelement.getElements('div');//".sheet_col');
    var maxval=0;
    var maxelem={};  
    var biggerCols = cols.filter(function(col) {    
      if ((col.isVisibleChild($(pelement))) && ((col.offsetTop+Math.max(col.offsetHeight,30)) > maxval)) {
      //if ((col.isVisible()) && ((col.offsetTop+Math.max(col.offsetHeight,30)) > maxval)) {
        maxval=col.offsetTop+col.offsetHeight;
        maxelem=col;
        return true;
      }
      return false;
    });
   
    if (maxelem)
      this.resizeContent(maxelem, forceReset, minHeight || 420,windowClosed || false);
  },

  /*
  Property: resizeContent
    animates the resize of a popup
  
  Arguments:
    biggestCol - tallest HTML div element contained in the popup; usually this is an element which doesn't fit in
  */

  resizeContent: function(biggestCol, forceReset,minHeight,windowClosed) {
    var content = this.popup.getElement('div.content');
    var activeSheet = $('sheets').getElement('div.active');
    var bottom = this.popup.getElement('div.bottom');
    var _height = Math.max(biggestCol.offsetTop+Math.max(biggestCol.offsetHeight,30),minHeight)
    if (window.ie) {
    	content.setStyle('height', _height );
      activeSheet.setStyle('height', _height );
      bottom.setStyle('top', _height + 43 );  
      
    }
    else {
      [content, activeSheet].each(function(div) {
        div.resizeFx = new Fx.Style(div, 'height');
      });
      content.resizeFx.start(_height - 40); //.chain(function () { 
      activeSheet.resizeFx.start(_height - 40);
      //});  
    }
    
    if(!windowClosed)  {
        (function() {
          this.activateDocumentOverflow(forceReset);
        }.bind(this)).delay(500);
    }
  },
  
  /*
  Property: activateDocumentOverflow
    checks if a popup exceeds page real estate and activates the default disabled overflow of the html element
    
  Arguments:
    forceReset - optional, boolean, forces a deactivation of the document overflow
  */
  
  activateDocumentOverflow: function(forceReset) {
    var shouldActivate = (this.popup.offsetHeight >= window.getInnerDimensions().height); 
    
    if (shouldActivate) {
      $$('html')[0].setStyle('overflow', 'auto');
      $('container').setStyle('overflow', 'hidden');  
    }
    else {
//      if (!window.ie6) $$('html')[0].setStyle('overflow', 'hidden');
//      $('container').setStyle('overflow', 'auto');
    }
    window.scrollTo(0, 0);
  },
  
  /*
  Property: afterOpen
    callback method which fires when a request for a sheet was successful
  
  Arguments:
    response - the requests response object, containing HTML for a sheet
  */

  afterOpen: function(response) {
    $('sheets_wrapper').setHTML(response);
    
    this.sheetContainer = $('sheets');
    this.sheets         = $$('div.sheet');
    this.activeSheet    = this.sheets[0];
    
    this.scrollSheetEffect = new Fx.Style(this.sheetContainer, 'margin-left', {
      duration: 500,
      transition: Fx.Transitions.Circ.easeOut,
      onComplete: function() {
        this.checkForResize();
      }.bind(this),
      onAfterIncrease: (window.webkit419 ? document.redraw : Class.empty)
    }).start(1);
    this.openCloseEffect.start(1);
    this.sheets.each(function(sheet) {
      if (!sheet.hasClass('active') && !sheet.hasClass('preloaded')) sheet.setStyle('width', 0);
    });
    
    this.fireOnInitialize(this.activeSheet);
    this.fireOnActivate(this.activeSheet);
  },
  
  /*
  Property: afterSwitchTo
    callback method which fires when a request for a sheet/popup was successful when switching between sheets
  
  Arguments:
    response - the requests response object, containing HTML for a sheet
  */

  afterSwitchTo: function(response) {
    $('sheets_wrapper').setHTML(response);
    
    this.sheetContainer = $('sheets');
    this.sheets         = $$('div.sheet');
    this.activeSheet    = this.sheets[0];
    
    this.sheets.each(function(sheet) {
      if (!sheet.hasClass('active') && !sheet.hasClass('preloaded')) sheet.setStyle('width', 0);
    });
    
    this.fireOnInitialize(this.activeSheet);
    this.fireOnActivate(this.activeSheet);
    
    (function() {this.checkForResize();}.bind(this)).delay(500);
  },
  
  /*
  Property: close
    animates the disappearance of the current popup
  */

  close: function() {
    this.checkForResize(true,null,true); //forces reset of overflow attributes
    // Hide textarea elements before closing the Popup to prevent FireFox misdrawing scroll bars
    textareaContainer = $$('div.form_section textarea');
    textareaContainer.each(function(textarea){
       textarea.hide();
    });
    // Hide ul elements (there are some that have overflow: auto) and the same scroll bar misdrawing problem
    ulContainer = $$('div.sheet_col ul');
    ulContainer.each(function(ul){
       ul.hide();
    });
    
    $$('html')[0].scrollTop=0;
    $$('html')[0].setStyle('overflow', 'hidden');
    $('container').style.overflow = 'auto';
    this.fireOnDeactivate(this.activeSheet);  
    this.openCloseEffect.start(0);
  },
  
  /*
  Property: scrollToSheet
    animates the scroll to a specific sheet; requests the contents of that specific sheet
  
  Arguments:
    sheet - the DOM id of the sheet to scroll to
    requestOptions - optional, an object containing request options  
  */
	scrollToSheet: function(sheet, requestOptions) {
		initLoading();
		sheet = $(sheet);
		this.loadSheet(sheet, function() {
			this.fireOnDeactivate(this.activeSheet);
			this.setActiveSheet(sheet);
			this.fireOnInitialize(this.activeSheet);
			this.fireOnActivate(this.activeSheet);

			var distance = this.getDistanceToSheet(sheet);
			this.scrollSheetEffect.start(distance);
		}.bind(this), requestOptions);
	},

  /*
  Property: scrollToSheetLocally
    animates the scroll to a specific sheet; assumes this sheet's content is already present
  
  Arguments:
    sheet - the DOM id of the sheet to scroll to  
  */
  
  scrollToSheetLocally: function(sheet) {
    sheet = $(sheet);
    this.fireOnDeactivate(this.activeSheet);
    
    this.setActiveSheet(sheet);
    this.fireOnActivate(this.activeSheet);
    var distance = this.getDistanceToSheet(sheet);
    this.scrollSheetEffect.start(distance);
  },  
  
  /*
  Property: getDistanceToSheet
    calculates the horizontal distance in px from the active sheet to another specific sheet
  
  Arguments:
    sheet - the DOM id of a specific sheet
  
  Returns:
    the horizontal distance in px from the active sheet to another sheet
  */
  
  getDistanceToSheet: function(sheet) {
    var distance = 0;    
    this.sheets.indexOf(sheet).times(function(i) {
      distance -= this.sheets[i].getWidth();
    }.bind(this));
    return distance;
  },
  
  /*
  Property: loadSheet
    handles requests for sheets; provides callbacks
  
  Arguments:
    sheet - DOM id of the sheet container to update
    onSheetLoaded - callback function, called when sheet HTML is completely present
    options - optional, object containing request specific options
  */
  
  loadSheet: function(sheet, onSheetLoaded, options) {
    sheet = $(sheet);
    
    if (options && options.data) {
      options = {
        data: options.data,
        method: 'post'
      } 
    } else {
      options = {
        data: null,
        method: 'get'
      }
    }
    
    new Ajax(this.sheetBaseURL + sheet.id, {
      onComplete: function(response) {
        sheet.setHTML(response); //empty sheets width: 0, filled sheets: 748px
        onSheetLoaded();       
      }.bind(this),
      data: options.data,
      evalScripts: true,
      method: options.method
    }).request();
  },
  
  /*
  Property: setActiveSheet
    sets the active sheet; sets initial styles
  
  Arguments:
    sheet - HTML element which represents the sheet
  */
  
  setActiveSheet: function(sheet) {
    this.activeSheet.removeClass('active');
    this.activeSheet = sheet.addClass('active').setStyle('width', 748);
  },
  
  /*
  Property: fireOnInitialize
    callback function, called right after a new sheet gets initialized
  
  Arguments:
    sheet - HTML element which represents the sheet
  */
  
  fireOnInitialize: function(sheet) {
    if(Sheets[sheet.id] && Sheets[sheet.id].onInitialize)
      Sheets[sheet.id].onInitialize.bind(Sheets[sheet.id])();
  },  
  
  /*
  Property: fireOnActivate
    callback function, called right after a new sheet gets activated
  
  Arguments:
    sheet - HTML element which represents the sheet
  */
  
	fireOnActivate: function(sheet) {    
		$ES('.overflow-hidden',sheet).each(function(el) {
			el.removeClass('overflow-hidden');
			el.addClass('overflow-auto');
			el.setStyle('overflow','auto');
		});
		if(Sheets[sheet.id] && Sheets[sheet.id].onActivate){
			Sheets[sheet.id].onActivate.bind(Sheets[sheet.id])();
		}
		loadingFinished();
	},
  
  /*
  Property: fireOnDeactivate
    callback function, called right after a sheet gets deactivated, e.g. when scrolling to another sheet
  
  Arguments:
    sheet - HTML element which represents the sheet
  */
  
  fireOnDeactivate: function(sheet) {
    
    // FF2-win bug - change overflow: auto to overflow: hidden
    $ES('.overflow-auto',sheet).each(function(el) {
      el.removeClass('overflow-auto');
      el.addClass('overflow-hidden');
      el.setStyle('overflow','hidden');
    });
    
    if(Sheets[sheet.id] && Sheets[sheet.id].onDeactivate)
      Sheets[sheet.id].onDeactivate.bind(Sheets[sheet.id])();    
  }
}
