<?php


class Tree {

	var $_table;
	var $_params;
	var $cookie_name;
	var $_limit;// limit nodes from DB
	var $_deep_limit;// limit nodes from DB
	var $_nodes_from_db;// how much nodes loaded from DB
	var $_opened_nodes_to_save;// nodes forced to open, to save in cookie after show tree,subtree
	private $_profiler;

	public function __construct($table) {
		$this->_table = $table;
		$this->_sql_parent_id_col = 'PARENT_ID';
		$this->_params = array();
		$this->cookie_name = 'TREE_' . $table;
		// TODO: fun name must be uniq to show couple tree's on one site
		$this->js_tree_hide_fun = 'TREE_' . $table . '_hide';
		$this->js_tree_open_rec_fun = 'TREE_' . $table . '_open_rec';
		$this->_limit = 0;
		$this->_deep_limit = 0;
		$this->_opened_nodes_to_save = array();
	}

	public function setProfiler($profiler) {
		$this->_profiler = $profiler;
	}

	public function log($msg, $groups = array()) {
		if ($this->_profiler && method_exists($this->_profiler, 'log')) {
			$this->_profiler->log($msg, $groups);
		}
	}

	public function set_parent_id_col($p_id_col) {
		$this->_sql_parent_id_col = $p_id_col;
	}

	public function get_item_p_id(&$r) {
		if (isset($r->{$this->_sql_parent_id_col})) {
			return $r->{$this->_sql_parent_id_col};
		}
		return null;
	}

	public function is_closed($id) {
		static $c;
		if (!$c) {
			$c = explode(' ', V::get($this->cookie_name, '', $_COOKIE));
		}
		if ($this->get_param('lazy_open_rec')) {
			if (!in_array($id, $c)) {
				$this->lazy_open($id);
			}
			return false;
		}
		return !in_array($id, $c);
	}

	public function show() {
		//echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;">';print_r(explode(' ', $_COOKIE[$this->cookie_name]));echo'</pre>';
		$this->show_css();
		$this->show_js();
		echo "\n".'<div class="tree-wrap">'."\n";
		$this->show_rec();
		echo '</div>'."\n";
		$this->_save_lazy_opened_nodes();
		echo"\n".'<!-- '."Loaded from DB: ".$this->_nodes_from_db.' -->'."\n";
	}

	/*
	 * Save collapsed nodes in cookie
	 * @see _save_lazy_opened_nodes
	 */
	public function lazy_open($id) {
		$this->_opened_nodes_to_save[$id] = true;
	}

	/*
	 * Save collapsed nodes in cookie
	 * @see lazy_open
	 */
	public function _save_lazy_opened_nodes() {
		if (!empty($this->_opened_nodes_to_save)) {
			$opened = array();
			if (!empty($_COOKIE[$this->cookie_name]) && $_COOKIE[$this->cookie_name] != '') {
				$opened = explode(' ', $_COOKIE[$this->cookie_name]);
			}
			foreach ($opened as $id) {
				$this->_opened_nodes_to_save [$id] = true;
			}

			$_COOKIE[$this->cookie_name] = implode(' ', array_keys($this->_opened_nodes_to_save));
			echo'<script type="text/javascript">'."
	jQuery(document).ready(function(){
		jQuery.cookie('".$this->cookie_name."','" . $_COOKIE[$this->cookie_name] . "');
	});
			".'</script>';
		}
	}

