﻿//<using>
//  nui/nui.js
//  nui/prototype.js
//  nui/lang.js
//  nui/util.js
//  nui/widget.js
//  nui/widget/button.js
//</using>

/**
 * All kinds of popups in NUI.
 * Copyright 2007, NetRanking.cn
 */
 
/**
 * Dropdown Popup
 * @class NUI.Widget.Dropdown
 * @param vChild {object}
 * @param vAttributes {object} OPTIONAL. The attributes of popup. 
 *      vAttributes = {
 *          id : "id",
 *          width : 100,
 *          height : 60,
 *          top : 24,
 *          left : -24
 *      }
 */
NUI.Widget.Dropdown = function(vChild, vAttributes){
    var m_dom = NUI.Util.DomService,
        m_sb = NUI.Util.StringService.StringBuilder,
        m_width = vAttributes ? ( vAttributes.width ? vAttributes.width : 150 ) : 150,
        m_height = vAttributes ? ( vAttributes.height ? vAttributes.height : 100 ) : 100,
        m_top = vAttributes ? ( vAttributes.top ? vAttributes.top : 22 ) : 22,
        m_left = vAttributes ? ( vAttributes.left ? vAttributes.left : -24 ) : -24,
        m_secret = {},
        m_mousedown = null,     //mousedown event of document;
        m_visiable = false;     //become true if that.show() is called and false if that.hide() is called.
    if(vAttributes && vAttributes.id) {
        m_secret.id = vAttributes.id;
    }
        
    var that = NUI.Widget.Base(m_secret);
    var m_attributes = {
        id : m_secret.id,
        className : "dropdown"
    };
    
    NUI.Util.ObjectService.annex(that, {
        nodeEntity : (function() {
            var retval = m_dom.createNode("div", m_attributes),
                sb = new m_sb();
            sb.append(
                "<div class=\"inner\" onmousedown=\"NUI.Util.EventService.cancelBubble()\" ",
                "style=\"top:" + m_top + "px; left:" + m_left + "px; ",
                "width:" + m_width + "px; height:" + m_height + "px;\"></div>"
            );
            m_dom.setInnerHTML(retval, sb.toString());
            if(NUI.Lang.isObject(vChild)) {
                m_dom.appendNode(retval.firstChild, vChild);
            }
            return retval;
        })(),
        
        /**
         * Insert the widget behind the target node, and show this widget.
         * When the widget become visiable, the onmousedown event handler of the document 
         * is backup into private variable "m_mousedown". And the onmousedown event 
         * handler become "that.hide"
         * @method show
         * @param vNode {string|object} (id of) the target node
         */
        show : function(vNode) {
            var n = m_dom.getNode(vNode);
            if(!n) {
                return;
            }
            that.appendBehind(n);       // 这里有问题，一个dropdown如果show多次，会多次appendBehind不同的node
            that.nodeEntity.style.display = "inline";
            m_visiable = true;
            m_mousedown = document.onmousedown;
            document.onmousedown = that.hide;
        },
        
        /**
         * Restore the onmousedown event handler of document.
         * Make the widget invisiable. Remove the widget from the document.
         * @method hide
         */
        hide : function() {
            if(!m_visiable) {
                return;
            }
            document.onmousedown = m_mousedown;
            m_mousedown = null;
            m_visiable = false;
            that.nodeEntity.style.display = "none";
        }
    });
    
    return that;
};


/**
 * Fog Popup. The base class.
 * @class NUI.Widget.Fog
 * @param vSecret {object}. 
 */
