/*
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');
        this.popup.setOpacity(0).hide();
        this.overlay = $('overlay');
        this.overlay.setOpacity(0);
        this.sheetBaseURL = sheetBaseURL;
        this.curSheet = null;
        this.sheetWidth = null;
        this.autoResize = true;
        this.visible = false;
        this.onClose = null;
        this.slideshow = null;

        // Adding click event for close popup button
        this.closeBtn = this.popup.getElement('a.close_popup');

        this.openCloseEffect = new Fx.Tween(this.popup, {
            duration: 0,
            transition: Fx.Transitions.Full,
            onStart: function () {
                if (!this.overlay.isVisible()) {
                    $('overlay').show();
                    $('popup').setStyle('margin-left', ($('popup').getWidth() / 2) * (-1));
                    $('popup').setStyle('margin-top', ($('popup').getHeight() / 2) * (-1));
                    /*$('sheets').setStyle('width', $('popup').getWidth());*/
                    /*margin: -320px 0 0 -417px;*/
                    new Fx.Tween(this.overlay, {
                        duration: 0,
                        transition: Fx.Transitions.Quart.easeInOut
                    }).start('opacity', .5);
                } else {
                    new Fx.Tween(this.overlay, {
                        duration: 500,
                        transition: Fx.Transitions.Quart.easeInOut,
                        onComplete: function () { this.element.hide(); }
                    }).start('opacity', 0);
                }
            } .bind(this)
        });
    },

    /*
    Property: open
    requests a sheet; animates the appearance of the requested sheet
    
    Arguments:
    path - the URL for the request
    sheetWidth - optional, the width for the popup
    */
    open: function (path, sheetWidth, onClose) { //bound to event object                        
        if (this.visible)
            return;

        this.visible = true;

        if (sheetWidth != null)
            this.sheetWidth = sheetWidth;

        if (onClose != null)
            this.onClose = onClose;

        new Request({
            url: path,
            method: 'GET',
            onComplete: this.afterOpen.bind(this),
            evalScripts: true,
            data: { 'p': getUniqueTime() }
        }).send();

        this.popup.getElement('a.close_popup').addEvents({
            'click': function (event) {
                event.stop();
                this.close();
            } .bindWithEvent(this)
        });
    },

    /*
    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);
        new Request({
            url: path,
            method: 'GET',
            onComplete: this.afterSwitchTo.bind(this),
            evalScripts: true
        }).send();
    },

    enableResizeEvent: function () {
        this.autoResize = true;
    },

    disableResizeEvent: function () {
        this.autoResize = 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 (forceReset) {
        if (this.autoResize) {
            var content = this.popup.getElement('div.content');
            if (this.curSheet == null) {
                this.curSheet = content.getElement('div.active');
            }
            var _width = this.curSheet.getWidth();
            var _height = this.curSheet.getHeight();
            _width += 40;
            _height += 45;
            if (forceReset) {
                content.setStyle('width', _width);
                content.setStyle('height', _height);
            }
            else {
                new Fx.Tween(content, {
                    duration: 300,
                    onComplete: function () {
                        content.setStyle('width', _width);
                    } .bind(this)
                }).start('width', _width);
                new Fx.Tween($('popup'), {
                    duration: 300,
                    onComplete: function () {
                        $('popup').setStyle('width', _width);
                    } .bind(this)
                }).start('width', _width);
                new Fx.Tween(content, {
                    duration: 300,
                    onComplete: function () {
                        content.setStyle('height', _height);
                    } .bind(this)
                }).start('height', _height);
            }

            var containerWidth = window.getSize().x;
            var newWidth = _width;
            if (newWidth > containerWidth)
                newWidth = containerWidth;
            new Fx.Tween('popup').start('margin-left', (newWidth / 2) * (-1));
            //$('popup').get('tween', {property: 'margin-left', duration: '300'}).start((widthSheet/2) * (-1));

            var containerHeight = window.getSize().y;
            var newHeight = _height;
            if (newHeight > containerHeight)
                newHeight = containerHeight;

            new Fx.Tween('popup').start('margin-top', (newHeight / 2) * (-1));
            //$('popup').get('tween', {property: 'margin-top', duration: '300'}).start((_height/2) * (-1));
        }
    },

    /*
    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').set('html', response);

        var content = this.popup.getElement('div.content');
        this.sheetContainer = $('sheets');
        this.sheets = $$('div.sheet');
        this.activeSheet = $('sheets').getElement('div.active');
        this.curSheet = this.activeSheet;

        if (this.sheetWidth != null) {
            this.curSheet.setStyle('width', this.sheetWidth);
        }

        this.popup.show();
        this.scrollSheetEffect = new Fx.Tween(this.sheetContainer, {
            duration: 500,
            transition: Fx.Transitions.Circ.easeOut,
            onComplete: function () {
                this.resizeContent();
            } .bind(this)
        }).start('margin-left', 1);
        this.openCloseEffect.start('opacity', 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').set('html', response);

        this.sheetContainer = $('sheets');
        this.sheets = $$('div.sheet');
        this.activeSheet = $('sheets').getElement('div.active');

        this.sheets.each(function (sheet) {
            if (!sheet.hasClass('active') && !sheet.hasClass('preloaded')) sheet.setStyle('width', 0);
        });

        this.fireOnInitialize(this.activeSheet);
        this.fireOnActivate(this.activeSheet);

        this.resizeContent();
    },

    /*
    Property: close
    animates the disappearance of the current popup
    */

    close: function () {
        $(document.body).getElements('.custom_tip').setStyle('visibility', 'hidden');

        /*
        var containerObj = $('container');
        if (containerObj != null && containerObj != undefined && $('allDoc')) {
        containerObj.setStyle('overflow', 'auto');
        var allObj = $('allDoc');
        allObj.scrollTop = 0;
        allObj.setStyle('overflow', 'hidden');
        }
        */

        // 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();
        });

        this.fireOnDeactivate(this.activeSheet);
        this.openCloseEffect.start('opacity', 0);

        //document.removeEvents('keyup');
        this.popup.getElement('a.close_popup').removeEvents('click');

        this.visible = false;

        /*
        var containerObj = $('container');
        if (containerObj != null && containerObj != undefined && $('allDoc')) {
        containerObj.setStyle('overflow', 'auto');
        var allObj = $('allDoc');
        //allObj.scrollTop = 0;
        document.body.scrollTop = 0; //webkit browsers !
        //allObj.setStyle('overflow', 'hidden');			
        }
        */

        $(document.body).getElements('.autocompleter-choices').setStyle('visibility', 'hidden');

        // close all sheets
        this.sheets.each(function (sheet) {
            sheet.innerHTML = "";
        });

        // scrollbar-fix: resize the popup to the content
        var content = this.popup.getElement('div.content');
        var containerWidth = window.getSize().x - 40;
        if (content.getSize().x > containerWidth) {
            content.setStyle('width', containerWidth);
            $('popup').setStyle('width', containerWidth);
        }
        var containerHeight = window.getSize().y - 45;
        if (content.getSize().y > containerHeight)
            content.setStyle('height', containerHeight);

        if (this.slideshow != null) {
            this.slideshow.destroy();
            this.slideshow == null;
        }

        if (this.onClose != null)
            this.onClose();
    },


    /**
    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, onSheetScrolled, sheetWidth, baseURL) {
        var sheetName = sheet;
        sheet = $(sheet);
        this.curSheet = sheet;
        if (sheetWidth != null)
            this.sheetWidth = sheetWidth;

        if (sheetName.contains('/'))
            this.sheetBaseURL = "";

        if (baseURL != null)
            this.sheetBaseURL = baseURL;

        if (sheet == null || sheet == undefined) {
            alert("sheet with id: '" + sheetName + "' not found in scrollToSheet -> popup.js");
            return;
        }

        this.loadSheet(sheet, function () {
            this.fireOnDeactivate(this.activeSheet);

            this.setActiveSheet(sheet);

            this.fireOnInitialize(this.activeSheet);
            this.fireOnActivate(this.activeSheet);

            var oldsheet = this.activeSheet;
            this.scrollSheetEffect.start('margin-left', this.getDistanceToSheet(sheet));
            if (onSheetScrolled != null)
                onSheetScrolled();
        } .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, onSheetScrolled, sheetWidth) {
        sheet = $(sheet);
        this.curSheet = sheet;
        this.fireOnDeactivate(this.activeSheet);

        if (sheetWidth != null)
            this.sheetWidth = sheetWidth;

        this.setActiveSheet(sheet);
        this.fireOnActivate(this.activeSheet);

        this.scrollSheetEffect = new Fx.Tween(this.sheetContainer, {
            duration: 500,
            transition: Fx.Transitions.Circ.easeOut,
            onComplete: function () {
                this.resizeContent();
                if (onSheetScrolled != null)
                    onSheetScrolled();
            } .bind(this)
        }).start('margin-left', this.getDistanceToSheet(sheet));
    },

    /*
    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) {
            if (this.sheets[i].getFirst())
                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 Request({
            url: this.sheetBaseURL + sheet.id + ".aspx",
            onComplete: function (response) {
                sheet.set('html', response);
                if (onSheetLoaded != null)
                    onSheetLoaded();
            } .bind(this),
            evalScripts: true,
            method: options.method
        }).post(options.data);
    },

    /*
    Property: saveForm
    posts a HTML form; provides callbacks
  
    Arguments:
    popupForm - DOM id of the form element to post
    options - optional, object containing request specific options e.g.: onSuccess
    */

    saveForm: function (popupForm, options) {
        var form = $(popupForm);
        var options = options || {};
        var req = new Request.HTML({
            url: form.getProperty('action'),
            method: 'post',
            onSuccess: function () {
                if (options.onSuccess)
                    options.onSuccess(req.response.text);
            }
        }).post(form);
    },

    saveFormWithJSON: function (popupForm, options) {
        var form = $(popupForm);
        var options = options || {};
        var req = new Request.JSON({
            url: form.getProperty('action'),
            method: 'post',
            onSuccess: function (responseJSON) {
                if (options.onSuccess)
                    options.onSuccess(responseJSON);
            }
        }).post(form);
    },

    /*
    Property: setActiveSheet
    sets the active sheet; sets initial styles
  
    Arguments:
    sheet - HTML element which represents the sheet
    */

    setActiveSheet: function (activesheet) {
        this.sheets.each(function (sheet) {
            if (sheet != activesheet) {
                var form = sheet.getElement("form");
                if (form) form.setProperty('action', '');
            }
        });
        this.activeSheet.removeClass('active');
        if (this.sheetWidth != null)
            this.activeSheet = activesheet.addClass('active').setStyle('width', this.sheetWidth);
        else if (this.curSheet.getWidth() == 0 || this.curSheet.getWidth() <= 748)
            this.activeSheet = activesheet.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) {
        if (Sheets[sheet.id] && Sheets[sheet.id].onActivate)
            Sheets[sheet.id].onActivate.bind(Sheets[sheet.id])();
    },

    /*
    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) {
        if (Sheets[sheet.id] && Sheets[sheet.id].onDeactivate)
            Sheets[sheet.id].onDeactivate.bind(Sheets[sheet.id])();
    }
};