	public function showSubTree($id = 0) {
		$this->show_css();
		$this->show_js();
		echo "\n".'<div class="tree-wrap">'."\n";
		$ids = explode(',', $id);
		foreach ($ids as $id) {
			$parents = array();
			$this->get_parents_rec($id, $parents);
			//echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;">';print_r($parents);echo'</pre>';
			$this->set_param('show_state', 'parents');
			$r = null;
			if (($r = reset($parents)) != null && $this->get_item_p_id($r) == -1) {
				echo'<b>'."Kosz".'</b>';
			}
			foreach ($parents as $r) {
				$cls = ' class="tree-last"';
				echo'<ul>'."\n";
				$item_id_html_id = ' id="TREE'.$r->ID.'"';
				echo '<li'.$cls.$item_id_html_id.'>';
				if ($r->ID == $id) break;
				$this->show_item($r);
			}

			$this->set_param('show_state', 'items');

			if ($r) {
				$this->show_item($r);
			} else {
				if ($this->get_param('is_trash')) {// is _trash
					echo'<b>'."Kosz".'</b>';
				} else {
					echo'<b>'."Brak danych".'</b>';
				}
			}
			//TODO: get item and if exists then show parents and childrens
			$this->show_rec($id);

			foreach ($parents as $r) {
				echo '</li>'."\n";
				echo'</ul>';
			}
			echo '<div style="border-bottom:1px solid #ddd"></div>';
		}
		echo '</div>'."\n";
	}

	/*
	 * Wyszukiwanie ID w drzewie.
	 */
	public function showSearchNode($id) {
		$parents = array();
		$this->get_parents_rec($id, $parents);

		if (empty($parents)) {
			echo'<p class="box box-red">Rekord id="<b>'.$id.'</b>" nie istnieje.</p>';
		} else {
			// TODO: drzewo ZWIN, trzeba teraz zmienic zawartosc cookie!
			//echo'<p>TODO: wyszukaj "'.$id.'" {'.implode(',', $parent_ids).'}</p>';
			echo'<p style="margin:0;padding:1px 10px;background-color:#C2F9C2;border:1px solid #CCC;border-style:solid solid none solid;">';
				$js = "return scrollToProces('".$id."');";
				echo'<a href="'."#TREE".$id.'" onclick="'.$js.'">'."Przejdz do ID <b>".$id."</b>".'</a>';
			echo'</p>';

			// TODO: sprawdzi czy aby na pewno dziala poprawnie, test szukaj 901, nie otwiera 892
			foreach ($parents as $r) {
				$this->lazy_open($r->ID);
			}

			$this->_save_lazy_opened_nodes();
		}

		$this->show();
	}

	/**
	 * TODO: Np. do menu, czy filtrowania drzewa.
	 * @see task_CRM_MENU
	 * @param items - array of items to show, array(ID => $r)
	 * @param show_item_callback - inna funkcja do wypisywania - TODO: jest $tree->set_param('show_item_callback');
	 */
	public function showItems(&$base_items, $show_item_callback = null) {
		$items = array();
		// get paretns flat
		$items_flat = array();
		foreach ($base_items as $p_id => $p) {
			$items[$p->ID] = $p;
			$items_flat[$p->ID] = $p->PARENT_ID;
			$items_flat[$this->get_item_p_id($p)] = null;
		}

		$user_menu_tree_created = TreeHelper::build_tree_flat($this->_table, $items_flat);

		$user_menu_tree = TreeHelper::get_tree_from_flat($items_flat);

		$this->fetch_data($items, $items_flat);

		if (!empty($user_menu_tree[0])) {
			$this->show_css();
			echo'<div class="tree-wrap">';
			$this->show_rec_by_tree($user_menu_tree[0], $items);
			echo'</div>';
		} else {
			//
		}
	}

	public function show_rec_by_tree(&$tree, &$items) {
		if (empty($tree)) {
			return;
		}

		echo'<ul>';
		$i = 0; $cnt = count($tree);
		foreach ($tree as $k_id => $v_arr) {
			$r = (isset($items[$k_id]))? $items[$k_id] : null;
			if ($r) {
				$cls = array();
				if ($this->is_closed($r->ID))  $cls['tree-close'] = true;
				if (++$i == $cnt) {
					$cls['tree-last'] = true;
				}
				if (empty($v_arr)) {
					$cls['tree-leaf'] = true;
				}
				$cls = (!empty($cls))? ' class="'.implode(' ', array_keys($cls)).'"' : '';

				$item_id_html_id = ' id="TREE'.$r->ID.'"';
				echo '<li'.$cls.$item_id_html_id.'>';
					if (isset($r->has_childrens) && $r->has_childrens) {
						echo'<div class="btn-open'.$btn_open_cls_add.'" onclick="return '.$this->js_tree_hide_fun.'(this,'.$r->ID.');"></div>';
					}
					$this->show_item($r);
					$this->show_rec_by_tree($v_arr, $items);
				echo'</li>';
			}
		}
		echo'</ul>';
	}

