﻿/*
* jQuery Box Plugins v1.0
* Date: 2009-09-09 15:17
* Revision: 1.0.0
*/
(function($) {

    var PROP_NAME = 'box';
    // Define the login box control.
    function Box(options) {
        // Default setting.
        this._defaults = {
            // The trigger link of box.
            trigger: "",
            // The position of box.
            position: "center",
            accord: "",
            hideAllButThis: true,
            //The UI URL of box.
            url: "",
            render: null,
            boxClassName: "",
            showAnim: "show",
            duration: 600,
            zIndex: 1000,
            showEvent: "click",
            onShow: null,
            onLoad: null,
            onHide: null,
            onDestroyBox: null
        };
        // The css name of box.
        this.markerClassName = "wynnBox";
        // Flag of the box UI.
        this.loadComlete = false;
        this.box = $("<div></div>");
        this.isShown = false;
        this.target = null;
    }
    $.extend(Box.prototype, {
        _get: function(prop) {
            return this._defaults[prop];
        },
        // The function of render view, render the view and diplay it.
        _renderHTML: function() {
            var self = this;
            var onLoad = this._get("onLoad");
            var url = this._get("url");
            var param = this._get("param");
            var boxDivClass = this._get("boxClassName");
            var process = function() {
                if ($.browser.msie && parseInt($.browser.version, 10) < 7) {
                    self.box.wrapInner("<div class='" + boxDivClass + "'></div>").append("<iframe class='maskIframe'></iframe>");
                } else {
                    self.box.addClass(boxDivClass);
                }

                if ($.isFunction(onLoad)) {
                    onLoad.apply(null, [self.box, self]);
                }

                self.loadComlete = true;
                self._showBox();
            };
            // Render the view.
            if (url) {
                this.box.load(url, param || {}, function() {
                    process();
                });
                return this;
            }
            var render = this._get("render");
            if (render) {
                this.box.append(render.html());
                render.empty();
                process();
            }
            return this;
        },
        // show the box use fade in effect.
        _showBox: function() {
            var showAnim = this._get('showAnim') || 'show';
            var duration = this._get('duration');
            var onShow = this._get("onShow");
            var hideAllButThis = this._get("hideAllButThis");
            var self = this;
            var postProcess = function() {
                if ($.isFunction(onShow)) {
                    onShow.apply(null, [self.box]);  // trigger custom callback
                }
                self.isShown = true;
            };

            if (hideAllButThis) {
                $.box.hideOtherBoxes(self);
            }

            if ($.effects && $.effects[showAnim]) {
                this.position().show(showAnim, this._get('showOptions'), duration, postProcess);
            } else {
                this.position()[showAnim](duration, postProcess);
            }
            return false;
        },

        // hide the box.
        _hideBox: function() {
            var showAnim = this._get('showAnim') || 'show';
            var duration = this._get('duration');
            var onHide = this._get("onHide");
            var self = this;
            var postProcess = function() {
                if ($.isFunction(onHide)) {
                    onHide.apply(null, [self.box]);
                }
                self.isShown = false;
            };
            if ($.effects && $.effects[showAnim]) {
                this.position().hide(showAnim, this._get('showOptions'), duration, postProcess);
            } else {
                this.position()[(duration == '' ? 'hide' : (showAnim == 'slideDown' ? 'slideUp' :
                (showAnim == 'fadeIn' ? 'fadeOut' : 'hide')))](duration, postProcess);
            }

        },
        _createBox: function(target, inst) {
            var boxDiv = this.box;
            if (boxDiv.hasClass(this.markerClassName))
                return;

            boxDiv.addClass(this.markerClassName).appendTo(document.body).css({
                position: 'absolute',
                overflow: 'hidden',
                zIndex: this._get("zIndex"),
                display: 'none'
            });

            // Add the box into the hash.
            $.box.Hash.push(this);
            $.data(target, PROP_NAME, inst);
            this._enableBox(target);
        },
        // init box, set the box position, event and show it.
        _initBox: function(target, settings) {
            var inst = $.extend(this._defaults, settings || {});
            this.target = $(target);
            this._createBox(target, inst);
            $(target).data("boxInstance", this);
        },
        // Destroy the box.
        _destroyBox: function(target) {
            var self = this;
            this._disableBox(target);
            // Render the view.
            var render = this._get("render");
            var boxDivClass = this._get("boxClassName");
            if (render) {
                var html;
                if ($.browser.msie && parseInt($.browser.version, 10) < 7) {
                    html = this.box.find("div." + boxDivClass);
                } else {
                    html = this.box;
                }
                render.append(html.html());
            }
            this.box.remove();
            $(target).removeData(PROP_NAME).removeData("boxInstance");

            $.box.Hash = $.grep($.box.Hash, function(index, elem) {
                return elem != self;
            });

            return this;
        },
        _disableBox: function(target) {
            this._hideBox();
            var eventName = this._get("showEvent");
            $(target).unbind(eventName);
            // Hide the box when click other area.
            $(document).unbind("click").css("cursor", "");
            // Hide the box when click close trigger
            if ($.trim(this._get("trigger")) !== "" && $(this._get("trigger")).size() > 0) {
                $(this._get("trigger")).unbind("click");
            }
        },
        _enableBox: function(target) {
            var self = this;
            var boxCSS = this.markerClassName;
            var eventName = this._get("showEvent");
            $(target).bind(eventName, function() {
                if (!self.loadComlete) {
                    self._renderHTML();
                } else {
                    self._showBox();
                }
                return false;
            }).css("cursor", "pointer");
            // Hide the box when click other area.
            $(document).bind("click", function(e) {
                var $clicked = $(e.target);
                if (!$clicked.parents().hasClass(boxCSS) && !$clicked.hasClass(boxCSS)) {
                    self._hideBox();
                }
            });

            $(window).resize(function() {
                if (self.isShown) {
                    self.position();
                }
            });

            // Hide the box when click close trigger
            if ($.trim(this._get("trigger")) !== "" && $(this._get("trigger")).size() > 0) {
                $(this._get("trigger")).click(function() {
                    self._hideBox();
                    return false;
                });
            }
            return self;
        },
        // The postion function of box.
        position: function() {
            var _position = this._defaults.position;
            var offset = { top: 0, left: 0 };
            var self = this;
            function _center() {
                var wnd = $(window), doc = $(document), pTop, pLeft;
                pTop = doc.scrollTop(), pLeft = doc.scrollLeft();
                var minTop = pTop;
                pLeft += (wnd.width() - self.box.outerWidth()) / 2;
                pTop += (wnd.height() - self.box.outerHeight()) / 2;
                pTop = Math.max(pTop, minTop);
                return { top: pTop, left: pLeft };
            }

            function _follow() {
                var target, pTop, pLeft;
                target = !!self._get("accord") ? $(self._get("accord")) : self.target;
                var offset = target.offset();
                pTop = offset.top + target.height();
                if (_position.align && _position.align == "left") {
                    pLeft = offset.left;
                } else {
                    pLeft = offset.left - self.box.outerWidth() + target.outerWidth();
                }
                return { top: pTop, left: pLeft };
            }
            var _case;
            if (typeof _position === "string") {
                _case = _position;
            } else if (typeof _position === "object") {
                _case = _position.name;
            }

            switch (_case) {
                case "follow":
                    offset = _follow();
                    break;
                case "center":
                default:
                    offset = _center();
                    break;
            }
            return this.box.css(offset);
        }
    });

    /* Invoke the box functionality.*/
    $.fn.box = function(options) {
        var otherArgs = Array.prototype.slice.call(arguments, 1);
        return this.each(function(i) {
            var box;
            var self = $(this);
            if (self.data("boxInstance")) {
                box = self.data("boxInstance");
            } else {
                box = new Box();
            }
            typeof options == 'string' ?
            box['_' + options + 'Box'].apply(box, [this].concat(otherArgs)) :
            box._initBox(this, options);
        });
    };

    $.fn.boxRef = function() {
        return $(this).data("boxInstance").box;
    };

    $.fn.boxHoverIntent = function(options, millseconds) {
        var seconds = millseconds || 5000;
        return $(this).each(function() {
            var self = $(this);
            self.box(options);
            var isOver = false;
            var mouseOutIntentHandle = null;
            var array = [self.boxRef(), self];
            $.each(array, function(index, element) {
                element.hover(
                    function() {
                        isOver = true;
                        clearTimeout(mouseOutIntentHandle);
                    },
                    function() {
                        isOver = false;
                        self.trigger("mouseOutIntent");
                    }
                );
            });

            self.bind("mouseOutIntent", function() {
                mouseOutIntentHandle = setTimeout(function() {
                    if (!isOver) {
                        self.box("hide");
                    }
                }, seconds);
            });
        });
    };

    $.box = { Hash: [] };

    $.box.hideOtherBoxes = function(box) {
        $.each($.box.Hash, function(index, elem) {
            if (box != elem && elem.isShown) {
                elem._hideBox();
            }
        });
    };

    $.box.uuid = new Date().getTime();
    $.box.version = "1.0.0";

})(jQuery);
