(function ($, B) {

    // 选中模式
    var g_SelectMode = {
        // 单选
        SINGLE: "single",
        // 多选
        MULTIPE: "multiple"
    };

    /**
      * 对象选择器命名空间
      * @module Beyondbit.OPicker
	  * @submodule OPicker
      *    
      */
    var opicker = B.registerNameSpace("OPicker");

    opicker.regional = [];

    opicker.regional[""] = opicker.regional["zh-CN"] = {
        service: {
            notAllowRegisterCodeEmpty: "注册Code不能为空",
            repeatRegistered: "重复注册服务标识:{0}",
            useNotRegisteredCode: "使用无注册服务标识:{0}"
        },
        title: "对象选择器",
        notSetObjectCode: "没有填写选择对象Codes",
        defaultNamesLengthNotEqualValuesLength: "默认值的name和value的长度不一致!",
        buttons: {
            ok: "确定",
            clear: "清除",
            cancel: "取消"
        },
        search: {
            title: "搜索",
            placeholder: "输入关键字检索"
        },
        select: {
            selected: "已选择",
            up: "向上",
            down: "向下"
        }
    }

    function getRegional() {
        return opicker.regional[B.CultureInfo.Current.get()];
    }

    /**
     * @class Opicker
     * 
     */

   /**
     * 选择
     * @method select
     * @param {json} options 选项请参考属性值
     * @static
     * @example
     *     
     *     <html>
     *          <div>
     *               <button class="btn" type="button" id="btnSelectUser">
     *                   <i class="fa fa-male"></i>
     *                   选择用户
     *               </button>
     *
     *               <input type="text" name="name" value="" id="txtName" />
     *               <input type="text" name="name" value="" id="txtValue" />
     *           </div>
     *
     *
     *           <div>
     *               <button class="btn" type="button" id="btnSelectUser2">
     *                   <i class="fa fa-male"></i>
     *                   选择用户2
     *               </button>
     *
     *               <input type="text" name="name" value="" id="txtName2" />
     *               <input type="text" name="name" value="" id="txtValue2" />
     *           </div>
     *     </html>
     * 
     *     <script>
     *          $(function () {
     *               $("#btnSelectUser2").click(function () {
     *                   B.OPicker.select({
     *                       title: "<i class='fa fa-male'></i> 选择用户",
     *                       objectCodes: ["orguser"],
     *                       associatedNameControl: $("#txtName2"),
     *                       associatedValueControl: $("#txtValue2")
     *                   });
     *               });
     *
     *
     *               $("#btnSelectUser").click(function () {
     *                   B.OPicker.select({
     *                       title: "<i class='fa fa-male'></i> 选择用户",
     *                       objectCodes: ["orguser", "roleuser"],
     *                       defaultValue: {
     *                           name: $("#txtName").val(),
     *                           value: $("#txtValue").val()
     *                       },
     *                       onSelectedValue: function (data) {
     *                           $("#txtName").val(data.name);
     *                           $("#txtValue").val(data.value);
     *                       }
     *                   });
     *               });
     *           })
     *     </script>
     */
    opicker.select = function (options) {
        new OPicker(options);
    };


    // #region 服务

    // 保存所有注册的services
    var _services = {};

    /**
      * 注册服务
      * @method registerService
      * @static
      * @param {String} code 服务标识,不能注册重复标识,重复抛异常
      * @param {String} name 显示名称
      * @param {String} serviceUrl 服务地址
      * @param {Fun} [dataFilter ] 调用成功后,过滤数据
      * @example
      *
      *    B.OPicker.registerService("user", http://service.beyondbit.com/user/get");
      *    
      */

    opicker.registerService = function (code, title, serviceUrl, dataFilter) {
        var serviceCode = code;
        if (!arguments[0]) {
            throw Error(getRegional().service.notAllowRegisterCodeEmpty);
        }
        var service;
        var firstArgumentType = $.type(arguments[0]);
        if (firstArgumentType === "string") {
            service = {
                code: serviceCode,
                title: title,
                url: serviceUrl
            };
        } else if ($.isFunction(arguments[0])) {
            //TODO: 延迟加载注册功能
        }
        else{    
            service = arguments[0];
            serviceCode = service.code;
        }

        if (_services[serviceCode]) {
            throw Error(getRegional().service.repeatRegistered.bformat(serviceCode));
        }
        
        
        _services[serviceCode] = $.extend(true, {},
            {
                /*
                 * 数据过滤事件
                 * @event dataFilter 
                 * @param {object} 过滤的数据项
                 */
                dataFilter: function (item) {
                    return item;
                },
                /*
                 * 获取静态数据数据源
                 * @event getStaticDataSource
                 */
                getStaticDataSource: function () { return null; },
                getSearchUrl: function (config) {
                    if (this.searchUrl) {
                        return this.getUrl(config, this.searchUrl);
                    }
                },
                /*
                 * 获取服务Url事件
                 * @event getUrl
                 * @param {json} config
                 * @param {string} url[default=this.url] 要包装的Url默认为当前url属性
                 */
                getUrl: function (config, url) {
                    return url || this.url;
                },
                /*
                 * 是否显示图标
                 * @event showIcon
                 * @param {object} 数据项
                 */
                showIcon: function (item) {
                    return true;
                }
            },
            service
         );
    };

    /**
      * 获取一个服务
      * @static
      * @private
      * @method getService
      * @param {String} code 服务标识,标识未注册抛异常
      * @example
      *
      *    B.OPicker.getService("user");
      *    
      */

    opicker.getService = function (code) {
        var service = _services[code];
        if (!service) {
            throw Error(getRegional().service.useNotRegisteredCode.bformat(code));
        }
        return service;
    }

    // #endregion

    function OPicker(options) {
        options = $.extend(true, {
            id: "opicker",
            /**
              * 选择器标题
              * @property title
              * @type String
              * @default "对象选择器"
              */
            title: getRegional().title,
            /**
              * 宽度
              * @property width
              * @type Number
              * @default 600
              */
            width: 600,
            /**
              * 高度
              * @property height
              * @type Number
              * @default 500
              */
            height: 500,
            /**
             * 选择对象Code集合, 目前只注册orguser,roleuser
             * @property objectCodes
             * @type Array(String)
             * @default [];
             * @requires
             */
            objectCodes: [],

            objects: [],
            /**
              * 多选值的分隔符
              * @property splitChar
              * @type {String}
              * @default ","
              */
            splitChar: ",",
            /**
              * 选择模式,单选还是多选. 0为多选, 1为单选
              * @property selectMode
              * @type Number
              * @default 0
              */
            selectMode: 0,
            /**
             * 默认值 .格式{name:"dd,dd1", value:"22,33"};
             * @property defaultValue 
             * @type {json}
             */
            defaultValue: null,
            /**
             * 联动名称控件,提供默认选中文本和选中完成后放置文本的控件
             * @property associatedNameControl
             * @type jQuery
             */
            associatedNameControl: null,
            /**
             * 联动值控件,提供默认选中值和选中完成后放置值的控件
             * @property associatedValueControl
             * @type jQuery
             */
            associatedValueControl: null,
            /**
              * 选择完成事件
              * @event onSelectedValue
              * @param {Array[json]} datas 返回选择的数据对象
              * @param {Json}   datas.data 单一数据对象
              * @param {String} datas.data.name 名称
              * @param {String} datas.data.value 值
              */
            onSelectedValue: null,
           /**
             * 关闭选择事件
             * @event onClose
             */
            onClose: null
        }, options);
        options.objects = options.objects || [];
        var objects = options.objects;
        if (options.objectCodes) {
            $.each(options.objectCodes, function (i, code) {
                objects.push({ code: code });
            });
        }

        if (objects.length == 0) {
            throw new Error(getRegional().notSetObjectCode);
        }

        


        var that = this;
        var inner = {
            self: this,
            options: options
        };
        
        inner.names = [];
        inner.values = [];
        
        var defaultName, defaultValue;
        if (options.defaultValue) {
            defaultName = options.defaultValue.name,
            defaultValue = options.defaultValue.value
        }
        else{
            if (options.associatedValueControl) {
                defaultValue = options.associatedValueControl.val();
            }
            if (options.associatedNameControl) {
                defaultName = options.associatedNameControl.val();
            }
        }
        if (defaultValue) {
            inner.names = (defaultName || "").splitRemoveEmptys(options.splitChar);
            inner.values = (defaultValue || "").splitRemoveEmptys(options.splitChar);
            if (inner.names.length != inner.values.length) {
                throw new Error(getRegional().defaultNamesLengthNotEqualValuesLength);
            }
        }
        
        inner.root = init(options, inner);
        inner.selectMode = options.selectMode == 1 ? g_SelectMode.SINGLE : g_SelectMode.MULTIPE;

        var events = {};

        /*
		* 执行事件
		* @method execEvent
		* @param {String} code 事件标识
		* @param {jQueryObject} target 触发事件源
		* @param {Object} [data] 事件数据
		*/
        this.execEvent = function (code, target, data) {
            var event = events[code];
            if (event) {
                event.fire(target, data, inner);
            }
            return true;
        };

        /*
		* 注册事件
		* @method registerEvent
		* @param {String} code 事件标识
		* @param {Fun} target 触发方法
		*/
        this.registerEvent = function (code, handle) {
            var event = events[code];
            if (!event) {
                event = $.Callbacks();
                events[code] = event;
            }
            event.add(handle);
        };


        /*
         * 获取或设置值
         * 
         */
        this.value = function (nodes) {
            if (nodes) {
                var names = $.map(nodes, function (n) { return n.name; })
                var values = $.map(nodes, function (n) { return n.value; })
                var value = {
                    name: names.join(options.splitChar),
                    value: values.join(options.splitChar),
                    names: names,
                    values: values,
                    nodes: nodes
                };
                if (options.associatedNameControl) {
                    options.associatedNameControl.val(value.name);
                }
                if (options.associatedValueControl) {
                    options.associatedValueControl.val(value.value);
                }
                if (options.onSelectedValue) {
                    options.onSelectedValue(value);
                }
            } else {
                var $items = $(".opicker-selector ul li", inner.root);
                var selectNodes = [];
                $items.each(function (index) {
                    var $this = $(this);
                    var node = $.extend(true, {}, $this.data("node"), {});
                    selectNodes.push(node);
                });

                return selectNodes;
            }
        };


        // #region 注册订阅事件

        // 注册订阅事件:删除已选中的项目
        this.registerEvent("removeSelectedItemed", removeSelectedItemed);
        // 注册订阅事件: 删除已选中的项目
        this.registerEvent("removeSelectedIteming", function (target, data, inner) {
            // 清除ztree的选中节点
            var $root = inner.root;
            var $currentTab = $("div.tab-item.current", $root);
            var ztreeObject = $.fn.zTree.getZTreeObj($("ul.ztree", $currentTab).attr("id"));
            checkZTreeNode(ztreeObject, target.data("value"), false, true);
        });

        // 注册事件:移动中已选中的项目
        this.registerEvent("moveSelectedIteming", function (target, command, inner) {
            return true;
        });

        // 注册事件:移动后已经选中的项目
        this.registerEvent("moveSelectedItemed", function (target, command, inner) {

        });

        // 注册事件:清空所有已选中的项目
        this.registerEvent("clearSelectedItem", clearSelectedItem);

        

        // 注册事件:插入一个选中项目
        this.registerEvent("insertItem", function (target, node, inner) {
            var $root = inner.root;
            var $selector = $(".opicker-selector", $root);
            var $ul = $("ul", $selector);
            var $item = renderSelectItem(node);
            $ul.append($item);

            var opicker = inner.self;
            opicker.execEvent("selectedChanged");
        });

        // 注册事件:删除一个选中项目
        this.registerEvent("removeItem", function (target, node, inner) {
            var $root = inner.root;
            var $selector = $(".opicker-selector", $root);
            var $ul = $("ul", $selector);
            $("li[data-value='{value}']".bformat(node), $ul).remove();

            var opicker = inner.self;
            opicker.execEvent("selectedChanged");
        });

        // 注册事件:清空所有选中的项目
        this.registerEvent("clearItem", function (target, data, inner) {
            var opicker = inner.self;
            opicker.execEvent("clearSelectedItem", null, inner);

            opicker.execEvent("selectedChanged");
        });

        // 注册事件:选中元素变更
        this.registerEvent("selectedChanged", function (target, data, inner) {
            var $root = inner.root;
            
            changeSelectedCount($root);
        });


        this.registerEvent("getOPickerValue", function (target, data, inner) {
            var value = that.value();
            that.value(value);
        });


        // #region Tab事件

        /*
         * Tab切换后事件
         * @event tabChanged
         * @param {jQuery} target 当前切换的Tab导航元素
         * @param {null} data 无数据
         */
        this.registerEvent("tabChanged", function (target, data, inner) {
            // 设置当前Ztree选中节点
            var ztree = getCurrentTabZTree(inner.root);
            setZTreeDefaultSelectedNodes(ztree, inner.values, false);
        })

        /*
         * Tab切换前事件
         * @event tabChanged
         * @param {jQuery} target 当前切换的Tab导航元素
         * @param {null} data 无数据
         */
        this.registerEvent("tabChanging", function (target, data, inner) {

        })

        // #endregion

        // #endregion


        bindEvent(inner);
    }


    /*
     * 初始化
     * @method init
     * @param {Json} options 选项
     * @param {Object} inner opicker内部对象
     *    
     */
    function init(options, inner) {
        var opicker = inner.self;
        var html = buildHtml(options);
        var $root = $(html);
        var dialog = B.Web.WindowManager.create({
            id: options.id,
            title: options.title,
            width: options.width,
            height: options.height,
            shadow: true,
            data: {
                inner: inner
            },
            onClose: function () {
                if (options.onClose) {
                    options.onClose();
                }
            },
            buttons: [{
                text: "<i class='fa fa-check'></i>{0}".bformat(getRegional().buttons.ok),
                events: {
                    click: function () {
                        var dialog = Beyondbit.Web.WindowManager.findByID(options.id);
                        var inner = dialog.Data.inner;
                        var opicker = inner.self;
                        opicker.execEvent("getOPickerValue", null);
                        B.Web.WindowManager.findByID(options.id).close();
                        return false;
                    }
                }
            }, {
                text: "<i class='fa fa-trash'></i>{0}".bformat(getRegional().buttons.clear),
                events: {
                    click: function () {
                        var dialog = Beyondbit.Web.WindowManager.findByID(options.id);
                        var inner = dialog.Data.inner;
                        var opicker = inner.self;
                        opicker.execEvent("clearSelectedItem", $(this));
                        return false;
                    }
                }
            }, {
                text: "<i class='fa fa-remove'></i>{0}".bformat(getRegional().buttons.cancel),
                events: {
                    click: function () {
                        Beyondbit.Web.WindowManager.findByID(options.id).close();
                        return false;
                    }
                }
            }]
        });
        dialog.setOptions({
            content: $root,
            title: options.title,
            width: options.width,
            height: options.height
        });
        dialog.Data.inner = inner;
        dialog.show();

        if ($root.find("div.opicker-tree-direction").css("display") == "none") {
            $root.find("div.tab").removeClass("tab-vertical");
        } else {
            $root.find("div.tab").addClass("tab-vertical");
        }

        return $root;
    }

    // #region 绑定事件


    /*
     * 绑定事件
     * @param {Json} inner 内部对象
     * @param {opicker} inner.self opicker对象本身this
     * @param {jQueryObject} inner.root opicker指向的根元素元素
     *    
     */
    function bindEvent(inner) {
        var that = inner.self;
        var $root = inner.root;
        bindSelectedItemEvent($root, inner);
        bindMoveSelectedItemEvent($root, inner);
        bindDefaultItem($root, inner);
        addTab($root, inner);
    }

    /*
     * 绑定默认元素
     */
    function bindDefaultItem($root, inner) {
        var $selector = $(".opicker-selector", $root);
        var $ul = $("ul", $selector);

        $.each(inner.values, function (index, value) {
            var node = {
                name: inner.names[index],
                value: value
            };
            $ul.append(renderSelectItem(node));
        });

        changeSelectedCount($root);
    }


    function bindSelectedItemEvent($root, inner) {
        var opicker = inner.self;
        var $selector = $(".opicker-selector", $root);
        var $ul = $("ul", $selector);
        
        $ul.click(function (event) {
            var $target = $(event.target);
            if ($target.is("i")) {
                /*
                 * 绑定删除元素Item事件
                 */
                var $li = $target.parent();
                var result = opicker.execEvent("removeSelectedIteming", $li);
                if (result == true) {
                    $li.remove();
                }
                var result = opicker.execEvent("removeSelectedItemed", $li);
                return false;
            } else if ($target.is("li")) {
                /*
                 * 绑定选中元素的点击事件
                 */
                var $li = $target;
                var result = opicker.execEvent("clickSelectedItemed", $li);
                if (result == true) {
                    $li.addClass("selected").siblings(".selected").removeClass("selected");
                }
            }

        });
    }

    /*
     * 绑定移动选中元素事件
     */
    function bindMoveSelectedItemEvent($root, inner) {
        var opicker = inner.self;
        var $selector = $(".opicker-selector", $root);
        var controls = $("div.scontrol a[data-control]", $selector);
        var ul = $("ul", $selector);
        controls.click(function () {
            var $this = $(this);
            var $items = $("li", ul);
            var $selected = $items.filter(".selected");
            if ($selected.length == 0) {
                return false;
            }
            var index = $items.index($selected);
            var command = $this.data("control");

            /*
             * event 
             * 移动选中元素
             * @param {String} code = moveSelectedItem
             * @param {target} target = 选中的元素
             * @param {String} data = command[up,down] 向上移动还是向下移动
             */
            var result = opicker.execEvent("moveSelectedIteming", $selected, command);
            if (result != true) {
                return false;
            }
            if (command == "up") {
                if (index == 0) {
                    return false;
                }
                var $prev = $selected.prev();
                var $temp = $selected.detach();
                $prev.before($temp);

            } else if (command == "down") {
                if (index == $items.length - 1) {
                    return false;
                }
                var $next = $selected.next();
                var $temp = $selected.detach();
                $next.after($temp);
            }

            /*
            * event 
            * 已经移动完成选中元素
            * @param {String} code = moveSelectedItemed
            * @param {target} target = 选中的元素
            * @param {String} data = command[up,down] 向上移动还是向下移动
            */
            opicker.execEvent("moveSelectedItemed", $selected, command);
            return false;
        });
    }

    // #endregion
    

    // 添加Tab标签
    function addTab($root, inner) {
        var opicker = inner.self;
        var options = inner.options;
        var objects = options.objects;
        var $tab = $(".tab", $root),
            $tabNav = $(".tab-nav", $tab),
            $tabContent = $(".tab-content", $tab);

        $.each(objects, function (index, object) {
            object.config = object.config || {};
            var code = object.code;
            var service = B.OPicker.getService(code);
            $tabNav.append('<li>{0}</li>'.bformat(object.title || service.title));
            var $tabItem = $('<div class="tab-item"><div class="opicker-dock">'
                + '<ul class="ztree" id="opicker_ztree_{0}_{1}"></ul></div></div>'.bformat(code, B.getIdentity()));

            $tabContent.append($tabItem);
            $tabItem.data("service-object", object);
        });

        $tabNav.find(">li").each(function (index) {
            $(this).click(function () {
                var $tabItem = $tabContent.find(".tab-item").eq(index);
                if ($tabItem.data("service-init") != true) {
                    var serviceObject = $tabItem.data("service-object");
                    var service = B.OPicker.getService(serviceObject.code);
                    bindTabItem($tabItem, service, serviceObject, inner);
                    $tabItem.data("service-init", true);
                }

                // 注册Tab切换前事件
                opicker.execEvent("tabChanging", $this);

                var $this = $(this);
                $this.addClass("current").siblings(".current").removeClass("current");
                $tabItem.addClass("current")
                    .siblings(".current").removeClass("current");

                // 注册Tab切换后事件
                opicker.execEvent("tabChanged", $this);
            });
        }).eq(0).trigger("click");
    }


    function bindTabItem($tabItem, service, serviceObject, inner) {
        var treeSetting = {
            async: {
                enable: true,
                url: service.getUrl.call(service, serviceObject.config),
                param: ["value=code"]
            },
            showIcon: service.showIcon,
            dataFilter: service.dataFilter,
            serviceObject: serviceObject,
            service: service
        };
        var source = treeSetting.service.getStaticDataSource.call(treeSetting.service, treeSetting.serviceObject.config, treeSetting.serviceObject);
        if (!source) {
            treeSetting.isAsync = true;
        } else {
            source = formatSource(source, serviceProcessDataItemFun(treeSetting));
        }

        var setting = getTreeSetting(inner, treeSetting);
        $.fn.zTree.init($("ul.ztree", $tabItem), setting, source);

        bindTabItemQuickSearch($tabItem, service,serviceObject, inner);
    }

    /*
     * 绑定Tab 选择快捷搜索功能和事件
     */
    function bindTabItemQuickSearch($tabItem, service, serviceObject,inner) {
        var searchUrl = service.getSearchUrl(serviceObject.config);
        if (!searchUrl) {
            return;
        }
       
        $tabItem.prepend('<dl class="opicker-quicksearch"><dt>{title}:<dt><dd><input placeholder="{placeholder}" title="{placeholder}" type="text" name="key" /></dd><dd class="opicker-quicksearch-result hide" hidefocus="true"  tabIndex="8889"><ul></ul></dd></dl>'.bformat(getRegional().search));

        $tabItem.css("overflow", "hidden");
        var $quickSearch = $(".opicker-quicksearch", $tabItem);
        var $quickSearchResult = $(".opicker-quicksearch-result", $tabItem);

        $(".opicker-dock", $tabItem).height($tabItem.parent().height() - $quickSearch.outerHeight());
       
        
        $("ul", $quickSearch).click(function (event) {
            var $this = $(this);
            var $target = $(event.target);

            if ($target.is("li")) {
                var $li = $target;
                if (!$li.hasClass("noSelect")) {
                    $li.addClass("selected");
                    var nodedata = convertNodeModel($li.data("data"));
                    selectNodeSaveData.call(inner, nodedata, true);
                }
            }
        });

        var timeoutSearchKey, intervalQuickSearchResult;

        $quickSearchResult.blur(function () {
            quickSearchVisibility(false);
        }).focus(function () {
            quickSearchVisibility(true);
        });

        

        $(":input[name=key]", $quickSearch).focus(function () {
            quickSearchVisibility(true);
        }).blur(function () {
            if (intervalQuickSearchResult) {
                clearInterval(intervalQuickSearchResult);
            }
            intervalQuickSearchResult = setInterval(function () {
                quickSearchVisibility(false);
            }, 300);
        }).on("input propertychange", function () {
            var $this = $(this);
            if (timeoutSearchKey != null) {
                clearTimeout(timeoutSearchKey);
            }
            if ($this.val() - 0 == 0) {
                setQuickSearchResult(null);
                return;
            }

            timeoutSearchKey = setTimeout(function () {
                var key = $this.val();
                startQuickSearch(key);
            }, 300);
        });

        
        var requestIndex = 1, responseIndex = 1;
        function startQuickSearch(key) {
            requestIndex = requestIndex + 1;
            var data = {
                keywords: key,
                requestIndex: requestIndex
            };

            data[B.Tenant.ACCESS_TOKEN_IDENTITY] = B.Tenant.getCurrentAccessToken();

            $.ajax({
                url: searchUrl,
                data: data,
                dataType: "jsonp",
                success: function (result) {
                    if (responseIndex <= result.requestIndex) {
                        setQuickSearchResult(result.data);
                        responseIndex = result.requestIndex;
                    }
                }
            });
        }

        function setQuickSearchResult(data) {
            var html = '';
            if (data && data.length > 0) {
                var data = formatSource(data);
                html = $.map(data, function (item) {
                    var $li = $('<li data-name="{name}" title="{tip}" data-value="{value}">{text}</li>'.bformat(item));
                    $li.data("data", item);
                    return $li;
                });
            }
            $quickSearchResult.find("ul").html(html);
        }

        function quickSearchVisibility(is) {
            if (intervalQuickSearchResult) {
                clearInterval(intervalQuickSearchResult);
            }
            if (is) {
                $quickSearchResult.removeClass("hide").show();
            } else {
                $quickSearchResult.hide();
            }
        }
    }

    /*
     * 构建opicker Html
     */
    function buildHtml(options) {
        var html = ''
		+ '<div class="opicker">'
        + '    <div class="opicker-tree">'
        +'         <div class="opicker-tree-direction"></div>'
        + '        <div class="tab tab-vertical">'
        + '            <ul class="tab-nav"></ul>'
        + '            <div class="tab-content"></div>'
        + '        </div>'
        + '    </div>'
        + '    <div class="opicker-selector">'
        + '        <div class="sbody">'
        + '            <h4>'+ getRegional().select.selected +':<strong>0</strong></h4>'
        + '            <div class="scontrol">'
        + '                <a href="#" class="btn btn-img" data-control="up" title="'+getRegional().select.up+'">'
        + '                    <i class="fa fa-arrow-circle-up "></i>'
        + '                    <em>' + getRegional().select.up + '</em>'
        + '                </a>'
        + '                <a href="#" class="btn btn-img" data-control="down" title="' + getRegional().select.down + '">'
        + '                    <i class="fa fa-arrow-circle-down"></i>'
        + '                    <em>' + getRegional().select.down + '</em>'
        + '                </a>'
        + '            </div>'
        + '            <ul></ul>'
        + '        </div>'
        + '    </div>'
        + '    <div class="clearfix"></div>'
        + '</div>'
        return html;
    }


    // #region ZTree

    /*
     * 服务处理数据
     */
    function serviceProcessDataItemFun(treeSetting) {
        return function (item) {
            return treeSetting.dataFilter(item, treeSetting.serviceObject.config, treeSetting.serviceObject);
        };
    }

    function serviceShowIcon(treeSetting) {
        return function (treeId, treeNode) {
            return treeSetting.showIcon(treeNode, treeId, treeSetting.serviceObject.config, treeSetting.serviceObject);
        }
    }

    /*
     * 获取zTreeSetting
     */
    function getTreeSetting(inner, treeSetting) {
        var options = inner.options;
        var zTreeObject;
        var selectMode = inner.selectMode;
        var setting = {
            view: {
                showIcon: serviceShowIcon(treeSetting)
            },
            async: {
                enable: true,
                autoParam: ["id", "name", "value"],
                dataFilter: function (treeId, parentNode, childNodes) {
                    if (!childNodes || childNodes.length == 0) {
                        return null;
                    }
                    childNodes = formatSource(childNodes, serviceProcessDataItemFun(treeSetting));
                    setSelectNode(childNodes, inner.values);
                    return childNodes;
                }
            },
            check: {
                enable: true,
                chkboxType: {
                    "Y": "",
                    "N": ""
                }
            },
            data: {
                simpleData: {
                    enable: true
                }
            },
            callback: {
                onCheck: function zTreeOnCheck(event, treeId, treeNode) {
                    if (options.selectMode == 2) {
                        recursiveFindParentSaveData.call(inner, treeNode.checked, treeNode);
                    }
                    else {
                        var nodedata = convertNodeModel(treeNode);
                        var checked = treeNode.checked;
                        selectNodeSaveData.call(inner, nodedata, treeNode.checked)
                        if (checked) {
                            if (selectMode == g_SelectMode.SINGLE) {
                                var zTreeObject = $.fn.zTree.getZTreeObj(treeId);
                                zTreeObject.checkNode(treeNode, true, true, false);
                            }
                            addSelectedNode(nodedata);
                        } else {
                            deleteSelectedNode(nodedata);
                        }
                        
                    }
                },
                beforeClick: function (treeId, treeNode, clickFlag) {
                    var zTreeObject = $.fn.zTree.getZTreeObj(treeId);
                    if (treeNode.isParent == true && treeNode.nocheck == true) {
                        zTreeObject.expandNode(treeNode);
                    }
                    else {
                        zTreeObject.checkNode(treeNode, null, true, true);
                    }
                    return false;
                },
                beforeAsync: function (treeId, treeNode) {
                    return !treeNode || treeNode.hasChilds != false;
                },
                onExpand: function (event, treeId, treeNode) {
                    if (options.selectMode == 2) {
                        if (treeNode.checked) {
                            recursiveSetChildsChecked(treeNode, true);
                        }
                    }
                }
            }
        };

        setZTreeAsyncSetting(treeSetting, setting);
        

        if (options.showIcon) {
            setting.view.showIcon = function (treeId, treeNode) {
                return options.showIcon(treeNode);
            }
        }

        return setting;
    }

    /*
     * 设置ZTree的异步设置 
     */
    function setZTreeAsyncSetting(treeSetting, setting) {
        if (treeSetting.isAsync) {

            setting.async.enable = true;
            setting.async.url = treeSetting.async.url;
            setting.async.dataType = "jsonp";
            setting.async.cache = true;

            var otherParam = treeSetting.async.otherParam || [];
            var accessToken = B.Tenant.getCurrentAccessToken();
            if (accessToken) {
                otherParam.push(B.Tenant.ACCESS_TOKEN_IDENTITY);
                otherParam.push(accessToken);
            }

            setting.async.otherParam = otherParam;

            if (treeSetting.async.param) {
                $.each(treeSetting.async.param, function (key, param) {
                    if ($.inArray(param, setting.async.autoParam) == -1) {
                        setting.async.autoParam.push(param);
                    }
                })
            }
        }
    }

    function addSelectedNode(node) {

    }

    function deleteSelectedNode(node) {

    }

    

    /*
	 * @description 选中Node后保存数据
	 * @param node {json} 数据包括name和value属性
	 * @param checked {Boolean} 是选中还是删除
	 */
    function selectNodeSaveData(node, checked) {
        var inner = this;
        var opicker = inner.self;
        var names = inner.names;
        var values = inner.values;
        var ni = Array.indexOf(names, node.name),
            vi = Array.indexOf(values,node.value);
        if (inner.selectMode == g_SelectMode.SINGLE) {
            opicker.execEvent("clearItem", null);
            if (checked) {
                values = [node.value];
                names = [node.name];
                opicker.execEvent("insertItem", null, node);
            } else {
                values = [];
                names = [];
            }
            inner.values = values;
            inner.names = names;
        } else {
            if (checked) {
                if (vi == -1) {
                    values.push(node.value);
                    opicker.execEvent("insertItem", null, node);
                }
                if (ni == -1) { names.push(node.name); }
            } else {
                if (vi != -1) {
                    values.splice(vi, 1);
                    opicker.execEvent("removeItem", null, node);
                }
                if (ni != -1) { names.splice(ni, 1); }
            }
        }
    }


    /*
     * 设置节点集合是否选中
     * @method setSelectNode
     * @param {ztreeNode} nodes 待设置的节点集合
     * @param {Array(String)} values 要设置的Node节点的值集合
     */
    function setSelectNode(nodes, values) {
        if (!nodes) { return; }
        $.each(nodes, function (index, node) {
            var ni = Array.indexOf(values, node.value);
            if (ni > -1) {
                node.checked = true;
            }
        });
    }


    /*
     * 清除当前Tab选中的Ztree节点
     */
    function clearCurrentTabZTree($root) {
        var ztree = getCurrentTabZTree($root);
        ztree.checkAllNodes(false);
    }

    /*
     * 获取当前选中Tab的Ztree
     */
    function getCurrentTabZTree($root) {
        var $currentTab = $("div.tab-item.current", $root);
        return $.fn.zTree.getZTreeObj($("ul.ztree", $currentTab).attr("id"));
    }

    /*
     * 设置ztree 默认选中的节点
     * @method setZTreeDefaultSelectedNodes
     * @param {ztree} ztree 要设置的ztree对象
     * @param {Array(String)} values 要设置的Node节点的值集合
     * @param {Boolean} [trigger=false] 是否触发Ztree事件
     * 
     */
    function setZTreeDefaultSelectedNodes(ztree, value, trigger) {
        trigger = trigger || false;
        ztree.checkAllNodes(false);

        if (!value) { return; }
        $.each(value, function (index, value) {
            checkZTreeNode(ztree, value, true, trigger);
        });
    }

    /*
     * 设置Ztree节点是否选中,根据node.value判断
     * @method checkZTreeNode
     * @param {ztree} ztree 要设置的ztree对象
     * @param {String} value 要设置的Node的值
     * @param {Boolean} checked 是否选中
     * @param {Boolean} [trigger=false] 是否触发Ztree事件
     */
    function checkZTreeNode(ztree, value, checked, trigger) {
        trigger = trigger || false;
        var znode = ztree.getNodeByParam("value", value);
        if (znode) {
            ztree.checkNode(znode, checked, true, trigger);
        }
    }

    /* selectMode=2时逻辑 */
    function recursiveFindParentSaveData(checked, treeNode) {
        if (checked) {
            var parent = treeNode.getParentNode();
            if (parent) {
                var isAllChecked = true;
                $.each(parent.children, function (index, node) {
                    if (node.checked == false) {
                        isAllChecked = false;
                        return false;
                    }
                });
                if (isAllChecked) {
                    setTreeNodeChecked(true, parent, false);
                    recursiveFindParentSaveData(checked, parent);
                } else {
                    setTreeNodeChecked(true, treeNode, true);
                }
            } else {
                setTreeNodeChecked(true, treeNode, true);
            };
        }
        else {
            setTreeNodeChecked(false, treeNode, true);
            recursiveFindParentSaveDataNoChecked(treeNode);
        }
    }
    function recursiveFindParentSaveDataNoChecked(treeNode) {
        var nodedata = convertNodeModel(treeNode);
        zTreeObject.checkNode(treeNode, false, false, false);
        deleteSelectedNode(nodedata);
        selectNodeSaveData(nodedata, false);
        var parent = treeNode.getParentNode();
        if (parent) {
            if (parent.checked == true) {
                $.each(parent.children, function (index, node) {
                    if (node.checked == true) {
                        var nodedata = convertNodeModel(node);
                        addSelectedNode(nodedata);
                        selectNodeSaveData(nodedata, true);
                    }
                });
                recursiveFindParentSaveDataNoChecked(parent);
            }
        }
    }
    function setTreeNodeChecked(checked, treeNode, isRecursive) {
        var nodedata = convertNodeModel(treeNode);
        if (checked) {
            zTreeObject.checkNode(treeNode, true, false, false);
            addSelectedNode(nodedata);
            selectNodeSaveData(nodedata, true);
            if (isRecursive == true) {
                recursiveSetChildsChecked(treeNode, true);
            }
        } else {
            zTreeObject.checkNode(treeNode, false, false, false);
            deleteSelectedNode(nodedata);
            selectNodeSaveData(nodedata, false);
            if (isRecursive == true) {
                recursiveSetChildsChecked(treeNode, false);
            }
        }
    }
    function recursiveSetChildsChecked(treeNode, checked) {
        var zTreeObject = this;
        var childs = treeNode.children;
        if (childs && childs.length > 0) {
            if (checked == true) {
                $.each(childs, function (index, node) {
                    var nodedata = convertNodeModel(node);
                    deleteSelectedNode(nodedata);
                    selectNodeSaveData(nodedata, false);
                    zTreeObject.checkNode(node, true, false, false);
                    recursiveSetChildsChecked(node, checked);
                });
            } else {
                $.each(childs, function (index, node) {
                    var nodedata = convertNodeModel(node);
                    deleteSelectedNode(nodedata);
                    selectNodeSaveData(nodedata, false);
                    zTreeObject.checkNode(node, false, false, false);
                    recursiveSetChildsChecked(node, checked);
                });
            }
        };
    }
    /* END selectMode=2时逻辑 */

    /*
     * 格式化数据源
     * @method formatSource
     * @param {Array(Json)} source 待格式化的数据
     * @param {Fun} [processDataItemFun] 处理数据的方法
     */
    function formatSource(source, processDataItemFun) {
        var zNodes = [];
        if (source) {
            if (processDataItemFun) {
                source = processDataItemFun(source);
            }
            $.each(source, function (index, item) {
                if (processDataItemFun) {
                    item = processDataItemFun(item);
                }
                var zNode = $.extend(true, {}, item, {
                    id: item.id || $.trim(item.value),
                    name: $.trim(item.name),
                    value: $.trim(item.value),
                    text: item.text || item.name,
                    pId: item.parentId,
                    open: item.open,
                    isParent: item.isParent
                });
                zNodes.push(zNode);
                var eachNode = function (item) {
                    if (item.nodes) {
                        $.each(item.nodes, function (index, node) {
                            if (processDataItemFun) {
                                node = processDataItemFun(node);
                            }
                            var znode = $.extend(true, {}, node, {
                                id: node.id || $.trim(node.value),
                                name: $.trim(node.name),
                                value: $.trim(node.value),
                                text: node.text || node.name,
                                pId: item.id,
                                open: item.open,
                                isParent: node.isParent
                            });
                            zNodes.push(znode);
                            eachNode(node);
                        });
                    };
                };
                eachNode(item);
            });
        }
        return zNodes;
    };

    /*
	 * 转换TreeNode为Node实体
	 * @method convertNodeModel
	 * @param {TreeNode} treeNode
	 */
    function convertNodeModel(treeNode) {
        return treeNode;
    };

    // #endregion

   /*
    * 生成一个选中的元素
    * @param {json} node
    * @returns jQuery
    * 
    */
    function renderSelectItem(node) {
        var $item = $('<li data-value="{value}"><i class="fa fa-remove"></i>{name}</li>'.bformat(node));
        $item.data("node", node);

        return $item;
    }

    /*
     * 变更已经选中的个数
     */
    function changeSelectedCount($root) {
        var $selector = $(".opicker-selector", $root);
        var items = $("ul li", $selector);
        $("div.sbody > h4 strong", $selector).html(items.length);
    }


    /*
     * 删除已经选择好的元素事件
     */
    function removeSelectedItemed(target, data, inner) {
        var opicker = inner.self;
        opicker.execEvent("selectedChanged", null);
    }

    /*
     * 清空选择的Item
     */
    function clearSelectedItem(target, data, inner) {
        inner.names = [];
        inner.values = [];

        var opicker = inner.self;
        var $selector = $(".opicker-selector", inner.root);
        var ul = $("ul", $selector);
        ul.html('');

        clearCurrentTabZTree(inner.root);

        opicker.execEvent("selectedChanged", null);
    }

    

})(jQuery, Beyondbit);