	public function fetch_data(&$items, $tree_flat) {
		$db = DB::getDB();
		$sql_ids = array();
		// find only not set
		foreach ($tree_flat as $k_id => $v) {
			if (empty($items[$k_id])) {
				$sql_ids[] = $k_id;
			}
		}
		// add tree parent proces info
		if (!empty($sql_ids)) {
			$sql_ids = implode(", ", $sql_ids);
			$sql = "select p.* from `{$this->_table}` as p where p.`ID` in ({$sql_ids}) ";
			$res = $db->query($sql);
			while ($r = $db->fetch($res)) {
				$items[$r->ID] = $r;
			}
		}
	}

	/*
	 * Open all nodes recursive.
	 */
	public function show_rec_all($parent_id = 0, $deep = 0) {
		$this->set_param('lazy_open_rec', true);// @see is_closed
		$this->lazy_open($parent_id);
		$this->show_rec($parent_id, $deep);
		$this->_save_lazy_opened_nodes();
	}

	public function show_rec($parent_id = 0, $deep = 0) {
		//if ($this->_deep_limit > 0 && $deep > $this->_deep_limit) {
		//	return;
		//}

		$this->log("show_rec({$parent_id}, {$deep}) start");

		$list = $this->get_childrens($parent_id);
		if (empty($list)) return;

		$this->log("show_rec({$parent_id}, {$deep}) -> get_childrens({$parent_id})", array('get_childrens'));

		echo '<ul>'."\n";
		$list_total = count($list);
		foreach ($list as $r) {
			$cls = array();
			if (!--$list_total) $cls['tree-last'] = true;
			if (!$this->get_param('rozwin')) {
				if ($this->is_closed($r->ID))  $cls['tree-close'] = true;
			}
			if ($this->_deep_limit > 0 && $deep >= $this->_deep_limit) {
				 $cls['tree-close'] = true;
			}
			if (!$r->has_childrens) {
				$cls['tree-leaf'] = true;
				if (isset($cls['tree-close'])) unset($cls['tree-close']);// show wskazniki on leaf
			}

			$cls = array_keys($cls);// uniq array
			// reopen nodes marked as open, but hide by default or deep, etc., @see show_js: tree_..._ajax_reopen
			$btn_open_cls_add = '';
			if (in_array('tree-close', $cls) && $this->is_closed($r->ID) == false) {
				$btn_open_cls_add = ' ajax-reopen';
			}

	//$cls[] = 'deep-'.$deep;
			$cls = (empty($cls))? '' : ' class="'.implode(' ', $cls).'"';
			$item_id_html_id = '';
			if ($this->get_item_p_id($r) == $parent_id) {// tylko normalny, a nie P_ID2, czy P_ID3, etc
				$item_id_html_id = ' id="TREE'.$r->ID.'"';
			}
			echo '<li'.$cls.$item_id_html_id.'>';
				if ($this->get_param('rozwin')) {
					if ($r->has_childrens) {
						if ($this->_deep_limit > 0 && $deep + 1 > $this->_deep_limit) {
							//echo'<a class="btn-open'.$btn_open_cls_add.'" onclick="return '.$this->js_tree_hide_fun.'(this,'.$r->ID.');" href="#">&nbsp;</a>';
							echo'<div class="btn-open'.$btn_open_cls_add.'" onclick="return '.$this->js_tree_hide_fun.'(this,'.$r->ID.');"></div>';
						}
					}
				} else {
					if ($r->has_childrens) {
						//echo'<a class="btn-open'.$btn_open_cls_add.'" onclick="return '.$this->js_tree_hide_fun.'(this,'.$r->ID.');" href="#">&nbsp;</a>';
						echo'<div class="btn-open'.$btn_open_cls_add.'" onclick="return '.$this->js_tree_hide_fun.'(this,'.$r->ID.');"></div>';
					}
				}
				$this->log("show_rec({$parent_id}, {$deep}) -> show_item start");
				$this->show_item($r);
				$this->log("show_rec({$parent_id}, {$deep}) -> show_item end", array('show_item'));

				if ($r->has_childrens) {
					$this->show_rec($r->ID, $deep + 1);
				}
			echo '</li>'."\n";
		}
		echo '</ul>'."\n";
		$this->log("show_rec({$parent_id}, {$deep}) end");
	}

