/*
 * Boxy 0.1.4 - (c) 2008 Jason Frame
 */
jQuery.fn.boxy = function(options) {
    this.showTimeout = null;
    options = options || {};
    return this.each(function() {
        var node = this.nodeName.toLowerCase(), self = this;
        if (node == 'a') {
            jQuery(this).click(function() {
                var active = Boxy.linkedTo(this),
                    href = this.getAttribute('href'),
                    localOptions = jQuery.extend({ actuator: this, title: this.title }, options);
                var width = this.getAttribute('width'), height = this.getAttribute('height');
                if (width && width > 0) { jQuery.extend(localOptions, { width: width }); }
                if (height && height > 0) { jQuery.extend(localOptions, { height: height }); }
                if (active) {
                    active.show();
                } else if (href.indexOf('#') >= 0) {
                    var content = jQuery(href.substr(href.indexOf('#'))),
                        newContent = content.clone(true);
                    //content.remove();
                    localOptions.unloadOnHide = false;
                    new Boxy(newContent, localOptions);
                } else { // fall back to AJAX; could do with a same-origin check
                    if (!localOptions.cache) localOptions.unloadOnHide = true;
                    Boxy.load(this.href, localOptions);
                }

                return false;
            });
        } else if (node == 'form') {
            jQuery(this).bind('submit.boxy', function() {
                var _msg = $(this).attr('title') || "请确定：";
                Boxy.confirm(_msg, function() {
                    jQuery(self).unbind('submit.boxy').submit();
                });
                return false;
            });
        }
    });
};

var boxy_loading_image = 'http://css.sodao.com/dialog/loading.gif';
// Boxy Class
function Boxy(element, options) {
    this.boxy = jQuery(Boxy.WRAPPER);
    jQuery.data(this.boxy[0], 'boxy', this);
    this.visible = false;
    this.options = jQuery.extend({}, Boxy.DEFAULTS, options || {});

    if (this.options.modal) {
        this.options = jQuery.extend(this.options, { center: true, draggable: false });
    }

    // options.actuator == DOM element that opened this boxy
    // association will be automatically deleted when this boxy is remove()    
    if (this.options.actuator) {
        jQuery.data(this.options.actuator, 'active.boxy', this);
    }
    this._setupTitleBar();
    this.setContent(element || "<div></div>");

    this.boxy.css('display', 'none').appendTo(document.body);
    this.toTop();

    if (this.options.fixed && Boxy._u(this.options.x, this.options.y)) {
        if (jQuery.browser.msie && jQuery.browser.version < 7) {
            this.options.fixed = false; // IE6 doesn't support fixed positioning
        } else {
            this.boxy.addClass('fixed');
        }
    }

    if (this.options.center && Boxy._u(this.options.x, this.options.y)) {
        this.center();
    } else {
        this.moveTo(
            Boxy._u(this.options.x) ? Boxy.DEFAULT_X : this.options.x,
            Boxy._u(this.options.y) ? Boxy.DEFAULT_Y : this.options.y
        );
    }
    
    if (this.options.show) this.show();
};

Boxy.EF = function() {};

