/*
 * jquery.box 1.1
 *
 * simple thickbox to display infos, external contents
 * or turn list of images into a gallery.
 *
 * initialize like this:
 * $('#selector').box( {options} )
 *
 * start like this:
 * $.box.open( $('#selector') ); // or
 * $.box.open( 'MyElementID' );
 *
 * start ajax content like this:
 * $.box.open( $('#selector'), 'http://www.example.de?foo=bar' );
 *
 * start gallery from outside like this (or by thumbnail-click):
 * $.box.open( $('#selector'), [int image index] );
 *
 * extra-button to close like this:
 * $.box.close( $('#selector') );
 *
 * while loading, overlay-close is deactivated, forced close like this
 * $.box.close( $('#selector'), true );
 *
 * @author: joachim wendenburg, kgde@wendenburg.de
 *
 * modified:    17.03.2010
 * item:        open, iframe also as second param it option iframe is true
 *
 * modified:    25.03.2010
 * item:        add curr_obj_check to make sure there are not different
 *              jquery.boxes running at one time
 *
 */
 (function($){

	$.fn.box = function(options) {

        var defaults = {
            display: 'none',
            width: '300px',
            height: '200px',
            zindex: '3000',
            onclose: false,
            beforeopen: false,
            beforeclose: false,
            txtback: '&lt;',
            txtnext: '&gt;',
            txtclose: 'x',
            txttitle: 'Info',
            dpltitle: true,
            iframe: false,      // false or url/true and url as second open-param
            ajax: false,        // false or true, pass url as second opening param
            json: false,        // false or function to handle responde
            iebugsrc: '/common/img/leer.gif',
            gallery: false,
            boxborder: "",
            display: "none",
            waitonly: false,    // false or true if you need overlay only
            clickable: true,    // false if overlay must not be clickeable
            closealways:  true  // new box always closes the past one (if different objects!)
        }

        return this.each(function() {

            // handle earlier versions
            if(typeof options === "string") {
                switch(options) {
                    case "close":
                        $.box.close( $(this) );
                        break;
                    case "gallery":
                        $.box.open( $(this), arguments[1] );
                        break;
                    default:
                        $.box.open( $(this) );
                }
                return;
            }

            defaults.display =  $(this).css('display');
            $(this).data('box', $.extend(defaults, options));
            $.box.init(this);
        });
	};

    jQuery.box = {

        // some html strings
        div:        "<div><\/div>",
        pspan_o:    "<p><span>",
        pspan_c:    "<\/span><\/p>",

        // store past el here
        curr_obj:   false,

        /**
         * initialize some box vars and preload view image if gallery
         * @params: element
         * @author: joachim wendenburg
         */
        init: function(el) {
            el                  =  this.get_el(el);
            el.opt              =  $(el).data('box');
            el.opt.box_window   =  false;
            el.opt.box_overlay  =  false;
            el.opt.viewpreload  =  false;
            el.opt.closable     =  true;

            if(el.opt.gallery) {
                el.opt.gallery =  this.preload(el);
            }
        },

        /**
         * loop all gallery thumbnails
         * get parent a-tag's href as original image source
         * preload original image
         * @params: element
         * @author: joachim wendenburg
         */
        preload: function(el) {
            el                  =  this.get_el(el);
            var view, tmp =  [];
            $(el).find("img").each(function(i) {
                view            =  new Image;
                view.src        =  $(this).parents('a').attr("href");
                view.title      =  this.title;
                view.index      =  i;
                view.load       =  0;
                this.index      =  tmp.length;
                $(this).click(function() {
                    $.box.open(el, this.index);
                });
                $(this).parents('a').click(function() {
                    return false;
                });
                tmp.push({view: view});
            });
            return tmp;
        },

        /**
         * init box window depending on mode (default, ajax or gallery)
         * @params: element, optional ajax-url or image-index
         * @author: joachim wendenburg
         */
        open: function(el) {

            el      =  this.get_el(el);
            el.opt  =  $(el).data('box') || false;
            if (!el.opt) return;

            // check if there is an _other_ jquery.box object in use
            // do nothing if this must not be closed
            //
            if (!this.curr_obj_check(el)) return;

            // handle nervous clicks by blocking close until box fade-in is done
            el.opt.closable =  el.opt.waitonly? true : false;

            if (el.opt.beforeopen) {
                el.opt.beforeopen( $(el).get(0) );
            }

            this.overlay(el);
            if (el.opt.gallery) {
                if(typeof arguments[1] === "undefined") {
                    return false;
                }
                this.init_gallery(el, arguments[1]);

            } else if(el.opt.ajax) {
                if(typeof arguments[1] === "undefined") {
                    this.init_box(el);
                    return false;
                }
                this.init_ajax(el, arguments[1]);
            } else if(el.opt.json) {
                if(typeof arguments[1] === "undefined") {
                    this.init_box(el);
                    return false;
                }
                this.init_json(el, arguments[1]);
            } else if(el.opt.iframe) {
                if(typeof arguments[1] !== "undefined") {
                    el.opt.iframe =  arguments[1];
                }
                this.init_box(el);
            } else if(el.opt.waitonly) {
                return;
            } else {
                this.init_box(el);
            }
        },

        /**
         * create box window's html depending on settings
         * @params: element, optional ajax-url or image-index
         * @author: joachim wendenburg
         */
        init_box: function(el) {

            el      =  this.get_el(el);
            el.opt  =  $(el).data('box') || false;
            if (!el.opt) return;

            if (el.opt.box_window) {

                el.opt.box_window_past  =  el.opt.box_window;
                el.opt.box_window       =  false;

                $(el.opt.box_window_past).css('zIndex', (el.opt.zindex +1) ).fadeOut(function(){
                    $(el.opt.box_window_past).remove()
                });

            } else {
                // create a placeholder to remember origin positin within dom-tree
                el.opt.box_holder       =  $(this.div).css('display', 'none');
                $(el).before( $(el.opt.box_holder) );
            }

            // create box
            el.opt.box_window  =  $(this.div).appendTo(document.body).attr('id', 'box-window').css( {'zIndex':el.opt.zindex, 'display':'none', 'margin': '0'} );

            // customized border style
            if(el.opt.boxborder) {
                $(el.opt.box_window).css('border', el.opt.boxborder);
            }

            // gallery or default box?
            if(el.opt.gallery) {

                // create headerbar
                if(el.opt.dpltitle) {
                    var idx             =  (typeof arguments[1] !== "undefined")? arguments[1] : 0;
                    var view            =  el.opt.gallery[idx].view;
                    var image_next      =  (idx < el.opt.gallery.length -1)? idx +1 : 0;
                    var image_back      =  (idx > 0)? idx -1 : el.opt.gallery.length -1;

                    el.opt.box_header   =  $(this.div).appendTo(el.opt.box_window).attr('id', 'box-image-header');
                    el.opt.box_close    =  $(this.pspan_o + el.opt.txtclose + this.pspan_c).appendTo(el.opt.box_header).attr('id', 'box-close').click(function(){ $.box.close(el) });
                    el.opt.box_next     =  $(this.pspan_o + el.opt.txtnext + this.pspan_c).appendTo(el.opt.box_header).attr('id', 'box-next').click(function(){ $.box.init_gallery(el, image_next) });
                    el.opt.box_back     =  $(this.pspan_o + el.opt.txtback + this.pspan_c).appendTo(el.opt.box_header).attr('id', 'box-back').click(function(){ $.box.init_gallery(el, image_back) });
                }

                el.opt.box_content  =  $(this.div).appendTo(el.opt.box_window).attr('id', 'box-image-content');
                el.opt.box_image    =  $("<img />").appendTo(el.opt.box_content).attr( {src: view.src}).css({width: view.width + "px", height: view.height + "px"} );
                el.opt.box_title    =  $(this.div).appendTo(el.opt.box_content).attr('id', 'box-image-title').css( {width: view.width + "px"} ).html(view.title);

                el.opt.box_image.click(function() { $.box.init_gallery(el, image_next) });

            } else {

                // create headerbar
                if(el.opt.dpltitle) {
                    el.opt.box_header   =  $(this.div).appendTo(el.opt.box_window).attr('id', 'box-header');
                    el.opt.box_close    =  $(this.pspan_o + el.opt.txtclose + this.pspan_c).appendTo(el.opt.box_header).attr('id', 'box-close').click(function(){ $.box.close(el) });
                    el.opt.box_title    =  $("<h3>" + el.opt.txttitle + "</h3>").appendTo(el.opt.box_header).attr('id', 'box-title');
                }

                if(el.opt.width) {
                    $(el.opt.box_window).css('width', el.opt.width);
                }

                if (el.opt.iframe) {
                    el.opt.box_iframe =  $("<iframe border='0' frameborder='0'></iframe>").appendTo(el).attr({'id': 'box-iframe', 'src': el.opt.iframe}).css( {'height': el.opt.height} );
                }

                el.opt.box_content =  $(this.div).appendTo(el.opt.box_window).attr('id', 'box-content').css({'height': el.opt.height});
                $(el).appendTo(el.opt.box_content).show();

            }

            // move box to it's final position depending on it' size
            // reseize overlay in case boy is larger then page content
            //this.set_boxmargin(el);
            this.set_box_pos(el);
            this.overlay_size(el);

            $(el.opt.box_window).fadeIn(function(){
                $(el.opt.box_overlay).css('backgroundImage','none');
                el.opt.closable =  true;
            });
        },

        /**
         * check if image height is available to make sure view-image is complete
         * @params: element, image's index
         * @author: joachim wendenburg
         */
        init_gallery: function(el, idx) {

            el                  =  this.get_el(el);
            el.opt  =  $(el).data('box') || false;
            if (!el.opt) return;

            var view            =  el.opt.gallery[idx].view;
            clearTimeout(el.opt.viewpreload);
            el.opt.viewpreload  =  false;

            if (!view.height) {
                if(view.load < 30) {
                    view.load ++;
                    el.opt.viewpreload =  setTimeout(function(){ $.box.init_gallery(el, idx) }, 1000);
                } else {
                    alert("unavailable: " + view.src);
                }
                return;
            }
            // succsess, continue
            this.init_box(el, idx);
        },

        /**
         * load ajax data into html element
         * open box on response
         * @params: element, script url
         * @author: joachim wendenburg
         */
        init_ajax: function(el, url) {
            el =  this.get_el(el);
            $(el).load( url, function(){
                $.box.init_box(el);
            });
        },

        /**
         * get json while overlay appears
         * on response
         * call function stored in el.opt.json
         * open box
         * @params: element, script url
         * @author: joachim wendenburg
         */
        init_json: function(el, url) {

            el      =  this.get_el(el);
            el.opt  =  $(el).data('box') || false;
            if (!el.opt || typeof el.opt.json !== "function") return;

            $.getJSON( url, function(response) {
                el.opt.json( $(el).get(0), response );
                $.box.init_box(el);
            });
        },

        /**
         * create overlay and append to dom
         * @params: element
         * @author: joachim wendenburg
         */
        overlay: function(el) {

            el                  =  this.get_el(el);
            el.opt  =  $(el).data('box') || false;
            if (!el.opt) return;

            if (el.opt.box_overlay) {
                return false;
            }
            el.opt.box_overlay =  $(this.div).appendTo(document.body).attr('id', 'box-overlay').css('zIndex', (el.opt.zindex -3));
            if (el.opt.clickable) {
                $(el.opt.box_overlay).click(function(){ $.box.close(el); });
            }
            this.ie6fix(el.opt.box_overlay, el.opt.iebugsrc);
            this.overlay_size(el);
        },

        overlay_size: function(el) {

            el      =  this.get_el(el);
            el.opt  =  $(el).data('box') || false;
            if (!el.opt) return;

            var overlay_height  =  ($.browser.msie && $.browser.version < 7)? "height" : "minHeight";
            $(el.opt.box_overlay).css(overlay_height, $.box.client().height + 'px').css('backgroundPosition', '50% ' + ($(window).height()/2 + $.box.client().scrolltop -50) + 'px');
        },

        /**
         * close box and overlay, restore dom if neccessary
         * @params: element
         * @author: joachim wendenburg
         */
        close: function(el) {

            var forceclose  =  (typeof arguments[1] !== "undefined")? arguments[1] : false;
            el              =  this.get_el(el);
            el.opt          =  $(el).data('box') || false;
            
            // do nothing if no options at all, overlay already closed or not closeable unless forceclose
            if (
                !el.opt ||
                !el.opt.box_overlay ||
                (!el.opt.closable && !forceclose)
            ) return;
            
            // callback before closing?
            if (el.opt.beforeclose) {
                el.opt.beforeclose( $(el).get(0) );
            }

            // not only overlay was in use
            if(!el.opt.waitonly) {

                // gallery or default box?
                if(el.opt.gallery) {

                    // cancel a running view-preload
                    clearTimeout(el.opt.viewpreload);
                    el.opt.viewpreload  =  false;

                } else {

                    // remove iframe
                    if (el.opt.iframe) {
                        $(el.opt.box_iframe).remove();
                    }

                    // restore original display
                    if (el.opt.display == "none") {
                        $(el).hide();
                    }

                    // restore original dom-tree if window
                    if(el.opt.box_window) {
                        $(el.opt.box_holder).before($(el));
                        $(el.opt.box_holder).remove();
                    }
                }

                if(el.opt.box_window) {
                    $(el.opt.box_window).remove();
                    el.opt.box_window   =  false;
                }
            }

            $(el.opt.box_overlay).remove();
            el.opt.box_overlay  =  false;

            // callback after closing?
            if (el.opt.onclose) {
                el.opt.onclose( $(el).get(0) );
            }

            // empty flag for current jquery.box-object
            this.curr_obj =  false;
        },

        /**
         * set position depending on window's and box's dimension
         * @params: element
         * @author: joachim wendenburg
         */
        set_box_pos: function(el) {

            el      =  this.get_el(el);
            el.opt  =  $(el).data('box') || false;
            if (!el.opt || !el.opt.box_window) return;

            var left    =  ($(window).width()/2 - $(el.opt.box_window).outerWidth()/2 + $.box.client().scrollleft)  + "px";
            var top     =  ($(window).height()/2 - $(el.opt.box_window).outerHeight()/2 + $.box.client().scrolltop) + "px";
            if($(window).height() > $(el.opt.box_window).outerHeight()) {
                $(el.opt.box_window).css("top", top).css("left", left);
            } else {
                $(el.opt.box_window).css("top", 0).css("left", left);
            }
        },

        /**
         * check if there is already an _other_ jquery.box object in use at this time
         * if it differs from the current object close it unless option closealways is false
         * set flag for current jquery.box object that is in use right now
         * @params: element
         * @author: joachim wendenburg
         */
        curr_obj_check: function(el) {

            var ret =  true;
            el      =  this.get_el(el);
            if(this.curr_obj && this.curr_obj !== el) {
            
                this.curr_obj.opt  =  $(this.curr_obj).data('box') || false;
                if (!this.curr_obj.opt) return true;
                
                if (this.curr_obj.opt.closealways) {
                    this.close(this.curr_obj, true);
                    this.curr_obj   =  el;
                    ret             =  true;
                } else {
                    ret             =  false;
                }
            } else {
                this.curr_obj       =  el;
            }
            return ret;
        },

        /**
         * get some infos about browser's dimensions
         * @params: element
         * @author: joachim wendenburg
         */
        client: function() {

            // get some data about the client
            var height, width;
            var doc_el  =  document.documentElement;
            var doc_bd  =  document.body;

            var scrolltop   =  Math.max(doc_el.scrollTop, doc_bd.scrollTop);
            var scrollleft  =  Math.max(doc_el.scrollLeft, doc_bd.scrollLeft);
            if ($.browser.msie && $.browser.version < 7) {
                var scrollHeight    =  Math.max(doc_el.scrollHeight, doc_bd.scrollHeight);
                var scrollWidth     =  Math.max(doc_el.scrollWidth, doc_bd.scrollWidth);
                var offsetHeight    =  Math.max(doc_el.offsetHeight, doc_bd.offsetHeight);
                var offsetWidth     =  Math.max(doc_el.offsetWidth, doc_bd.offsetWidth);
                height              =  (scrollHeight < offsetHeight)?   $(window).height()  : scrollHeight;
                width               =  (scrollWidth < offsetWidth)?     $(window).width()   : scrollWidth;
            } else {
                height   =  $(document).height();
                width    =  $(document).width();
            }
            return {width:width, height:height, scrolltop: scrolltop, scrollleft: scrollleft}
        },

        /**
         * check if ob or string
         * @params: element
         * @author: joachim wendenburg
         */
        get_el: function(el) {
            return (typeof el === "string")? $("#" + el) : $(el);
        },

        /**
         * append iframe for ie6 to cover selects etc.
         * @params: element
         * @author: joachim wendenburg
         */
        ie6fix: function(parent, src) {
            if (!($.browser.msie && $.browser.version < 7) || !src) {
                return;
            }
            var iframe          =  document.createElement("iframe");
            iframe.src          =  src;
            iframe.style.height =  "100%";
            iframe.style.width  =  "100%";
            iframe.style.filter =  "alpha(opacity=0)";
            $(parent).append(iframe);
            iframe.contentWindow.document.onclick =  function(){
                iframe.parentNode.click();
            }
        }
    }
})(jQuery);