	public function show_item(&$r) {
		if ($callback = $this->get_param('show_item_callback')) {
			$callback($r, $this);
		} else {
			echo'<dl><dt>';
			echo '<span class="item_id btn-box">'.$r->ID.'</span>';
			echo'</dt></dl>';
		}
	}

	public function &get_childrens($parent_id) {
		$ret = array();

		// check tree limit - load more by ajax
	// mved to show_rec
	//	if ($this->_limit > 0 && $this->_nodes_from_db > $this->_limit) {
	//		return $ret;
	//	}

		$sql = new stdClass();
		$sql->select = array();

		$sql->select[] = "t.*";

		// PARENT_TYPE dla tabeli CRM_LISTA_ZASOBOW
		if ($this->_table == 'CRM_LISTA_ZASOBOW') {
			$sql->select[] = "
				IF( t.`{$this->_sql_parent_id_col}`='{$parent_id}'
					, 'P_ID'
					, IF( (FIND_IN_SET('{$parent_id}', t.`PARENT_ID_ACCESS`) > 0)
						, 'P_ID_ACCESS'
						, IF( (FIND_IN_SET('{$parent_id}', t.`PARENT_ID_MAP`) > 0)
							, 'P_ID_MAP'
							, 'P_ID_UNKNOWN'
						)
					)
				) as PARENT_TYPE
			";

			$sql->select[] = "IF(t.`ALIAS_ID` > 0
					, (select concat_ws('.', zap.`DESC`, za.`DESC`)
							from `CRM_LISTA_ZASOBOW` as za
								left join `CRM_LISTA_ZASOBOW` as zap on(zap.`ID`=za.`PARENT_ID`)
							where za.`ID`=t.`ALIAS_ID`
							limit 1
						)
					, ''
				) as ALIAS_NAME
			";
		}

		$sql->filter = array();
		$sql->join_filter = array();
		$sql->filter[] = "(t.`{$this->_sql_parent_id_col}`='{$parent_id}')";
		$sql->join_filter[] = "(t2.`{$this->_sql_parent_id_col}`=t.`ID`)";
		if ($this->_table == 'CRM_LISTA_ZASOBOW') {
			// TODO: $this->get_param('TREE_SHOW_P_ID2') $this->get_param('TREE_SHOW_P_ID3')
			if ($_SESSION['TREE_SHOW_P_ID2'] || $_SESSION['TREE_SHOW_P_ID3']) {
				if ($_SESSION['TREE_SHOW_P_ID2']) {
					$sql->filter[] = "(FIND_IN_SET('{$parent_id}', t.`PARENT_ID_ACCESS`) > 0)";
					$sql->join_filter[] = "(FIND_IN_SET(t.`ID`, t2.`PARENT_ID_ACCESS`) > 0)";
				}
				if ($_SESSION['TREE_SHOW_P_ID3']) {
					$sql->filter[] = "(FIND_IN_SET('{$parent_id}', t.`PARENT_ID_MAP`) > 0)";
					$sql->join_filter[] = "(FIND_IN_SET(t.`ID`, t2.`PARENT_ID_MAP`) > 0)";
				}
			}
		}

		$sql->where = implode(" or ", $sql->filter);
		$sql->join_filter = implode(" or ", $sql->join_filter);