jQuery.extend(Boxy, {

    WRAPPER: "<table cellspacing='0' cellpadding='0' border='0' class='boxy-wrapper'>" +
                "<tr><td class='boxy-top-left'></td><td class='boxy-top'></td><td class='boxy-top-right'></td></tr>" +
                "<tr><td class='boxy-left'></td><td class='boxy-inner'></td><td class='boxy-right'></td></tr>" +
                "<tr><td class='boxy-bottom-left'></td><td class='boxy-bottom'></td><td class='boxy-bottom-right'></td></tr>" +
                "</table>",

    DEFAULTS: {
        title: null,           // titlebar text. titlebar will not be visible if not set.
        closeable: true,           // display close link in titlebar?
        draggable: true,           // can this dialog be dragged?
        clone: false,          // clone content prior to insertion into dialog?
        actuator: null,           // element which opened this dialog
        center: true,           // center dialog in viewport?
        show: true,           // show dialog immediately?
        modal: false,          // make dialog modal?
        modalOpacity: 0.7,       //默认模态背景透明度
        fixed: true,           // use fixed positioning, if supported? absolute positioning used otherwise
        closeText: '关闭窗口',      // text to use for default close link
        closeDelay: 0,
        submiting: false,       //form正在提交处理
        unloadOnHide: false,          // should this dialog be removed from the DOM after being hidden?
        clickToFront: false,          // bring dialog to foreground on any click (not just titlebar)?
        behaviours: Boxy.EF,        // function used to apply behaviours to all content embedded in dialog.
        afterDrop: Boxy.EF,        // callback fired after dialog is dropped. executes in context of Boxy instance.
        afterShow: Boxy.EF,        // callback fired after dialog becomes visible. executes in context of Boxy instance.
        afterHide: Boxy.EF,        // callback fired after dialog is hidden. executed in context of Boxy instance.
        beforeUnload: Boxy.EF,      // callback fired after dialog is unloaded. executed in context of Boxy instance.
        onFormSubmit: Boxy.EF,
        customerClosed: Boxy.EF,
        callbackData: null

    },

    DEFAULT_X: 50,
    DEFAULT_Y: 50,
    zIndex: 1337,
    dragConfigured: false, // only set up one drag handler for all boxys
    resizeConfigured: false,
    dragging: null,

    //处理Form表单提交后返回的内容
    handlerFormCallback: function(cmd, rtn, source) {
        source.options.submiting = false;   //完成反馈！
        if (cmd == "close") {
            source.hideAndUnload();
        } else if (cmd == "success" || cmd == "success close") {
            var successText = "恭喜你，提交成功！";
            if (rtn && rtn.success) {
                successText = rtn.success;
            }
            Boxy.popTip('成功提示', "<br>" + successText + "<br>", 2500);
            if (cmd == "success close") { source.hideAndUnload(); }
        } else if (cmd == "error") {
            var errorText = "抱歉，请求错误！";
            if (rtn && rtn.error) {
                errorText = rtn.error;
            }
            Boxy.popTip('错误提示', "<br>" + errorText + "<br>", 4000);
        }
    },
    // load a URL and display in boxy
    // url - url to load
    // options keys (any not listed below are passed to boxy constructor)
    //   type: HTTP method, default: GET
    //   cache: cache retrieved content? default: false
    //   filter: jQuery selector used to filter remote content
    load: function(url, options, method, data) {
        if (method == 'undefined' || method == null) {
            method = 'GET';
        }
        if (data == 'undefined' || data == null) {
            data = {};
        }
        options = options || {};
        var ajax = {
            url: url, type: method, data: data, dataType: 'html', cache: false, success: function(html) {
                html = jQuery(html);
                if (options.filter) { html = html.filter(options.filter); }
                if (options.onFormSubmit) {
                    var form;
                    form = html.filter('form');
                    if (!form.is('form')) { form = html.find('form'); }
                    if (form.is('form')) {
                        form.find("input[type='submit']").attr("onclick", "").bind("click", function() {
                            try {
                                var _boxy = Boxy.get(this);
                                if (_boxy.options.submiting) {
                                    Boxy.popTip('错误提示', '正在处理您的提交，请稍候...', 2000);
                                    return false;
                                }
                                _boxy.options.submiting = true;
                                options.onFormSubmit(form.attr('action'), form.serialize(), Boxy.handlerFormCallback, _boxy);
                            } catch (err) { alert("回调出错"); }
                            return false;
                        });
                    }
                    html = jQuery("<div></div>").append(form);
                } else { html = jQuery("<div></div>").append(html); }
                new Boxy(html, options);
            }
        };
        jQuery.each(['type', 'cache'], function() {
            if (this in options) {
                ajax[this] = options[this];
                delete options[this];
            }
        });
        jQuery.ajax(ajax);
    },
    //iframe 载入
    loadFrame: function(url, options) {
        options = jQuery.extend(options, { isIframe: true });
        var html = jQuery('<div style="text-align:center"></div>');
        html.append('<img src="' + boxy_loading_image + '" border="0">');
        var frame = jQuery('<iframe frameborder="0" hspace="0" id="sodaoIframe"></iframe>').attr('src', url).css('visibility', 'hidden');
        if (options.width) { frame.css('width', options.width + 'px'); }
        if (options.height) { frame.css('height', options.height + 'px'); }
        var self = this;
        frame.load(function() {
            $(this).prev().css('display', 'none');
            $(this).css('visibility', 'visible');
            //自动设置标题
            if ((window.location.hostname && $(this).attr('src').indexOf(window.location.hostname) > -1) || $(this).attr('src').indexOf('http://') == -1) {
                var title = options.title;
                if (!title || title == '') {
                    try {
                        var iframe = $(this).contents();
                        title = iframe.find('title').text();
                        if (title == 'undefined' || title == "") {
                            title = iframe.find('title').html(); // for IE
                        }
                    } catch (err) { }
                    if (title != 'undefined') { Boxy.get(this).setTitle(title); }
                }
            }
        });
        html.append(frame);
        if (!options.title) { options.title = ''; } //iframe 默认指定标题
        return new Boxy(html, options);
    },
    // allows you to get a handle to the containing boxy instance of any element
    // e.g. <a href='#' onclick='alert(Boxy.get(this));'>inspect!</a>.
    // this returns the actual instance of the boxy 'class', not just a DOM element.
    // Boxy.get(this).hide() would be valid, for instance.
    get: function(ele) {
        var p = jQuery(ele).parents('.boxy-wrapper');
        return p.length ? jQuery.data(p[0], 'boxy') : null;
    },

    // returns the boxy instance which has been linked to a given element via the
    // 'actuator' constructor option.
    linkedTo: function(ele) {
        return jQuery.data(ele, 'active.boxy');
    },
    loading: function(message, options) {
        var options = jQuery.extend({ modalOpacity: 0.1 }, options);
        var html = jQuery('<div style="text-align:center;font-size:14px;"></div>');
        html.append(message + '<br><br>' + '<img src="' + boxy_loading_image + '" border="0">');
        return new Boxy(html, options);
    },
    // displays an alert box with a given message, calling optional callback
    // after dismissal.
    alert: function(message, callback, options, btnText) {
        if (!btnText) {
            btnText = "确认";
        }
        return Boxy.ask(message, [btnText], callback, options);
    },

    // displays an alert box with a given message, calling after callback iff
    // user selects OK.
    confirm: function(message, after, options) {
        return Boxy.ask(message, ['确认', '取消'], function(response) {
            if (response == '确认') after(options.callbackData);
        }, options);
    },
    popTip: function(title, message, delay, options) {
        var settings = jQuery.extend({ modal: false, closeable: true, title: title, closeDelay: delay }, options || {});
        var html = jQuery('<div></div>').append(message);
        new Boxy(html, settings);
    },
    popLinked: function(ele, options) {
        options = jQuery.extend(options, { actuator: ele });
        var html = jQuery("<div><div>").append(options.actuator.clone(true).contents());
        new Boxy(html, options);
    },
    // asks a question with multiple responses presented as buttons
    // selected item is returned to a callback method.
    // answers may be either an array or a hash. if it's an array, the
    // the callback will received the selected value. if it's a hash,
    // you'll get the corresponding key.
    ask: function(question, answers, callback, options) {

        options = jQuery.extend({ modal: true, closeable: false },
                                options || {},
                                { show: true, unloadOnHide: true });

        var body = jQuery('<div></div>').append(jQuery('<div class="question"></div>').html(question));

        // ick
        var map = {}, answerStrings = [];
        if (answers instanceof Array) {
            for (var i = 0; i < answers.length; i++) {
                map[answers[i]] = answers[i];
                answerStrings.push(answers[i]);
            }
        } else {
            for (var k in answers) {
                map[answers[k]] = k;
                answerStrings.push(answers[k]);
            }
        }

        var buttons = jQuery('<form class="answers"></form>');
        buttons.html(jQuery.map(answerStrings, function(v) {
            //给确认对话框的确认取消按钮添加不同的class
            var btn_index;
            if (v == "确认" || v == "确定" || v == "确 认" || v == "确 定" || v == "开始" || v == "开 始") {
                btn_index = 1;
            } else if (v == "取消" || v == "取 消") {
                btn_index = 2;
            } else {
                btn_index = 3;
            }
            //add end.  include the 'btn_index' below 
            return "<input class='boxy-btn" + btn_index + "' type='button' value='" + v + "' />";
        }).join(' '));

        jQuery('input[type=button]', buttons).click(function() {
            var clicked = this;
            Boxy.get(this).hide(function() {
                if (callback) callback(map[clicked.value], options.callbackData);
            });
        });

        body.append(buttons);
        new Boxy(body, options);
    },

    // returns true if a modal boxy is visible, false otherwise
    isModalVisible: function() {
        return jQuery('.boxy-modal-blackout').length > 0;
    },

    _u: function() {
        for (var i = 0; i < arguments.length; i++)
            if (typeof arguments[i] != 'undefined') return false;
        return true;
    },

    _handleResize: function(evt) {
        var d = jQuery(document);
        jQuery('.boxy-modal-blackout').css('display', 'none').css({
            width: d.width(), height: d.height()
        }).css('display', 'block');
    },

    _handleDrag: function(evt) {
        var d;
        if (d = Boxy.dragging) {
            d[0].boxy.css({ left: evt.pageX - d[1], top: evt.pageY - d[2] });
        }
    },

    _nextZ: function() {
        return Boxy.zIndex++;
    },

    _viewport: function() {
        var d = document.documentElement, b = document.body, w = window;
        return jQuery.extend(
            jQuery.browser.msie ?
                { left: b.scrollLeft || d.scrollLeft, top: b.scrollTop || d.scrollTop} :
                { left: w.pageXOffset, top: w.pageYOffset },
            !Boxy._u(w.innerWidth) ?
                { width: w.innerWidth, height: w.innerHeight} :
                (!Boxy._u(d) && !Boxy._u(d.clientWidth) && d.clientWidth != 0 ?
                    { width: d.clientWidth, height: d.clientHeight} :
                    { width: b.clientWidth, height: b.clientHeight }));
    }

});