NUI.Widget.Fog = (function() {
    var g_dom = NUI.Util.DomService,
        g_sb = NUI.Util.StringService.StringBuilder,
        g_gty = NUI.Util.WindowService.Geometry,
        g_htmlTmplt = (function(){
            var sb = new g_sb();
            sb.append(
                "<div class=\"fog\">",
                "<table cellpadding=\"0\" cellspacing=\"0\" class=\"fadeTable\" ><tr><td>",
                "<div class=\"fadeDiv\" id=\"{ID}_fade\">",
                "</div></td></tr></table>",
                "</div>",
                
                "<div class=\"fog\" id=\"{ID}_fog_2\">",
                "<table id=\"{ID}_tb_2\" cellpadding=\"0\" cellspacing=\"0\" class=\"panelTable\"><tr>",
                "<td valign=\"middle\" align=\"center\"><div id=\"{ID}_panel\">",
                "</div></td></tr></table>",
                "</div>"
            );
            return sb.toString();
        })();
    
    return function(vSecret) {
        vSecret = vSecret || {};
            
        var that = NUI.Widget.Base(vSecret);
        var m_id = vSecret.id,
            m_node = (function() {
                var retval = g_dom.createNode("div", { 
                    id : m_id,
                    className : "hide"
                });
                g_dom.setInnerHTML(retval, g_htmlTmplt.supplant({
                    ID : m_id
                }));
                return retval;
            })();
            
        /**
         * Adjust the popup's size. Used when show the panel.
         */
        function _adjustSize() {
            var docHeight = g_gty.getDocumentHeight(),
                docWidth = g_gty.getDocumentWidth();
            if(docHeight < g_gty.getViewportHeight()) {    // to be fixed
                docHeight = g_gty.getViewportHeight();
            }
            
            var fadeDiv = vSecret.getChild(m_id + "_fade");
            if(fadeDiv) {
                fadeDiv.style.width = docWidth + "px";
                fadeDiv.style.height = docHeight + "px";
            }
            
            var topPadding = g_gty.getVerticalScroll();
            var fog2 = vSecret.getChild(m_id + "_fog_2");
            if(fog2) {
                fog2.style.top = topPadding + "px";
            }
        }
        
        NUI.Util.ObjectService.annex(vSecret, {
            /**
             * render the fog's child panel
             * @method setChild
             * @param vChild {object | string} The child node
             */
            setChild : function(vChild) {
                if(vChild) {
                    var panelCon = vSecret.getChild(m_id + "_panel");
                    g_dom.setChild(panelCon, vChild);
                }
            }
        });
        
        NUI.Util.ObjectService.annex(that, {
            nodeEntity : m_node,
            
            /**
             * Show the fog
             * @method show
             */
            show : function() {
                if(m_node.parentNode != document.body) {
                    g_dom.appendNode(document.body, m_node);
                }
                _adjustSize();
                g_dom.show(m_node);
                
                // adjust the position in IE6
                var isIE6 = (NUI.Util.EnvService.browser.ie && NUI.Util.EnvService.browser.version < 7);
                if(isIE6) {
                    setTimeout(function(){
                        var fog2 = vSecret.getChild(m_id + "_fog_2");
                        var m_top = (g_gty.getViewportHeight() - fog2.offsetHeight) / 2;
                        fog2.style.marginTop = m_top + "px";
                    }, 500);
                }
            },
            
            /**
             * Hide and DESTROY the fog
             * @method hide
             */
            hide : function() {
                g_dom.hide(m_node);
            }
        });
        
        return that;
    };
})();

/**
 * Fog Alert. Inherent from Fog.
 * How to use ?
 *      NUI.Widget.Alert('abc', {
 *          btnText:"下定决心了"
 *      });
 *
 * @class NUI.Widget.Alert
 * @param vMsg {string}. The message to alert
 * @param vAttribute {object}. OPTIONAL
 *      vAttribute = {
 *          btnText : string,
 *          title : string
 *      }
 */
NUI.Widget.Alert = (function() {
    var g_dom = NUI.Util.DomService,
        g_sb = NUI.Util.StringService.StringBuilder,
        g_htmlTmplt = (function() {
            var sb = new g_sb();
            sb.append(
                "<div class=\"panel\" style=\"width:300px;\">",
                "<div class=\"header\">{TITLE}</div><div class=\"content\">",
                "<div style=\"padding:5px;\">{MESSAGE}</div>",
                "<div style=\"padding:5px;\"><input type=\"button\" value=\"&nbsp;{BTN_TEXT}&nbsp;\" /></div>",
                "</div></div>"
            );
            return sb.toString();
        })();
    
    return function(vMsg, vAttribute) {
        var m_secret = {},
            that = new NUI.Widget.Fog(m_secret),
            m_id = m_secret.id;
            
        var m_btnText = "确认",
            m_title = "提示消息";
        if(vAttribute) {
            if(vAttribute.btnText) {
                m_btnText = vAttribute.btnText;
            }
            if(vAttribute.title) {
                m_title = vAttribute.title;
            }
        }
        
        var m_child = (function(){
                var retval = g_dom.createNode("div", {
                        onclick : function() {
                            var src = event.srcElement;
                            if(g_dom.isButton(src)) {
                                that.hide();
                            }
                        }
                    });
                g_dom.setInnerHTML(retval, 
                    g_htmlTmplt.supplant({
                        MESSAGE : vMsg,     // vMsg should html encoding
                        TITLE : m_title,
                        BTN_TEXT : m_btnText
                    }));
                return retval;
            })();
        m_secret.setChild(m_child);
        
        that.show();
        return that;
    };
})();