		// filtr_status
		if ($this->_table == 'IN7_MK_BAZA_DYSTRYBUCJI') {
			$sqlStatus = array();
			if ($this->get_param('filtr_status') == 'NORMAL') {
				$sqlStatus[] = "'NORMAL'";
			} else if ($this->get_param('filtr_status') == 'WAITING') {
				$sqlStatus[] = "'NORMAL'";
				$sqlStatus[] = "'WAITING'";
			}
			if (!empty($sqlStatus)) {
				$sqlStatus = implode(',', $sqlStatus);
				$sql->where = "({$sql->where}) and t.`A_STATUS` in({$sqlStatus}) ";
			}
		}

		if (in_array($this->_table, array('CRM_PROCES','CRM_LISTA_ZASOBOW'))) {
			$sql->order_by = "order by t.`SORT_PRIO` asc, t.`ID` asc";
		} else {
			$sql->order_by = "order by t.`ID` asc";
		}

		// has_childrens
		# IF((select 1 from `CRM_PROCES` as t2 where t2.`PARENT_ID` = t.`ID` limit 1) > 0, 1, 0) AS has_childrens
		if ($this->_table == 'CRM_LISTA_ZASOBOW') {
			//$sql->select [] = "IF(t.`".$this->_sql_parent_id_col."`='".$parent_id."' and t2.`ID` is not null, 1, 0) as has_childrens";
			$sql->select[] = "IF((select 1 from `{$this->_table}` as t2 where {$sql->join_filter} limit 1) is not null, 1, 0) as has_childrens";
		} else {
			//$sql->select [] = "IF(t2.`ID` is not null, 1, 0) as has_childrens";
			$sql->select[] = "IF((select 1 from `{$this->_table}` as t2 where {$sql->join_filter} limit 1) is not null, 1, 0) as has_childrens";
		}