(function ($, B) {

    
    var _defaultServiceHost = "http://192.168.40.106/SharedService";
    // _defaultServiceHost = "http://localhost:2109";

    function getEntireServiceUrl(url) {
        if (url.indexOf("http://") == 0) {
            return url;
        }
        return (window.SharedServiceHost || _defaultServiceHost) + url;
    }


    var opicker = B.registerNameSpace("OPicker");

    opicker.regional["zh-CN"].services = {
        orgUser: {
            title: "按部门"
        },
        roleUser: {
            title: "按角色"
        },
        org: {
            title: "部门"
        },
        role: {
            title: "角色"
        },
        source: {
            title: "选择"
        },
        orgDeputy: {
            title: "选择机构代表",
            notConfigHierarchyCode: "没有配置hierarchyCode参数"
        }
    };

    function getRegional() {
        return opicker.regional[B.CultureInfo.Current.get()];
    }

    // #region 注册系统默认提供服务

    /**
     * 按部门选择用户服务
     * @class OrgUserService
     * 
     */
    opicker.registerService({
        code: "orguser",
       /**
         * 标题
         * @property title 
         * @type String
         * @default "按部门"
         */         
        title: getRegional().services.orgUser.title,
        /**
         * 配置
         * @property config
         * @type json
         */
        config: {
            /**
             * 是否显示根元素
             * @property config.isShowRoot
             * @type Boolean
             * @default false
             */
            isShowRoot: false,
            /**
             * 根部门Code
             * @property config.rootOrgCode
             * @type String
             */
            rootOrgCode: null
        },
        searchUrl: getEntireServiceUrl("/api/OrgAndUserQuery"),
        url: getEntireServiceUrl("/api/OrgAndUser"),
        dataFilter: function (item, config) {
            if (config.isShowRoot == true) {
                item.open = true;
            }
            if (item.isParent || (item.nodes != null && item.nodes.length > 0)) {
                item.nocheck = true;
            };
            return item;
        },
        getUrl: function (config, url) {
            var url = new B.Url(url || this.url);

            if (config.rootOrgCode) {
                url.appendKey("rootCode", config.rootOrgCode);
            }
            if (config.isShowRoot == true) {
                url.appendKey("isIncludeRoot", config.isShowRoot);
            }

            return url.toString();
        }
    });

    /**
     * 按角色选择用户服务
     * @class RoleUserService
     * 
     */
    opicker.registerService({
        code: "roleuser",
      /**
        * 标题
        * @property title 
        * @type String
        * @default "按角色"
        */
        title: getRegional().services.roleUser.title,
        /**
         * 配置
         * @property config
         * @type json
         */
        config: {
            /*
             * 是否显示根元素
             * @property config.isShowRoot
             * @type Boolean
             * @default false
             */
            isShowRoot: false,
            /**
             * 指定的角色Code
             * @property config.code
             * @type String
             */
            code: null,
            /**
             * 指定的App Code
             * @property config.appCode
             * @type String
             */
            appCode: null
        },
        url: getEntireServiceUrl("/api/RoleAndUser"),
        dataFilter: function (item, config) {
            if (item.isParent || (item.nodes != null && item.nodes.length > 0)) {
                item.nocheck = true;
            };
            return item;
        },
        getUrl: function (config, url) {
            var url = new B.Url(url || this.url);
            if (config.code) {
                url.appendKey("code", config.code);
            }
            if (config.appCode) {
                url.appendKey("appCode", config.appCode);
            }
            return url.toString();
        }
    });

    /**
     * 选择部门服务
     * @class OrgService
     * 
     */
    opicker.registerService({
        code: "org",
        /**
        * 标题
        * @property title 
        * @type String
        * @default "部门"
        */
        title: getRegional().services.org.title,
        /**
         * 配置
         * @property config
         * @type json
         */
        config: {
            /*
             * 是否显示根元素
             * @property config.isShowRoot
             * @type Boolean
             * @default false
             */
            isShowRoot: false,
            /**
             * 根部门Code
             * @property config.rootOrgCode
             * @type String
             */
            rootOrgCode: null
        },
        url: getEntireServiceUrl("/api/Org"),
        showIcon: function (item) {
            return false;
        },
        dataFilter: function (item, config) {
            if (config.isShowRoot == true) {
                item.open = true;
            }
            return item;
        },
        getUrl: function (config, url) {
            var url = new B.Url(url || this.url);

            if (config.rootOrgCode) {
                url.appendKey("rootCode", config.rootOrgCode);
            }
            if (config.isShowRoot == true) {
                url.appendKey("isIncludeRoot", config.isShowRoot);
            }

            return url.toString();
        }
    });


    /**
     * 选择角色服务
     * @class RoleService
     * 
     */
    opicker.registerService({
        code: "role",
        /**
          * 标题
          * @property title 
          * @type String
          * @default "按角色"
          */
        title: getRegional().services.role.title,
        /**
         * 配置
         * @property config
         * @type json
         */
        config: {
            /**
             * 指定的App Code
             * @property config.appCode
             * @type String
             */
            appCode: null
        },
        url: getEntireServiceUrl("/api/Role"),
        getUrl: function (config, url) {
            var url = new B.Url(url || this.url);

            if (config.appCode) {
                url.appendKey("appCode", config.appCode);
            }

            return url.toString();
        }
    });

  /**
    * 自定义数据源选择服务
    * @class SourceService
    * 
    */
    opicker.registerService({
        code: "source",
        title: getRegional().services.source.title,
      /**
        * 数据源
        * @property source
        * @type Array[Node]
        * @default []
        */
        source: [],
        /*
          * 配置
          * @property config
          * @type json
          */
        config: {
           
        },
        getStaticDataSource: function (config, object) {
            return object.source;
        }
    });

    // #endregion


    // #region 机构代表服务

    opicker.registerService({
        code: "orgdeputy",
        title: getRegional().services.orgDeputy.title,
        url: getEntireServiceUrl("/OrgDeputy/Org"),
        config: {
            hierarchyCode: null
        },
        showIcon: function (item) {
            return false;
        },
        dataFilter: function (item, config) {
            if (config.isShowRoot == true) {
                item.open = true;
            }
            return item;
        },
        getUrl: function (config) {
            var url = new B.Url(this.url);

            if (!config.hierarchyCode) {
                throw Error(getRegional().services.orgDeputy.notConfigHierarchyCode);
            }
            url.appendKey("hierarchyCode", config.hierarchyCode);

            if (config.rootOrgCode) {
                url.appendKey("rootCode", config.rootOrgCode);
            }
            if (config.isShowRoot == true) {
                url.appendKey("isIncludeRoot", config.isShowRoot);
            }

            return url.toString();
        }
    })

    // #endregion

})(jQuery, Beyondbit);
    
Top