﻿ (function ($) {
     var defaults =
	{
	    container: null,                // родительский div, в котором будет формироваться дерево
	    clickDelegate: null,            // доп. обработчики клика по ноде
	    sqlprocedure: null,             // имя хранимой процедуры/ функции, к которой должен обращаться серверный код для получения нод след. ур-ня. 
	    url: null,                      // url, который вернет данные о нодах след. ур-ня
	    checkBoxes: false,              // нужно ли отображать чекбоксы у листьев
	    nodeIdPrefix: "item_",          // префикс, который будет использоваться при формировании ноды  \
	    nodeIdPostfix: "",              // постфикс, который будет использоваться при формировании ноды /   с помощью префикса и постфикса можно формировать уникальные для дерева id, используя, например, id контейнера.
	    workWithOnlyOneBranch: false,   // работа с одной веткой или с несколькими  
	    user_id: -1,
	    waitObject: null,                // объект wait screen
	    isAutoCat: 0
	}

     $.extend(
    {
        // конструктор дерева
        AndersenTreeView: function (target, options) {
            this.settings = $.extend({}, defaults, { container: target }, options || {})
            // подгружаем корневые ноды
            this.loadNodes(null);
        }
    })

     $.extend($.fn,
        {
            treeview: function (target, options) {
                return this.each(function () {
                    new $.Menu(this, options);
                });
            }
        }
    )
     var node = null;
     var itemId = null;
     var obj = this;
     var parentIdPrevious = 0;
     var count = 0;
     /* public методы */
     $.extend($.AndersenTreeView,
	{
	    prototype:
		{
		    saveTreeState: function () {
		        var self = this;

		        if (this.settings.container) {
		            var expandedNodes = new Array();
		            jQuery("li.collapsable", jQuery(this.settings.container)).each(
                        function () {
                            expandedNodes.push(self.toDomainId(this.id));
                        }
                    );

		            //SessionData.SetValue(_treeviewContainerId+"TreeState", expandedNodes);
		            var expireDate = new Date();
		            expireDate.setHours(expireDate.getHours() + 1);
		            $.cookie(this.settings.container + "_TreeState", expandedNodes.join(","), { expires: expireDate });
		            //$.cookie(this.settings.container + "_TreeStateSelectedDiv", null, { expires: expireDate});
		            $.cookie(this.settings.container + "_TreeStateSelectedDiv", jQuery("div.selected").parent().attr("id"), { expires: expireDate });
		            expandedNodes = null;
		        }
		    },



		    loadTreeState: function () {
		        if (this.settings.container) {
		            //var expandedNodes = SessionData.GetValue(_treeviewContainerId+"TreeState", null);
		            var expandedNodes = ($.cookie(this.settings.container + "_TreeState") || "").split(",");
		            var activeNode = ($.cookie(this.settings.container + "_TreeStateSelectedDiv") || "");

		            if (expandedNodes != null) {
		                for (i = 0; i < expandedNodes.length; i++) {
		                    //jQuery("#" + this.toDOMId(expandedNodes[i]) + ">div").click();
		                    this.toggleNodeState(jQuery("#" + this.toDOMId(expandedNodes[i])));
		                }
		            }

		            if (activeNode != "") {
		                jQuery("#" + activeNode + " div:first").addClass("selected");
		                this.settings.clickDelegate(this.toDomainId(activeNode));
		            }

		            expandedNodes = null;
		            activeNode = null;
		        }
		    },

		    // выбирает отмеченные ноды во всей ветке (Id из БД).
		    getCheckedItems: function (parentId) {
		        var self = this;

		        if (!parentId || !this.settings.checkBoxes) return null;

		        var checkedNodesId = new Array();

		        jQuery("." + parentId + " :checkbox:checked").parent().each(
                    function () {
                        //debugger;
                        checkedNodesId.push(self.toDomainId($(this).parent().attr("id")));
                    }
                );

		        return checkedNodesId;
		    },

		    // id элемента DOM переводит в Id, который был получен с сервера
		    toDomainId: function (domId) {
		        var prefixLength = this.settings.nodeIdPrefix.length;
		        var postfixLength = this.settings.nodeIdPostfix.length;
		        return domId.substr(prefixLength, domId.length - (prefixLength + postfixLength));
		    },

		    // формирует id для записи в DOM
		    toDOMId: function (domainId) {
		        return this.settings.nodeIdPrefix + domainId + this.settings.nodeIdPostfix;
		    },

		    appendNodesTo: function (object, jsonNodes, parentId) {
		        var self = this;
//		        debugger;
		        if (jsonNodes.length > 0) {
		            object.append("<ul></ul>");
		            object = jQuery("ul", object);

		            for (var i = 0; i < jsonNodes.length; i++) {
		                if (parentId == null) { parentId = 0; }
		                // формируем ноду
		                var node = jsonNodes[i];
		                var checks = '';

		                if (this.settings.checkBoxes) {
		                    var disabled = 'disabled';
		                    if ($('input.searchinnode').length != 0) {
		                        if ($('input.searchinnode').attr('checked')) {
		                            disabled = '';
		                        }
		                    }
		                    checks = "<input class='inputcheck' type='checkbox' style='display:inline;float:none;' " + disabled + " />";
		                }
		                if (this.settings.isAutoCat == 0) {
		                    if (node.HasChilds == '1') {
		                        //object.append("<li class='expandable childless' childsLoaded='0' hasChilds='" + node.HasChilds + "' id='item_" + node.Id + "' ><div class='iconed'>" + node.Name + "</div></li>");
		                        object.append("<li class='expandable' childsLoaded='0' id='" + this.toDOMId(node.Id) + "'><div class='iconed'>" + checks + "<div class='containerimg'></div><div class='folderimg'></div><div class='containertext'>" + node.Name + "</div></div></li>");
		                    }
		                    else {
		                        if (this.settings.checkBoxes)
		                            object.append("<li class='childless' childsLoaded='0' id='" + this.toDOMId(node.Id) + "'><div class='iconed'>" + checks + "" + node.Name + "</div></li>");
		                        else
		                            object.append("<li class='childless' childsLoaded='0' id='" + this.toDOMId(node.Id) + "'><div class='iconed'>" + checks + "<div class='containerimg'></div><div class='containertext'>" + node.Name + "</div></div></li>");
		                    }
		                }

		                else
		                    if (this.settings.isAutoCat == 2) {
		                        if (node.HasChilds == '1') {
		                            //debugger;
		                            if (node.HasModelImage == '1') {
		                                object.append("<li class='expandable' childsLoaded='0' id='" + this.toDOMId(node.Id) + "' parentId='" + node.Parent_Id + "' ><div class='iconed'>" + checks + "<div class='containerimg'></div><div class='folderimg'></div><div class='containertext'>" + node.Name + "</div>&nbsp;&nbsp;<a href='javascript:GetModel(&quot;" + node.Map + "&quot;, &quot;" + node.Old_Id + "&quot;, &quot;" + node.Id + "&quot;)' nodeId='" + node.Id + "' class='smallimage'>&nbsp;&nbsp;&nbsp;&nbsp;</a></div></li>");
		                            }
		                            else {
		                                object.append("<li class='expandable' childsLoaded='0' id='" + this.toDOMId(node.Id) + "' parentId='" + node.Parent_Id + "' ><div class='iconed'>" + checks + "<div class='containerimg'></div><div class='folderimg'></div><div class='containertext'>" + node.Name + "</div></div></li>");
		                            }
		                        }
		                        else {
		                            //if (this.settings.checkBoxes)
		                            //    object.append("<li class='childless' childsLoaded='0' id='" + this.toDOMId(node.Id) + "' parentId='" + node.Parent_Id + "' ><div class='iconed'>" + checks + "<div class='containerimg'></div><div class='containertext'>" + node.Name + "</div>&nbsp;&nbsp;<a href='javascript:OpenFrame(" + node.Map + "," + node.Picture_Id + ",&quot;" + node.Id + "&quot;)' nodeId='" + node.Id + "' class='smallimage'>&nbsp;&nbsp;&nbsp;&nbsp;</a>&nbsp;&nbsp;&nbsp;&nbsp;</a></div></li>");
		                            //    object.append("<li class='childless' childsLoaded='0' id='" + this.toDOMId(node.Id) + "' parentId='" + node.Parent_Id + "' ><div class='iconed'>" + checks + "<div class='containerimg'></div><div class='containertext'>" + node.Name + "</div>&nbsp;&nbsp;<a href='javascript:OpenFrame(" + node.Map + "," + node.Picture_Id + ",&quot;" + node.Id + "&quot;)' nodeId='" + node.Id + "' class='smallimage'>&nbsp;&nbsp;&nbsp;&nbsp;</a></div></li>");
		                            //else {		                            
		                            object.append("<li class='childless' childsLoaded='0' id='" + this.toDOMId(node.Id) + "' parentId='" + node.Parent_Id + "' ><div class='iconed'>" + checks + "<div class='containerimg'></div><div class='containertext'>" + node.Name + "</div>&nbsp;&nbsp;<a href='javascript:OpenFrame(" + node.Map + "," + node.Picture_Id + ",&quot;" + node.Id + "&quot;)' nodeId='" + node.Id + "' class='smallimage'>&nbsp;&nbsp;&nbsp;&nbsp;</a>&nbsp;&nbsp;&nbsp;&nbsp;</a></div></li>");

		                            //}
		                        }
		                        if (node.HasDocumentation == '0') {
		                            //object.append("&nbsp;&nbsp;<a class='documentation' href='Document.htm'></a>");
		                        }
		                    }



		                    else {
		                        //debugger;
		                        if (node.HasChilds == '1') {
		                            //debugger;
		                            if (node.HasModelImage == '1') {
		                                if (node.HasDocumentation == '0') {
		                                    object.append("<li class='expandable' childsLoaded='0' id='" + this.toDOMId(node.Id) + "' parentId='" + node.Parent_Id + "' ><div class='iconed'>" + checks + "<div class='containerimg'></div><div class='folderimg'></div><div class='containertext'>" + node.Name + "</div>&nbsp;&nbsp;<a href='javascript:GetModel(&quot;" + node.Map + "&quot;, &quot;" + node.Old_Id + "&quot;, &quot;" + node.Id + "&quot;)' nodeId='" + node.Id + "' class='smallimage'>&nbsp;&nbsp;&nbsp;&nbsp;</a></div></li>");
		                                }
		                                else
		                                    if (node.HasDocumentation == '1') {
		                                        object.append("<li class='expandable' childsLoaded='0' id='" + this.toDOMId(node.Id) + "' parentId='" + node.Parent_Id + "' ><div class='iconed'>" + checks + "<div class='containerimg'></div><div class='folderimg'></div><div class='containertext'>" + node.Name + "</div>&nbsp;&nbsp;<a href='javascript:GetModel(&quot;" + node.Map + "&quot;, &quot;" + node.Old_Id + "&quot;, &quot;" + node.Id + "&quot;)' nodeId='" + node.Id + "' class='smallimage'>&nbsp;&nbsp;&nbsp;&nbsp;</a>&nbsp;&nbsp;<a class='documentation'  nodeId='" + node.Id + "' href='Documentation.htm'>&nbsp;&nbsp;&nbsp;&nbsp;</a></div></li>");
		                                    }

		                            } else {
		                                if (node.HasDocumentation == '0') {
		                                    object.append("<li class='expandable' childsLoaded='0' id='" + this.toDOMId(node.Id) + "' parentId='" + node.Parent_Id + "' ><div class='iconed'>" + checks + "<div class='containerimg'></div><div class='folderimg'></div><div class='containertext'>" + node.Name + "</div></div></li>");
		                                }
		                                else
		                                    if (node.HasDocumentation == '1') {
		                                        object.append("<li class='expandable' childsLoaded='0' id='" + this.toDOMId(node.Id) + "' parentId='" + node.Parent_Id + "' ><div class='iconed'>" + checks + "<div class='containerimg'></div><div class='folderimg'></div><div class='containertext'>" + node.Name + "</div>&nbsp;&nbsp;<a class='documentation' nodeId='" + node.Id + "' href='Documentation.htm'>&nbsp;&nbsp;&nbsp;&nbsp;</a></div></li>");
		                                    }
		                            }
		                        }
		                        else {
		                            //if (this.settings.checkBoxes)
		                            //    object.append("<li class='childless' childsLoaded='0' id='" + this.toDOMId(node.Id) + "' parentId='" + node.Parent_Id + "' ><div class='iconed'>" + checks + "<div class='containerimg'></div><div class='containertext'>" + node.Name + "</div>&nbsp;&nbsp;<a href='javascript:OpenFrame(" + node.Map + "," + node.Picture_Id + ",&quot;" + node.Id + "&quot;)' nodeId='" + node.Id + "' class='smallimage'>&nbsp;&nbsp;&nbsp;&nbsp;</a>&nbsp;&nbsp;&nbsp;&nbsp;</a></div></li>");
		                            //    object.append("<li class='childless' childsLoaded='0' id='" + this.toDOMId(node.Id) + "' parentId='" + node.Parent_Id + "' ><div class='iconed'>" + checks + "<div class='containerimg'></div><div class='containertext'>" + node.Name + "</div>&nbsp;&nbsp;<a href='javascript:OpenFrame(" + node.Map + "," + node.Picture_Id + ",&quot;" + node.Id + "&quot;)' nodeId='" + node.Id + "' class='smallimage'>&nbsp;&nbsp;&nbsp;&nbsp;</a></div></li>");
		                            //else {
		                            if (node.HasDocumentation == '0') {
		                                object.append("<li class='childless' childsLoaded='0' id='" + this.toDOMId(node.Id) + "' parentId='" + node.Parent_Id + "' ><div class='iconed'>" + checks + "<div class='containerimg'></div><div class='containertext'>" + node.Name + "</div>&nbsp;&nbsp;<a href='javascript:OpenFrame(" + node.Map + "," + node.Picture_Id + ",&quot;" + node.Id + "&quot;)' nodeId='" + node.Id + "' class='smallimage'>&nbsp;&nbsp;&nbsp;&nbsp;</a>&nbsp;&nbsp;&nbsp;&nbsp;</a></div></li>");
		                            }
		                            else
		                                if (node.HasDocumentation == '1') {
		                                    object.append("<li class='childless' childsLoaded='0' id='" + this.toDOMId(node.Id) + "' parentId='" + node.Parent_Id + "' ><div class='iconed'>" + checks + "<div class='containerimg'></div><div class='containertext'>" + node.Name + "</div>&nbsp;&nbsp;<a href='javascript:OpenFrame(" + node.Map + "," + node.Picture_Id + ",&quot;" + node.Id + "&quot;)' nodeId='" + node.Id + "' class='smallimage'>&nbsp;&nbsp;&nbsp;&nbsp;</a>&nbsp;&nbsp;&nbsp;&nbsp;</a>&nbsp;&nbsp;<a class='documentation' nodeId='" + node.Id + "' href='Documentation.htm'>&nbsp;&nbsp;&nbsp;&nbsp;</a></div></li>");
		                                }

		                            //}
		                        }
		                        if (node.HasDocumentation == '0') {
		                            //object.append("&nbsp;&nbsp;<a class='documentation' href='Document.htm'></a>");
		                            /*
		                            jQuery(".documentation", object).click(function () {
		                            debugger;
		                            $.cookie("nodeDocumentationId", jQuery(this).attr("nodeId"));
		                            });
		                            */

		                        }

		                    }
		            }

		            jQuery(".documentation", object).click(function () {
		                $.cookie("nodeDocumentationId", jQuery(this).attr("nodeId"));
		            });

		            jQuery("div", object).click(function (e) {
		                // вызываем ф-ю в контексте данного объекта
		                self.nodeClick(e, false); //.call(self, e);
		            }
                    );
		            jQuery("div", object).bind("dblclick", function (e) {
		                // вызываем ф-ю в контексте данного объекта                            
		                self.nodeDblClick(e, true); //.call(self, e);
		            }
                    );
		        }
		    },

		    loadNodes: function (parentId, previous) {
		        var self = this;

		        if (!this.settings.url)
		            return;

		        $.ajax(
                    {
                        type: "GET",
                        async: false,
                        url: this.settings.url,
                        data: { parentid: parentId, parentidprevious: previous, procedure: this.settings.sqlprocedure, userid: this.settings.user_id, isautocat: this.settings.isAutoCat },
                        success: function (json) {
                            if (parentId == null)
                                self.appendNodesTo(jQuery(self.settings.container), json, parentId);
                            else
                                self.appendNodesTo(jQuery("#" + self.toDOMId(parentId)), json, parentId);
                        },
                        dataType: "json",
                        error: function (text) { debugger; alert(text); }
                    }
                );
		        //parentIdPrevious = parentId.split('t')[1];

		    },

		    /*
		    node - обернутый li, представляющий ноду
		    itemDomainId - id ноды в формате БД
		    */
		    toggleNodeState: function (node, itemDomainId) {
		        //debugger;
		        if (node.length != 1) return;

		        if (!itemDomainId) itemDomainId = this.toDomainId(node.attr("id"));


		        if (node.hasClass("collapsable")) {
		            // если есть что скрывать - скрываем
		            jQuery("ul", node).hide();
		            node.attr("class", "expandable");
		        }
		        else {
		            if (node.attr("class") != "childless") {
		                if (node.attr("childsLoaded") == '0') {
		                    this.loadNodes(itemDomainId, node.attr('parentId'));
		                    node.attr("childsLoaded", '1');
		                }
		                else {
		                    jQuery("ul:first", node).show();
		                }

		                node.attr("class", "collapsable");
		            }
		        }
		    },
		    start: function () {
		        obj.toggleNodeState(node, itemId);
		    },
		    nodeClick: function (e, isdblclick) {
		        count++;
		        if (count == 1) { return; }
		        if (count == 2) { count = 0; }
		        if (jQuery("#fromtree").length > 0) {
		            jQuery("#fromtree").val("1");
		        }
		        // находим li, в который обрамлен div (обработчики на спанах)
		        var target = (new BrowserDetect().browser == "Explorer") ? e.srcElement : e.target;
		        //Для определения нажатия на контейнер
		        var flag = false;
		        if ((jQuery(target).attr("class")).indexOf("iconed") != -1) { node = jQuery(target).parent(); flag = true; }
		        else { node = jQuery(target).parent().parent(); }

		        itemId = this.toDomainId(node.attr("id"));
		        obj = this;
		        //debugger;
		        if (node.attr("class") != "collapsable" && node.attr("class") != "expandable" || (jQuery(target).attr("class") == "containerimg")) {
		            // (ра)скрываем узел 
		            if ((jQuery(target).attr("class") == "containerimg") || (node.attr("class") != "collapsable" && jQuery(target).attr("class") == "containertext") || flag) {
		                jQuery().oneTime("1s", this.start);
		                if (this.settings.workWithOnlyOneBranch/* && node.hasClass("collapsable")*/) {
		                    var self = this;
		                    jQuery(this.settings.container + " li.collapsable")                      // Из набора всех раскрытых нод исключаем
                                .not(node)                                                      // ноду, которую только что раскрыли
                                .not(node.parents(this.settings.container + " li.collapsable")) // и всех ее родителей.
                                .each(function () { self.toggleNodeState(jQuery(this)); });           // Закрываем все оставшиеся ноды.
		                }
		            }
		        }
		        // поддерживаем выделение кликнутых нод
		        if (this.settings.workWithOnlyOneBranch) {
		            jQuery('div.selected').removeClass("selected");
		            //debugger;                                        
		            node.find('div:first').addClass("selected");
		        }
		        // подтягиваем функции делегаты
		        if (jQuery(target).attr("class") == "containertext" || flag) {
		            if (this.settings.clickDelegate != null) {
		                this.settings.clickDelegate(itemId);
		                if (jQuery("#fromtree").length > 0) {
		                    jQuery("#fromtree").val("0");
		                }
		            }
		        }
		    },
		    nodeDblClick: function (e, isdblclick) {
		        if (jQuery("#fromtree").length > 0) {
		            jQuery("#fromtree").val("1");
		        }
		        // находим li, в который обрамлен div (обработчики на спанах)
		        var target = (new BrowserDetect().browser == "Explorer") ? e.srcElement : e.target;
		        //Для определения нажатия на контейнер
		        var flag = false;
		        if ((jQuery(target).attr("class")).indexOf("iconed") != -1) { node = jQuery(target).parent(); flag = true; }
		        else { node = jQuery(target).parent().parent(); }
		        //if(node.attr("class") != "childless") {                
		        itemId = this.toDomainId(node.attr("id"));
		        obj = this;
		        // (ра)скрываем узел 
		        if ((jQuery(target).attr("class") == "containerimg") || (node.attr("class") != "collapsable" && jQuery(target).attr("class") == "containertext") || flag) {
		            jQuery().oneTime("1s", this.start);
		            if (this.settings.workWithOnlyOneBranch/* && node.hasClass("collapsable")*/) {
		                var self = this;
		                jQuery(this.settings.container + " li.collapsable")                      // Из набора всех раскрытых нод исключаем
                                .not(node)                                                      // ноду, которую только что раскрыли
                                .not(node.parents(this.settings.container + " li.collapsable")) // и всех ее родителей.
                                .each(function () { self.toggleNodeState(jQuery(this)); });           // Закрываем все оставшиеся ноды.
		            }
		        }
		        // поддерживаем выделение кликнутых нод
		        if (this.settings.workWithOnlyOneBranch) {
		            jQuery('div.selected').removeClass("selected");
		            //debugger;                                        
		            node.find('div:first').addClass("selected");
		        }
		        //}
		    }
		}
	});
 })(jQuery)