		$db = DB::getDB();
		$sql->select = implode("\n, ", $sql->select);
		$sql = "select
				{$sql->select}
			from `{$this->_table}` as t
			where
				{$sql->where}
			{$sql->order_by}
		";
		if('123' == V::get('DBG_SQL', '', $_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;"> (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($sql);echo'</pre>';}
		$res = $db->query($sql);
		$rowsCount = 0;
		while ($r = $db->fetch($res)) {
			$ret[$r->ID] = $r;
			$rowsCount++;
		}
		$this->_nodes_from_db += $rowsCount;
		return $ret;
	}

	public function &get_parents_rec($id, &$arr) {
		$db = DB::getDB();
		$sql = "select
				t.*
				, '1' as has_childrens
				, 'P_ID' as PARENT_TYPE
			from `{$this->_table}` as t
			where
				t.`ID`='".$id."'
		";
		$res = $db->query($sql);
		if ($r = $db->fetch($res)) {
			array_unshift($arr, $r);
			if (null == $this->get_item_p_id($r) || '0' == $this->get_item_p_id($r)) {
				return $arr;
			} else {
				$this->get_parents_rec($this->get_item_p_id($r), $arr);
			}
		}
		return $arr;
	}

	public function set_param($key, $value) {
		$this->_params[$key] = $value;
	}

	public function get_param($key) {
		if (array_key_exists($key, $this->_params)) {
			return $this->_params[$key];
		}
		return null;
	}

	public function show_css() {
		static $_run_only_once;
		if ($_run_only_once) {
			return;
		}
		$_run_only_once = true;
		?>
		<style type="text/css">
.tree-wrap{border:1px solid #ccc;margin:0;padding:0 5px;list-style:none;font-size:12px;line-height:16px;font-family:monospace;}
.tree-wrap ul{margin:0;padding:0;list-style:none;}
.tree-wrap li{margin:0 0 0 0;padding:0 0 0 10px;line-height:16px;}
.tree-wrap li * {line-height:16px;}
.tree-wrap p,
.tree-wrap .cnt{margin:0 0 0 0;padding:0 0 0 10px;background:url(stuff/i/t-ul.gif) 0 0 repeat-y;}
.tree-wrap li.tree-leaf .cnt{background:none;}
.tree-wrap p:hover,
.tree-wrap .cnt:hover{background:#FFFFCA url(stuff/i/t-ul.gif) 0 0 repeat-y;}
.tree-wrap li.tree-leaf .cnt:hover{background:none;}
.tree-wrap div.has_wsk{margin:0 0 0 0;padding:0 0 0 10px;background:url(stuff/i/t-ul-green.gif) 0 0 repeat-y;}
.tree-wrap a.item_id:hover {color:#fff; text-decoration:none}
.tree-wrap p .item_id,
.tree-wrap .cnt .item_id{margin:0 0 0 -10px;}
.tree-wrap .cnt .has_wsk .item_id{margin:0 0 0 -20px;}
.tree-wrap ul{background:url(stuff/i/t-ul.gif) 0 0 repeat-y;}
.tree-wrap li{background:url(stuff/i/t-li.gif) 0 0 no-repeat;}
.tree-wrap li.tree-last{background-color:#fff;}
.tree-wrap .item_type_PROCES_INIT{background:#f00;color:#fff;}
.tree-wrap .btn-p5{margin:0 2px;padding:0 2px;background:#eee;color:#3A3AFF;text-decoration:none;border:0;font-weight:bold;}
.tree-wrap .btn-red{background:#eee;color:#f00;}

.tree-wrap p:hover .btn-box,
.tree-wrap .cnt:hover .btn-box{background:#333;}
.tree-wrap dt:hover .btn-box{background:#333;}
.tree-wrap dt:hover .desc{background-color:#F8F8B4;}
.tree-wrap .active > dl .desc{background-color:#F8F8B4;}
.tree-wrap .active > dl .item_id{background-color:#000;}

.tree-wrap .item-wskazniki{margin:0;padding:0 0 3px 0;}
.tree-wrap .item-has_children{background:url(stuff/i/t-ul.gif) 0 0 repeat-y;}
.tree-wrap .item-wskazniki ul{margin:0 2px 0 10px;color:#008000;}
.tree-wrap .item-wskazniki ul{background:url(stuff/i/t-ul-green.gif) 0 0 repeat-y;}
.tree-wrap .item-wskazniki li{background:url(stuff/i/t-li-green.gif) 0 0 no-repeat;}
.tree-wrap .item-wskazniki li.tree-last{background-color:#fff;}
.tree-wrap .item-wskazniki p {margin:0;padding:0;background:#fff;}
.tree-wrap .item-wskazniki p:hover{background:#FFFFCA;}
.tree-wrap .item-wskazniki p .wsk_parents{display:none;}
.tree-wrap .item-wskazniki p:hover .wsk_parents{display:inline;color:#555;font-size:11px;}

.tree-wrap .btn-p5:hover{background:#3A3AFF;color:#eee;}

.tree-wrap .btn-open{display:block;width:12px;height:9px;overflow:hidden;}
/*.tree-wrap .btn-open{margin:0;padding:0;position:absolute;top:4px;left:-4px;}*/
/* TODO: IF IE left: -14px */
.tree-wrap .btn-open{border:none;text-decoration:none;background:url(stuff/i/tree-collapse-btn.gif) no-repeat left top;cursor:pointer;}
.tree-wrap li.tree-close .btn-open{background-position:0 -9px;}
.tree-wrap li.tree-close ul{display:none;background:none;}
.tree-wrap li.tree-close .cnt,
.tree-wrap li.tree-close .item-wskazniki,
.tree-wrap li.tree-close dt,
.tree-wrap li.tree-close dd,
.tree-wrap li.tree-close .has_wsk{background:none;}
.tree-wrap li.tree-close dd{padding:0;}

.tree-wrap .desc{margin:0 2px;color:#000;font-weight:normal;}
.tree-wrap .desc-red{color:#f00;}
.tree-wrap .desc-group1{color:navy;}
.tree-wrap .desc-group2{color:olive;}
.tree-wrap .desc .more-desc{color:#333;font-weight:normal;overflow:hidden;}
.tree-wrap .desc .more-desc *{margin:0;}
.tree-wrap .desc .more-desc img{margin:0 2px;}
.tree-wrap .desc .more-desc ul{background:none; list-style:disc; padding:0 0 0 20px;}
.tree-wrap .desc .more-desc ul li {padding:0;}
.tree-wrap .desc .more-desc ul li,
.tree-wrap .desc .more-desc p {background:none;}
.tree-wrap .silver{color:#333;font-weight:normal;}

/* tree-wrap dl-dt-dd: dl{ dt, dd, dl{...} } */
.tree-wrap{border:1px solid #ccc;margin:0;padding:0 5px;list-style:none;font-size:12px;line-height:16px;font-family:monospace;}
.tree-wrap dl{padding:0;margin:0;}
.tree-wrap dt{padding:0 0 0 10px;margin:0;}
.tree-wrap dd{padding:0;margin:0;}
.tree-wrap dl.has_wsk dt{margin:0 0 0 0;padding:0 0 0 20px;background:url(stuff/i/t-ul-green.gif) 0 0 repeat-y;}

.tree-wrap dd{margin:0;padding:0 0 3px 0;}
.tree-wrap dd ul{margin:0 2px 0 10px;color:#008000;}
.tree-wrap dd ul{background:url(stuff/i/t-ul-green.gif) 0 0 repeat-y;}
.tree-wrap dd li{background:url(stuff/i/t-li-green.gif) 0 0 no-repeat;}
.tree-wrap dd li.tree-last{background-color:#fff;}

.tree-wrap dt .item_id{margin:0 0 0 -10px;}
.tree-wrap .has_wsk .item_id{margin:0 0 0 -20px;}
.tree-wrap dd,
.tree-wrap dt{background:url(stuff/i/t-ul.gif) 0 0 repeat-y;}
.tree-wrap dl.has-no-children dd,
.tree-wrap dl.has-no-children dt{background:none;}
.tree-wrap li.tree-leaf dt{background:none;}
.tree-wrap li.tree-leaf dd{background:none;}
.tree-wrap dd p {margin:0;padding:0;background:#fff;}
.tree-wrap dd p:hover{background:#FFFFCA;}
.tree-wrap dd p .wsk_parents{display:none;}
.tree-wrap dd p:hover .wsk_parents{display:inline;color:#555;font-size:11px;}

/* colors by zasob type */
.tree-wrap .type-P_ID .desc {color:#f00;}
.tree-wrap .type-P_ID_ACCESS .desc {color:#0E7E0E;}
.tree-wrap .type-P_ID_MAP .desc {color:#A020F0;}
.tree-wrap .type-ALIAS_ID .desc {color:#FF6900;}
.tree-wrap dt:hover .item_id{background:#000;}
.tree-wrap dl.type-ALIAS_ID dt:hover .item_id{background:#FB9044;}
.tree-wrap dl.type-P_ID_MAP dt:hover .item_id{background:#AB54DF;}
.tree-wrap dl.type-P_ID_ACCESS dt:hover .item_id{background:#0E7E0E;}

/* TODO: IE style
.tree-wrap ul{float:left;overflow:hidden;}
.tree-wrap li{float:left;clear:both}
.tree-wrap dl{float:left;}
.tree-wrap dl{display:inline;}
*/
/*
.tree-wrap ul{clear:both;float:left;width:100%;}
.tree-wrap li{float:left;clear:both;width:100%;}
.tree-wrap dl{clear:both;}
.tree-wrap dl dt{float:left}
.tree-wrap dl dd{}
.tree-wrap .btn-open{float:left;margin:4px 0 0 -14px;padding:0;}
.tree-wrap .has_wsk .btn-open{float:left;margin:4px 0 0 -24px;padding:0;}
*/
.tree-wrap li{position:relative}
.tree-wrap .btn-open{position:absolute;top:4px;left:-4px;padding:0;}
/*.tree-wrap .has_wsk .btn-open{position:absolute;top:4px;left:-14px;padding:0;}*/

/* zasoby: external ids */
.tree-wrap .external-ids{color:#008A00; font-weight:bold;}
.tree-wrap .external-ids .not-found{color:#666; font-weight:normal;}
.tree-wrap .external-ids a{color:#008A00; font-weight:normal; text-decoration:none;}
.tree-wrap .external-ids a:hover{text-decoration:underline;}
.tree-wrap .external-ids a img{vertical-align:bottom;}

.tree-wrap .search_id .desc{background-color:#C2F9C2;}

.tree-wrap .open-rec{display:none;}
.tree-wrap .tree-close .open-rec{display:inline;}

.tree-wrap li.hide-wskazniki dd{display:none;}


.tree-wrap .wsk-modal,
.tree-wrap .popover,
.tree-wrap .wsk-help {color:#333;}
.tree-wrap .wsk-modal h1,
.tree-wrap .wsk-modal h2,
.tree-wrap .wsk-modal h3,
.tree-wrap .wsk-modal h4,
.tree-wrap .wsk-modal h5,
.tree-wrap .wsk-modal h6 {line-height:1.2em;}

		</style>
	<?php
}

	public function show_js() {
		?>
	<script type="text/javascript">
function <?php echo $this->js_tree_hide_fun; ?>(n, id){
	var p=jQuery(n).parents('li:first')
	<?php echo $this->js_tree_hide_fun; ?>_node(p, id);
}
function <?php echo $this->js_tree_hide_fun; ?>_node(p, id, open_rec) {
	p.toggleClass('tree-close');

	var c = jQuery.cookie('<?php echo $this->cookie_name; ?>');
	if (c === null) c = '';
	if (p.hasClass('tree-close')) {// open subtree
		// remove id from cookie
		//c = (' '+c+' ').replace((new RegExp(' '+id+' ', 'g')), ' ')
		var carr = c.split(' ');
		jQuery.unique(carr);
		c = (' ' + carr.join(' ') + ' ').replace((new RegExp(' ' + id + ' ', 'g')), ' ');
	}
	else {// close subbtree
		// add id to cookie, uniq array
		if ((' ' + c + ' ').indexOf(' ' + id + ' ') == -1){
			c = (c === '')? '' + id : '' + id + ' ' + c;
		}
		if (jQuery(p).children('ul').length == 0) {
			// create node to verride html from ajax request
			var cnt = jQuery('<em>loading...</em>');
			jQuery(p).append(cnt);
			var cnt = jQuery(p).children('em').get(0);
			// run ajax function
			var ajax_add_args = '';
			if (open_rec) {
				ajax_add_args = '&open_rec=1';
			}
			procesy_ajax_run(cnt, '?function_init=ajax_get_subtree&tbl=<?php echo $this->_table; ?>&id=' + id + ajax_add_args, 'override');
		}
	}
	c = jQuery.trim(c);
//if (console && console.log) console.log(c)
	jQuery.cookie('<?php echo $this->cookie_name; ?>', c);
	return false;
}

// open recursive
function <?php echo $this->js_tree_open_rec_fun; ?>(n, id) {
	// execute ajax function to fetch subtree with Drzewo=ROZWIN
	var p = jQuery(n).parents('li:first');
	node_id = p.attr('id');
	if (node_id.substr(0, 4) == 'TREE') {
		node_id = node_id.substr(4);
		//console.log('[' + node_id + ']has_class: ' + p.hasClass('tree-close') + ' ...');
		var childrens = p.children('ul');
		//console.log('[' + node_id + ']childrens: ');
		if (childrens) {
			childrens.remove();
		}
		<?php echo $this->js_tree_hide_fun; ?>_node(p, node_id, true);
	} else {
		//console.log('ERROR: id TREE');
	}
	return false;
}

// ajax reopen nodes, on document load
jQuery(document).ready(function(){
	var nodes = jQuery('.ajax-reopen');
	if (nodes.length) nodes.click();

	if (jQuery.browser.msie) {
		// TODO: add message: view not work in IE
	}

	jQuery('.wsk-help').popover({trigger:'hover', html:true, placement:'top'});
	//jQuery('.wsk-long-desc').modal();
});
			</script>
		<?php
	}

}