/**
 * Fog Confirm. Inherent from Fog.
 * How to use ?
 *      NUI.Widget.Confirm('你已经下定决心了吗', function(vOk) {
 *          alert(vOk);
 *      }, {
 *          btnOkText:"下定决心了", 
 *          btnCancelText:"算了等等吧"
 *      });
 *
 * @class NUI.Widget.Confirm
 * @param vMsg {string}. The message to alert
 * @param vFunc {function}. The function to execute after user click "ok" or "cancel"
 * @param vAttribute {object}. OPTIONAL
 *      vAttribute = {
 *          btnOKText : string,
 *          btnCancelText : string
 *          width : int
 *      }
 */
NUI.Widget.Confirm = (function() {
    var g_dom = NUI.Util.DomService,
        g_htmlTmplt = (function() {
            var m_sb = new NUI.Util.StringService.StringBuilder();
            m_sb.append(
                "<div class=\"panel\" style=\"{WIDTH_STYLE};line-height:20px;\">",
                "<div class=\"header\">确认消息</div><div class=\"content\">",
                "<div style=\"padding:5px;\">{MESSAGE}</div>",
                "<div style=\"padding:5px;\"><input type=\"button\" id=\"{ID}_OK\" value=\"&nbsp;{BTN_OK_TEXT}&nbsp;\" />",
                "&nbsp;&nbsp;<input type=\"button\" id=\"{ID}_CANCEL\" value=\"&nbsp;{BTN_CANCEL_TEXT}&nbsp;\" /></div>",
                "</div></div>"
            );
            return m_sb.toString();
        })();
    
    return function(vMsg, vFunc, vAttribute) {
        var m_secret = {},
            that = new NUI.Widget.Fog(m_secret),
            m_id = m_secret.id;
            
        var m_btnOkText = "确认", 
            m_btnCancelText = "取消",
            m_width = 300;
        if(vAttribute) {
            m_btnOkText = vAttribute.btnOkText ? vAttribute.btnOkText : m_btnOkText;
            m_btnCancelText = vAttribute.btnCancelText ? vAttribute.btnCancelText : m_btnCancelText;
            m_width = (vAttribute.width && vAttribute.width > 0) ? vAttribute.width : m_width;
        }
            
        var m_child = (function(){
                var retval = g_dom.createNode("div", {
                        onclick : function() {
                            var src = event.srcElement;
                            if(g_dom.isButton(src)) {
                                if(vFunc) {
                                    var cn = src.id.controlIdStr();
                                    switch(cn) {
                                        case "OK":
                                            vFunc(true);
                                            break;
                                        case "CANCEL":
                                            vFunc(false);
                                            break;
                                    }
                                }
                                that.hide();
                            }
                        }
                    });
                g_dom.setInnerHTML(retval, 
                    g_htmlTmplt.supplant({
                        ID : m_id,
                        MESSAGE : vMsg,     // vMsg should html encoding
                        BTN_OK_TEXT : m_btnOkText,
                        BTN_CANCEL_TEXT : m_btnCancelText,
                        WIDTH_STYLE : "width:" + m_width + "px"
                    }));
                return retval;
            })();
            
        m_secret.setChild(m_child);
            
        that.show();
        return that;
    };
})();

/**
 * Popup window. Inherent from Fog.
 * How to use ?
 *      NUI.Widget.Popup("I am child, I can be dom object or string", {title:"标题"}).show();
 *
 * @class NUI.Widget.Popup
 * @param vChildNode {object}
 * @param vAttribute {object}. OPTIONAL
 *      vAttribute = {
 *          title : {string},
 *          width : {int},
 *          height : {int},
 *          canHide : {boolean}
 *      }
 */
