﻿/*
 * 
 *
 */

;(function($) {

var proxied = $.fn.treeview;
$.fn.treeEdit = function(settings) {
	var _this = this;
	if(!settings.callback) settings.callback={};
	this.callback = {
		onrename	: function(id,oldname,newname) {},
		dragStart : function(){},
		drag : function(refNode,dragNode){return true;},
		dragEnd : function(data,opid,oseq){},
		remove : function(node){},
		add : function(node){},
		selected: function(node){}
	};
	
	//将定义参数中的事件绑定到默认事件
	if(settings.callback){
		for(var i in settings.callback)
			this.callback[i] = settings.callback[i];
	}
	
	//通过脚本绑定事件
	this.bindEvent = function(evtName,func){
		this.callback[evtName] = func;
		settings.callback[evtName] = func;
	}
	
	//编辑节点名称
	this.rename = function(node){
		if(!settings.select && node) return;
		node = node? node : settings.select.children("span").children("a");
		var liNode = node.closest("li");
		var oldname = node.text();
		var newname;
		
		var ins = $("<input type='text' autocomplete='off'/>").val(oldname)
		.bind("keyup",function (event) { 
			var key = event.keyCode || event.which;
			if(key == 27) { this.value = oldname; this.blur(); return }
			if(key == 13) { this.blur(); return; }
		});
		ins.blur(function(event){
			newname = $.trim(this.value) == ""? oldname:this.value;
			node.empty().text(newname);
			if(newname != oldname)	{
				liNode.data("data").name = newname;
				_this.callback.onrename(liNode.data("data").id,oldname,newname);
			}
		});
		
		node.empty().append(ins);
		ins.focus().select();
	};
	//向上移
	this.moveup = function(){
		if(!settings.select) return;
		var drgNode = settings.select;
		var refNode = drgNode.prev();
		//console.info(refNode.size());
		if(refNode.size()>0) dragToBefore(refNode,drgNode);
	}
	//向下移
	this.movedown = function(){
		if(!settings.select) return;
		var drgNode = settings.select;
		var refNode = drgNode.next();
		if(refNode.size()>0) dragToAfter(refNode,drgNode);
	}

	//删除节点
	this.delNode = function(){
		if(!settings.select) return;
		var data = settings.select.data("data");
		delFun(settings.select);
		_this.callback.remove(data);
	}
	//添加节点
	this.addNode = function (data){
		if(!settings.select && !refNode) return;
		var refNode = settings.select;
		var addNode = $("<li><span><img/><a></a></span></li>");
		addNode.find("img").attr("src",data.icon?data.icon:"../js/css/jquery-treeview/images/folder-closed.gif");
		addNode.find("a").text(data.name?data.name:"newobj");
		addNode.data("data",data);
		addFun(refNode,addNode);
		_this.callback.add(addNode);
	}
	
	function delFun(obj){
		var $parent = obj.parent();
		obj = obj.remove();
		
		if ($parent.children("li").size() == 0) {
			$parent.parent().removeClass().find(">div").remove();
			$parent.parent().parent().children("li:last").addClass("last");
			$parent.remove();
		}
		var last = $parent.children("li:last");
		if(last.children("ul").size() != 0){
			last.filter(".expandable").replaceClass("expandable","lastExpandable").end()
			    .filter(".collapsable").replaceClass("collapsable","lastCollapsable");
			last.children("div").filter(".expandable-hitarea").replaceClass("expandable-hitarea","lastExpandable-hitarea").end()
			    .filter(".collapsable-hitarea").replaceClass("collapsable-hitarea","lastCollapsable-hitarea");
		}else{
			last.addClass("last");
		}
	}
	
	function addFun(refNode,addNode){
		addNode.swapClass( "collapsable", "expandable" )
			.swapClass( "lastCollapsable", "lastExpandable" )
			//.data("data",{})
			.children("div").remove();
		refNode.filter(":has(>ul:hidden)").children("div").click();
		if(refNode.children("ul").size() !=0){
			refNode.children("ul").append(addNode);
			_this.trigger("add", [addNode]);
		}else{
			$("<ul></ul>").appendTo(refNode).append(addNode);
			_this.trigger("add", [refNode]);
			refNode.children("div").click();
		}
		//reBuildSequence(obj);
	}
	//重构节点下子节点的sequence
	function reBuildSequence(node){
		node.children("ul").children("li").each(function(i,v){
			$(v).attr("sequence",i+1);
			$(v).data("data").sequence = i+1;
			$(v).data("data").pid = node.data("data").id;
		});
	}
	
	//拖拽节点
	function mousemove(event){
		var tmp = settings.dragDrop;
		var is_start = false;

		if (tmp.isdown) {
			tmp.ref_node	= $(event.target).closest("li");
			if(!settings.dragDrop.marker){
				settings.dragDrop.marker = $("<div id='jstree-marker'>&nbsp;</div>").appendTo("body");
			}
			if(!tmp.moving && Math.abs(tmp.init_x - event.pageX) < 5 && Math.abs(tmp.init_y - event.pageY) < 5) {
				event.preventDefault();
				event.stopPropagation();
				return false;
			}else {
				if(!tmp.moving) {
					settings.dragDrop.moving = true;
					is_start = true;
				}
			}
			if(tmp.drag_help !== false) {
				if(!tmp.appended) {
					if(tmp.foreign !== false) tmp.origin_tree = $.tree.focused();
					$("body").append(tmp.drag_help);
					tmp.w = tmp.drag_help.width();
					tmp.appended = true;
				}
				tmp.drag_help.css({ "left" : (event.pageX + 5 ), "top" : (event.pageY + 15), "position" : "absolute" });
			}
			if(event.target.tagName == "DIV" && event.target.id == "jstree-marker") return false;
			
			var et = $(event.target);
			if(et.is("ins")) et = et.parent();
			var cnt = et.is(".treeview") ? et : et.parents(".treeview:eq(0)");
			var pnt = et.is(".dragged")? et : et.parents(".dragged:eq(0)");

			//在树范围之外 或 在要拖动的节点的子节点下 或 拖动条件接口返回false
			if(cnt.size() == 0 || pnt.size() != 0 || !_this.callback.drag(tmp.ref_node,tmp.drag_node)) {
				if(tmp.drag_help !== false) tmp.drag_help.addClass("forbidden");
				tmp.move_type = false;
				tmp.ref_node = false;
				settings.dragDrop.marker.hide();
				return false;
			}
			
			var mov = false;
			var st = cnt.scrollTop();
			var liHeight = 20;
			if (event.target.tagName == "A" ) {
				if(et.closest("li").is(".dragged")) return false;
				if(et.closest("li").filter(":has(>ul:hidden)").size()>0) {
					//console.info("open");
					setTimeout( function () { et.closest("li").children("div").click(); }, 500);
				}
				var et_off = et.offset();
				var goTo = { 
					x : (et_off.left - 1),
					y : (event.pageY - et_off.top)
				};
				
				if(goTo.y < liHeight/3 - 1 ) {
					mov = "before";
					goTo.y = et_off.top - 2;
					settings.dragDrop.marker.attr("class","marker");
					if(tmp.ref_node.data("data").pid == -1){
						if(tmp.drag_help !== false) tmp.drag_help.addClass("forbidden");
						tmp.move_type = false;
						tmp.ref_node = false;
						settings.dragDrop.marker.hide();
						return false;
					}
				}
				else if( goTo.y > liHeight*2/3 - 3 ){
					mov = "after";
					goTo.y = et_off.top-6 + liHeight;
					settings.dragDrop.marker.attr("class","marker");
					if(tmp.ref_node.data("data").pid == -1){
						if(tmp.drag_help !== false) tmp.drag_help.addClass("forbidden");
						tmp.move_type = false;
						tmp.ref_node = false;
						settings.dragDrop.marker.hide();
						return false;
					}
				}
				else {
					mov = "inside";
					goTo.x -= 2;
					goTo.y = et_off.top -4 + liHeight/2;
					settings.dragDrop.marker.attr("class","marker_plus"); 
				}
				
				tmp.move_type	= mov;
				
				if(tmp.drag_help !== false) tmp.drag_help.removeClass("forbidden");
				settings.dragDrop.marker.css({ "left" : goTo.x , "top" : goTo.y }).show();
			}else{
				if(tmp.drag_help !== false) tmp.drag_help.addClass("forbidden");
				tmp.move_type = false;
				tmp.ref_node = false;
				settings.dragDrop.marker.hide();
				return false;
			}
			//console.info(mov);	
			event.preventDefault();
			event.stopPropagation();
			return false;
		}	
		return true;
	}
	
	function mouseup(event){
		var tmp = settings.dragDrop;
		if( tmp.drag_node && tmp.drag_node.size() && tmp.ref_node) {
			tmp.drag_help.remove();
			
			switch(tmp.move_type){
				case "before":
						dragToBefore(tmp.ref_node,tmp.drag_node);
						break;
					case "after":
						dragToAfter(tmp.ref_node,tmp.drag_node);
						break;
					case "inside":
					  dragToInside(tmp.ref_node,tmp.drag_node);
						break;
					default:
						break;
			}
			tmp.move_type	= false;
			tmp.ref_node	= false;
		}
		
		if(tmp.drag_help && tmp.drag_help.size()) tmp.drag_help.remove();
		if(tmp.drag_node && tmp.drag_node.size()) tmp.drag_node.removeClass("dragged");
		if(tmp.dragged && tmp.dragged.size()) tmp.dragged.removeClass("dragged");
		tmp.dragged		= false;
		tmp.drag_help	= false;
		tmp.drag_node	= false;
		tmp.f_type		= false;
		tmp.f_data		= false;
		tmp.init_x		= false;
		tmp.init_y		= false;
		tmp.moving		= false;
		tmp.appended	= false;
		tmp.origin_tree	= false;
		if(tmp.isdown){
			tmp.isdown = false;
			if(settings.dragDrop.marker) settings.dragDrop.marker.hide();
			event.preventDefault(); 
			event.stopPropagation();
			return false;
		}
	}
	
	$(function(){
		$(document).bind("mousemove.tree",mousemove);
		$(document).bind("mouseup.tree",mouseup);
	});
	
	function dragToBefore(refNode,drgNode){
		var parentRefNode = refNode.parent();
		var parentDrgNode = drgNode.parent();
		var lastRefNode = parentRefNode.children("li:last-child");
		var lastDrgNode = parentDrgNode.children("li:last-child");

		var oseq = drgNode.data("data").sequence;
		var opid = drgNode.data("data").pid;
		
		refNode.before(drgNode);
		drgNode.removeClass("last").filter(":has(ul)").removeClass("lastExpandable lastCollapsable").children("div").removeClass("lastExpandable-hitarea lastCollapsable-hitarea");
		if(lastRefNode.hasClass("dragged")){
			var last = parentRefNode.children("li:last-child").addClass("last");
			last.filter(":has(ul:hidden)").addClass("lastExpandable").children("div").addClass("lastExpandable-hitarea");
			last.filter(":has(ul:not(:hidden))").addClass("lastCollapsable").children("div").addClass("lastCollapsable-hitarea");
		}else{
			var last = parentDrgNode.children("li:last-child").addClass("last");
			last.filter(":has(ul:hidden)").addClass("lastExpandable").children("div").addClass("lastExpandable-hitarea");
			last.filter(":has(ul:not(:hidden))").addClass("lastCollapsable").children("div").addClass("lastCollapsable-hitarea");
		}
		
		if(refNode.children("ul").children("li").size() == 0){
			refNode.children("div").remove().end().children("ul").remove().end().removeClass("expandable collapsable").replaceClass("lastExpandable","last").replaceClass("lastCollapsable","last");
		}
		
		reBuildSequence(parentRefNode.parent());
		reBuildSequence(parentDrgNode.parent());
		
		_this.callback.dragEnd(drgNode.data("data"),opid,oseq);
	}
	function dragToAfter(refNode,drgNode){
		var parentRefNode = refNode.parent();
		var parentDrgNode = drgNode.parent();
		var lastRefNode = parentRefNode.children("li:last-child");
		var lastDrgNode = parentDrgNode.children("li:last-child");
		
		var oseq = drgNode.data("data").sequence;
		var opid = drgNode.data("data").pid;
		
		refNode.after(drgNode);
		drgNode.removeClass("last").filter(":has(ul)").removeClass("lastExpandable lastCollapsable").children("div").removeClass("lastExpandable-hitarea lastCollapsable-hitarea");
		refNode.removeClass("last").filter(":has(ul)").removeClass("lastExpandable lastCollapsable").children("div").removeClass("lastExpandable-hitarea lastCollapsable-hitarea");
		if(lastDrgNode.hasClass("dragged")){
			var last = parentDrgNode.children("li:last-child").addClass("last");
			last.filter(":has(ul:hidden)").addClass("lastExpandable").children("div").addClass("lastExpandable-hitarea");
			last.filter(":has(ul:not(:hidden))").addClass("lastCollapsable").children("div").addClass("lastCollapsable-hitarea");
		}
		var lastRef = parentRefNode.children("li:last-child").addClass("last");
		lastRef.filter(":has(ul:hidden)").addClass("lastExpandable").children("div").addClass("lastExpandable-hitarea");
		lastRef.filter(":has(ul:not(:hidden))").addClass("lastCollapsable").children("div").addClass("lastCollapsable-hitarea");

		if(refNode.children("ul").children("li").size() == 0){
			refNode.children("div").remove().end().children("ul").remove().end().removeClass("expandable collapsable").replaceClass("lastExpandable","last").replaceClass("lastCollapsable","last");
		}

		reBuildSequence(parentRefNode.parent());
		reBuildSequence(parentDrgNode.parent());
		
		_this.callback.dragEnd(drgNode.data("data"),opid,oseq);
	}
	function dragToInside(refNode,drgNode){
		var parentRefNode = refNode.parent();
		var parentDrgNode = drgNode.parent();
		
		var oseq = drgNode.data("data").sequence;
		var opid = drgNode.data("data").pid;
		var data = drgNode.data("data");
		data.pid = refNode.data("data").id;
		data.sequence = refNode.children("ul").children("li").size()+1;

		delFun(drgNode);
		drgNode.data("data",data);
		addFun(refNode,drgNode);
		

		//console.info(drgNode.data("data"));
		reBuildSequence(refNode);
		reBuildSequence(parentDrgNode.parent());
		//console.info(drgNode.data("data"));
		
		_this.callback.dragEnd(drgNode.data("data"),opid,oseq);
	}
	
	return proxied.call(this, $.extend(settings, {
		editable : true,
		dragDrop : {
			isdown		: false,	// Is there a drag
			drag_node	: false,	// The actual node
			drag_help	: false,	// The helper
			dragged		: false,
	
			init_x		: false,
			init_y		: false,
			moving		: false,
	
			origin_tree	: false,
			marker		: false,
	
			move_type	: false,	// before, after or inside
			ref_node	: false,	// reference node
			appended	: false,	// is helper appended
	
			foreign		: false,	// Is the dragged node a foreign one
			droppable	: [],		// Array of classes that can be dropped onto the tree
	
			open_time	: false,	// Timeout for opening nodes
			scroll_time	: false		// Timeout for scrolling
		}
	}));
};
})(jQuery);