Boxy.prototype = {

    // Returns the size of this boxy instance without displaying it.
    // Do not use this method if boxy is already visible, use getSize() instead.
    estimateSize: function() {
        this.boxy.css({ visibility: 'hidden', display: 'block' });
        var dims = this.getSize();
        this.boxy.css('display', 'none').css('visibility', 'visible');
        return dims;
    },

    // Returns the dimensions of the entire boxy dialog as [width,height]
    getSize: function() {
        return [this.boxy.width(), this.boxy.height()];
    },

    // Returns the dimensions of the content region as [width,height]
    getContentSize: function() {
        var c = this.getContent();
        return [c.width(), c.height()];
    },

    // Returns the position of this dialog as [x,y]
    getPosition: function() {
        var b = this.boxy[0];
        return [b.offsetLeft, b.offsetTop];
    },

    // Returns the center point of this dialog as [x,y]
    getCenter: function() {
        var p = this.getPosition();
        var s = this.getSize();
        return [Math.floor(p[0] + s[0] / 2), Math.floor(p[1] + s[1] / 2)];
    },

    // Returns a jQuery object wrapping the inner boxy region.
    // Not much reason to use this, you're probably more interested in getContent()
    getInner: function() {
        return jQuery('.boxy-inner', this.boxy);
    },

    // Returns a jQuery object wrapping the boxy content region.
    // This is the user-editable content area (i.e. excludes titlebar)
    getContent: function() {
        return jQuery('.boxy-content', this.boxy);
    },

    // Replace dialog content
    setContent: function(newContent) {
        newContent = jQuery(newContent).css({ display: 'block' }).addClass('boxy-content');
        //if (!this.options.isIframe) {
        if (this.options.width) { newContent.css('width', this.options.width + 'px'); }
        if (this.options.height) { newContent.css('height', this.options.height + 'px'); }
        //}
        if (this.options.clone) newContent = newContent.clone(true);
        this.getContent().remove();
        this.getInner().append(newContent);
        this._setupDefaultBehaviours(newContent);
        this.options.behaviours.call(this, newContent);
        return this;
    },

    // Move this dialog to some position, funnily enough
    moveTo: function(x, y) {
        this.moveToX(x).moveToY(y);
        this.showIframeMask(); //iframe 遮罩
        return this;
    },

    // Move this dialog (x-coord only)
    moveToX: function(x) {
        if (typeof x == 'number') this.boxy.css({ left: x });
        else this.centerX();
        return this;
    },

    // Move this dialog (y-coord only)
    moveToY: function(y) {
        if (typeof y == 'number') this.boxy.css({ top: y });
        else this.centerY();
        return this;
    },

    // Move this dialog so that it is centered at (x,y)
    centerAt: function(x, y) {
        var s = this[this.visible ? 'getSize' : 'estimateSize']();
        if (typeof x == 'number') this.moveToX(x - s[0] / 2);
        if (typeof y == 'number') this.moveToY(y - s[1] / 2);
        return this;
    },

    centerAtX: function(x) {
        return this.centerAt(x, null);
    },

    centerAtY: function(y) {
        return this.centerAt(null, y);
    },

    // Center this dialog in the viewport
    // axis is optional, can be 'x', 'y'.
    center: function(axis) {
        var v = Boxy._viewport();
        var o = this.options.fixed ? [0, 0] : [v.left, v.top];
        if (!axis || axis == 'x') this.centerAt(o[0] + v.width / 2, null);
        if (!axis || axis == 'y') this.centerAt(null, o[1] + v.height / 2);
        return this;
    },

    // Center this dialog in the viewport (x-coord only)
    centerX: function() {
        return this.center('x');
    },

    // Center this dialog in the viewport (y-coord only)
    centerY: function() {
        return this.center('y');
    },

    // Resize the content region to a specific size
    resize: function(width, height, after) {
        if (!this.visible) return;
        var bounds = this._getBoundsForResize(width, height);
        this.boxy.css({ left: bounds[0], top: bounds[1] });
        this.getContent().css({ width: bounds[2], height: bounds[3] });
        self.showIframeMask(); //iframe 遮罩
        if (after) after(this);
        return this;
    },

    // Tween the content region to a specific size
    tween: function(width, height, after) {
        if (!this.visible) return;
        var bounds = this._getBoundsForResize(width, height);
        var self = this;
        this.boxy.stop().animate({ left: bounds[0], top: bounds[1] });
        this.getContent().stop().animate({ width: bounds[2], height: bounds[3] }, function() {
            if (!self.options.modal) { self.showIframeMask(); } //iframe 遮罩            
            if (after) after(self);
        });
        return this;
    },

    // Returns true if this dialog is visible, false otherwise
    isVisible: function() {
        return this.visible;
    },
    //显示背景
    showIframeMask: function(disp) {
        if ((jQuery.browser.msie && jQuery.browser.version < 7) || disp) {
            if (!this.options.modal || disp) {
                var size = this.getSize();
                var pos = this.getPosition();
                var self = this;
                if (!this.iframeMask) {
                    var position = this.options.fixed ? "fixed" : "absolute";
                    //iframe 遮罩
                    this.iframeMask = jQuery('<iframe id="sodaoModalIframeMask" src="javascript:\'\';" class="boxy-modal-blackout-iframe"></iframe>')
								.css({ opacity: 0,
                                    position: position, zIndex: 28,
								    width: 0, height: 0, left: pos[0], top: pos[1],
								    display: 'none'
								}).appendTo(document.body);
                    this.options.fixed = false; //IE6 doesn't support fixed positioning                    
                } else {
                    this.iframeMask.css({ display: 'none', width: 0, height: 0, left: pos[0], top: pos[1] });
                }
                setTimeout(function() { self.iframeMask.css({ display: "", width: size[0], height: size[1] }); }, 50);
            }
        }
    },
    // Make this boxy instance visible
    show: function() {
        if (this.visible) return;
        var self = this;
        if (this.options.modal) {
            if (!Boxy.resizeConfigured) {
                Boxy.resizeConfigured = true;
                jQuery(window).resize(function() { Boxy._handleResize(); });
            }
            this.modalBlackout = jQuery('<div class="boxy-modal-blackout"></div>')
                .css({ zIndex: Boxy._nextZ(),
                    opacity: this.options.modalOpacity,
                    display: 'none',
                    width: jQuery(document).width(),
                    height: jQuery(document).height()
                })
                .appendTo(document.body);
            if (jQuery.browser.msie && jQuery.browser.version < 7) {
                this.modalBlackout.css('width', jQuery(document).width() - 20); //IE6 下需要减掉
                //iframe 遮罩
                this.iframeMask = jQuery('<iframe id="sodaoModalIframeMask" src="javascript:\'\';" class="boxy-modal-blackout-iframe"></iframe>')
								.css({ opacity: 0, width: '100%',
								    height: jQuery(document).height()
								}).appendTo(document.body);
            }
            //return;
            //显示Modal
            setTimeout(function() {
                jQuery('.boxy-modal-blackout').show(); //('fast');
            }, 0);
            this.toTop();
            if (this.options.closeable) {
                jQuery(document.body).bind('keypress.boxy', function(evt) {
                    var key = evt.which || evt.keyCode;
                    if (key == 27) {
                        self.hideAndUnload();
                        jQuery(document.body).unbind('keypress.boxy');
                    }
                });
            }
            this.showTimeout = setTimeout(function() {
                self.boxy.stop().css({ opacity: 1 }).stop().fadeIn('fast');
                self.tweenShow(true);
            }, (this.options.modalOpacity <= 0.1 ? 25 : 100));
        } else {
            this.boxy.stop().css({ opacity: 1 }).stop().fadeIn('fast');
            this.tweenShow();
        }

        this.visible = true;
        this._fire('afterShow');

        //定时自动关闭
        if (this.options.closeDelay && this.options.closeDelay > 0) {
            setTimeout(function() { self.hideAndUnload(); }, self.options.closeDelay);
        }
        return this;
    },
    tweenShow: function(disp) {
        if (!this.options.modal || disp) { this.showIframeMask(disp); }
        //根据是否Iframe来决定是否要动画展示
        //        if (!this.options.isIframe) {
        //            if (this.options.width && this.options.height) { 
        //                if (!this.visible) { this.visible = true; }
        //                this.tween(this.options.width, this.options.height);
        //            } else { if (!this.options.modal) { this.showIframeMask(); } }
        //        } else { if (!this.options.modal) { this.showIframeMask(); } }
    },
    // Hide this boxy instance
    hide: function(after) {
        try { clearTimeout(this.showTimeout); } catch (e) { } //clearTimeout
        if (!this.visible) return;
        var self = this;
        if (this.iframeMask) {
            this.iframeMask.css('display', 'none');
        }
        if (this.options.modal) {
            jQuery(document.body).unbind('keypress.boxy');
            this.modalBlackout.hide(25, function() {
                jQuery(this).remove();
            });
        }
        this.boxy.stop().fadeOut('fast', function() {
            self.boxy.css({ display: 'none' });
            self.visible = false;
            self._fire('afterHide');
            if (after) after(self);
            if (self.options.unloadOnHide) self.unload();
        });
        if (this.options.isIframe) {
            this.boxy.find("#sodaoIframe").attr("src", "").removeAttr("id");
        }
        return this;
    },

    toggle: function() {
        this[this.visible ? 'hide' : 'show']();
        return this;
    },

    hideAndUnload: function(after) {
        this.options.unloadOnHide = true;
        this.hide(after);
        return this;
    },

    unload: function() {
        this._fire('beforeUnload');
        this.boxy.remove();
        if (this.options.actuator) {
            jQuery.data(this.options.actuator, 'active.boxy', false);
        }
    },

    // Move this dialog box above all other boxy instances
    toTop: function() {
        this.boxy.css({ zIndex: Boxy._nextZ() });
        return this;
    },

    // Returns the title of this dialog
    getTitle: function() {
        return jQuery('> .title-bar h2', this.getInner()).html();
    },

    // Sets the title of this dialog
    setTitle: function(t) {
        jQuery('> .title-bar h2', this.getInner()).html(t);
        return this;
    },

    // Don't touch these privates
    _getBoundsForResize: function(width, height) {
        var csize = this.getContentSize();
        var delta = [width - csize[0], height - csize[1]];
        var p = this.getPosition();
        return [Math.max(p[0] - delta[0] / 2, 0),
                Math.max(p[1] - delta[1] / 2, 0), width, height];
    },

    _setupTitleBar: function() {
        if (this.options.title || this.options.title == '') {
            var self = this;
            var tb = jQuery("<div class='title-bar'></div>").html("<h2>" + this.options.title + "</h2>"); //.css('cursor', (this.options.draggable ? 'move' : 'arrow'))
            if (this.options.closeable) {
                tb.append(jQuery("<a href='#' class='close'></a>").attr('title', this.options.closeText).html(this.options.closeText));
            }
            if (this.options.draggable) {
                tb[0].onselectstart = function() { return false; }
                tb[0].unselectable = 'on';
                tb[0].style.MozUserSelect = 'none';
                if (!Boxy.dragConfigured) {
                    jQuery(document).mousemove(Boxy._handleDrag);
                    Boxy.dragConfigured = true;
                }
                tb.mousedown(function(evt) {
                    self.toTop();
                    Boxy.dragging = [self, evt.pageX - self.boxy[0].offsetLeft, evt.pageY - self.boxy[0].offsetTop];
                    jQuery(this).addClass('dragging');
                }).mouseup(function() {
                    jQuery(this).removeClass('dragging');
                    Boxy.dragging = null;
                    self._fire('afterDrop');
                });
            }
            this.getInner().prepend(tb);
            this._setupDefaultBehaviours(tb);
        }
    },

    _setupDefaultBehaviours: function(root) {
        var self = this;
        if (this.options.clickToFront) {
            root.click(function() { self.toTop(); });
        }
        jQuery('.close', root).click(function() {
            if (self.options.isIframe) {
                self.hide();
            } else {
                self.hideAndUnload(); //hide();
            }
            return false;
        }).mousedown(function(evt) { evt.stopPropagation(); });
    },

    _fire: function(event) {
        if (event == "afterDrop") {
            this.showIframeMask();
        } else if (event == "afterHide") {
            if (this.iframeMask) { this.iframeMask.remove(); }
        }
        this.options[event].call(this);
    }
};