NUI.Widget.Popup = (function() {
    var g_dom = NUI.Util.DomService,
        g_htmlTmplt = (function() {
            var m_sb = new NUI.Util.StringService.StringBuilder();
            m_sb.append(
                "<div class=\"panel\" style=\"{WIDTH_STYLE};\">",
                "<div class=\"header\"><div id=\"{ID}_BTN\" style=\"float:right\"></div>{TITLE}</div>",
                "<div id=\"{ID}_CONTENT\" class=\"content\" ",
                "style=\"{WIDTH_STYLE}; {HEIGHT_STYLE}; overflow:auto; text-align:left;\" >",
                "</div></div>"
            );
            return m_sb.toString();
        })();
    
    return function(vChild, vAttribute) {
        var m_width = 500, 
            m_height = 0, 
            m_title = "弹出窗口",
            m_canHide = true;
        if(vAttribute) {
            m_width = vAttribute.width ? vAttribute.width : m_width;
            m_height = vAttribute.height ? vAttribute.height : m_height;
            m_title = vAttribute.title ? vAttribute.title : m_title;
            m_canHide = (vAttribute.canHide != null) ? vAttribute.canHide : m_canHide;
        }
        
        var m_secret = {},
            that = new NUI.Widget.Fog(m_secret),
            m_id = m_secret.id;
            
        var m_child = (function() {
                var retval = g_dom.createNode("div");
                g_dom.setInnerHTML(retval, g_htmlTmplt.supplant({
                    ID : m_id,
                    TITLE : m_title,
                    HEIGHT_STYLE : (m_height > 0) ? "height:" + m_height + "px" : "",
                    WIDTH_STYLE : (m_width > 0) ? "width:" + m_width + "px" : ""
                }));
                if(m_canHide) {
                    var _btncon = g_dom.getNode(m_id + "_BTN", { root:retval }),
                        _btn = new NUI.Widget.Button.SpanButton({
                            index : 0,
                            width : 15,
                            height : 15,
                            image : "nui/button/smallbtn.gif"
                        }, {
                            id : m_id + "closebtn",
                            onclick : function(){
                                that.hide();
                            }
                        });
                    _btn.attachTo(_btncon);
                }
                var _contentcon = g_dom.getNode(m_id + "_CONTENT", { root:retval });
                if(vChild) {
                    g_dom.setChild(_contentcon, vChild);
                }
                return retval;
            })();
            
        m_secret.setChild(m_child);
        
        NUI.Util.ObjectService.annex(that, {
            /**
             * Change the content of the popup
             */
//            setContent : function(vContent) {
//                if(vContent == null) {
//                    return;
//                }
//                var con = m_secret.getChild(m_id + "_CONTENT");
//                if(con) {
//                    g_dom.setChild(con, vContent);
//                }
//            }
        });
        
        return that;
    };
})();

/**
 * Waiting window. Inherent from Fog.
 * How to use ?
 *      NUI.Widget.Waiting.start("please wait...");
 *
 * @class NUI.Widget.Waiting
 */
NUI.Widget.Waiting = (function() {
    var g_dom = NUI.Util.DomService;
    
    var g_window = null;
    
    var that = {
        start : function(vMsg, vCon) {
            if(vMsg == null) {
                vMsg = "请稍候...";
            }
            var html = "<div style=\"padding:20px; text-align:center;\"><img style=\"vertical-align:middle;\" src=\"" + 
                NUI.Util.WindowService.Path.imagePath("utility/loading.gif") + "\" alt=\"loading\" />&nbsp;" + 
                vMsg + "...</div>";
            var con = g_dom.getNode(vCon);
            if(con) {
                g_dom.setInnerHTML(con, html);
            } else {
                if(g_window) {
                    g_window.destroy();
                }
                g_window = NUI.Widget.Popup(html, {
                    title : "请稍候",
                    width : 250,
                    canHide : false
                });
                g_window.show();
            }
        },
        end : function() {
            if(g_window) {
                g_window.destroy();
            }
        },
        create : function(vMsg, vCon) {
            if(vMsg == null) {
                vMsg = "请稍候...";
            }
            var html = "<div><img style=\"vertical-align:middle;\" src=\"" + 
                NUI.Util.WindowService.Path.imagePath("utility/loading.gif") + "\" alt=\"loading\" />&nbsp;" + 
                vMsg + "...</div>";
            var con = g_dom.getNode(vCon);
            var node = null;
            if(con != null) {
                var con_rect = NUI.Util.WindowService.getNodeRect(con);
                if(con_rect != null) {
                    node = g_dom.createNode("div", {
                        className : "waiting_outer"
                    });
                    g_dom.appendNode(con, node);
                    var rect = NUI.Util.WindowService.getNodeRect(node);
                    var inner_node = g_dom.createNode("div", {
                        className : "waiting_inner"
                    });
                    g_dom.appendNode(node, inner_node);
                    inner_node.style.height = (con_rect.height > 0) ? (con_rect.height + "px") : "auto";
                    inner_node.style.width = (con_rect.width > 0) ? (con_rect.width + "px") : "auto";
                    inner_node.style.top = (con_rect.top-rect.top) + "px";
                    inner_node.style.left = (con_rect.left-rect.left) + "px";
                    var msg_node = g_dom.createNode("div");
                    g_dom.setInnerHTML(msg_node, html);
                    g_dom.appendNode(inner_node, msg_node);
                    msg_node.style.padding = (con_rect.height/2 < 20) ? (Math.floor(con_rect.height/2) +"px") : "20px";
                }
            }
            return {
                destroy : function() {
                    g_dom.destroyNode(node);
                }
            };
        }
    };
    return that;
})();



