<?php
// +----------------------------------------------+
// | Class TabPanel                               |
// | JGNJ                                         |
// +----------------------------------------------+
// | Cria e ativa abas com seus conteudos         |
// | ex:                                          |
// |                                              |
// | $tab = TabPanel::getInstance();              |
// |                                              |
// | $tab->create('aba 1','idAba1')               |
// |     ->append(<b>conte�do aba1</b>);          |
// |                                              |
// | $tab->create('aba 2','idAba2')               |
// |     ->append(<b>conte�do aba2</b>);          |
// |                                              |
// | $tab->create('aba 3','idAba3')               |
// |     ->append(<b>conte�do aba3</b>);          |
// |                                              |
// | echo $tab->outPut();                         |
// +----------------------------------------------+
class TabPanel
{
	static private $instance 	= NULL;
	private $msie					= false;
	private $id						= array();
	private $containerId;
	private $containerClass;
	private $contentTab;
	private $firstTab				= true;
	private $appendTab			= array();
	private $paramTab				= array();
	private $iscontenttab		= false;

	static public function getInstance()
	{
		if (self::$instance==NULL)
			self::$instance = new TabPanel();

		return self::$instance;
	}

	private function __construct()
	{
		return $this;
	}

	/* para diferenciar o objeto js */
	public function id($i)
	{
		$this->containerId = $i;
		return $this;
	}

	/**
	 * TabPanel::cls()
	 *
	 * Refer�ncia a uma classe de css
	 * $obj->css('myCssClass');
	 */
	public function cls($c)
	{
		$this->containerClass = $c;
		return $this;
	}

	/**
	 * TabPanel::create()
	 * return object TabPanelContent
	 */
	public function create($titleTab,$id)
	{
		/* armazena id para objeto js posterior */
		if (!in_array($id,$this->id)) {
			$this->id[] = $id;
			
			$this->paramTab['tabTitle']		= $titleTab;
			$this->paramTab['tabId']			= $id;
			$this->paramTab['containerId']	= $this->containerId;
			$this->paramTab['firstTab']		= $this->firstTab;

			/* objeto da aba */
			$obj = new TabPanelContent($this->paramTab);

			/* primeira aba */
			$this->firstTab = false;

			/* array com objetos das abas */
			$this->appendTab[] = $obj;

			return $obj;
		}

		/* Gera um fatal error - id de abas repetidas */
		return;

	}

	public function outPut()
	{
		foreach($this->appendTab as $obj) {
			if ($obj instanceof TabPanelContent) {
				$header.= $obj->header();
				$body.= $obj->body();
			} else {
				die('erro na inst�ncia do objeto');
				break;
			}
		}

		$content = preg_replace('/\{TABS_PANEL\}/',$header,self::getTemplate());
		$content = preg_replace('/\{SCRIPT\}/',self::jsClass(),$content);
		$content = preg_replace('/\{TABS_PANEL_CONTENT\}/',$body,$content);

		self::unsetAttr();
		return $content;
	}

	public function activeTab()
	{
		return "__TabPanel_{$this->containerId}.activeTab()";
	}
	
	/* private methods */
	private function unsetAttr()
	{
		$this->id				= array();
		$this->containerId	= NULL;
		$this->contentTab		= NULL;
		$this->firstTab		= true;
		$this->appendTab		= array();
		$this->paramTab		= array();
	}

	private function getTemplate()
	{
		if (isset($this->containerClass[1])) {
			$class = "class=\"{$this->containerClass}\"";
		}
		
		$tpl = "<div id=\"PFtabPanelContainer_{$this->containerId}\" $class>\n";
		$tpl.= "<ul style=\"margin:0;padding:0;\n";
		$tpl.= "	font-family: tahoma,'Lucida Grande','Lucida Sans Unicode', 'Lucida Sans'; font-size: 11px;\">\n";
		$tpl.= "{TABS_PANEL}\n";
		$tpl.= "</ul>\n{TABS_PANEL_CONTENT}\n</div>{SCRIPT}\n";

		return $tpl;
	}

	private function jsClass()
	{
		/**
		 * Classe js para manipula��o das abas
		 * __TabPanel_+id
		 *  -> tabs()			retorna o array das abas
		 *  -> activeTab()	retorna o id da aba ativa
		 *  -> changeTab()	muda de aba no click
		 */
$js = <<<JS
<script>
var __TabPanel_{$this->containerId} = {
	isActive:'',
	$: function(id) {
		return document.getElementById(id);
	},
	tabs: function() {
		return new Array({IDS});
	},
	activeTab: function() {
		if (__TabPanel_{$this->containerId}.isActive.length) {
			return __TabPanel_{$this->containerId}.isActive;
		}
		
		var t = this.tabs(); 
		for (var e=0,act;act=t[e];e++) {
			if (this.$('PFtabPanelContent_'+act).style.display=='block') {
				return act;
			}
		}
	},
	changeTab: function(id) {
		var act = this.activeTab();
		if (act!=id) {
			this.enable(id);
			this.disable(act);
		}
	},
	enable: function(id) {
		this.$('PFtabPanelContent_'+id).style.display='block';
		this.$('PFtabPanel_'+id).style.padding='2px 5px 3px 6px';
		this.$('PFtabPanel_'+id).style.borderWidth='1px 1px 0px 1px';
		
		__TabPanel_{$this->containerId}.isActive = id;
	},
	disable: function(id) {
		this.$('PFtabPanelContent_'+id).style.display='none';
		this.$('PFtabPanel_'+id).style.padding='0px 5px 2px 6px';
		this.$('PFtabPanel_'+id).style.borderWidth='1px 1px 0px 1px';
	}
}
</script>
JS;

		foreach ($this->id as $idPanel)
			$ids.= "'$idPanel',";
		
		/* Retira todos os espa�os e quebra de linha */
		$js = preg_replace('/[\\r\\n\\t]/',NULL,$js);
		
		return preg_replace('/\{IDS\}/',substr($ids,0,-1),$js);
	}

	private function browser()
	{
		return $_SERVER['HTTP_USER_AGENT'];
	}
}

// +----------------------------------------------+
// | Class TabPanelContent                        |
// | JGNJ                                         |
// +----------------------------------------------+
final class TabPanelContent
{
	private $tab;
	private $tabContent;
	private $style = 'border:1px solid #979797;background:#fff;';
	private $jsCallBack;
	private $_autowidth;
	
	public function __construct($param)
	{
		$t				= $param['tabTitle'];
		$ft			= (bool)$param['firstTab'];
		$padding		= ($ft) ? '2px 5px 3px 6px' : '0px 5px 2px 6px';
		$id			= $param['tabId'];
		$jsClassId	= $param['containerId'];

		$ml = (!$ft) ? NULL : 'margin:0 -1px 0 2px;*margin:0 2px 0 2.8px;';

		// cabe�alho da aba
		$this->tab = "<li id=\"PFtabPanel_$id\"";
		$this->tab.= " style=\"position:relative;display:inline;$ml;cursor:pointer;padding:$padding;";
		$this->tab.= " {CSSCOMP} border-width:1px 1px 0px 1px;\"";
		$this->tab.= " onclick=\"__TabPanel_{$jsClassId}.changeTab('$id');{CALLBACK}\"";
		$this->tab.= ">$t</li>\n";
		
		$mBottom = NULL;
		if (ereg('MSIE',$_SERVER['HTTP_USER_AGENT']))
			$mBottom = "<div style=\"clear:both;\"></div>";

		// conteudo da aba
		$this->tabContent = "<div id=\"PFtabPanelContent_$id\" style=\"";
		$this->tabContent.= ($ft) ? 'display: block;' : 'display: none;';
		$this->tabContent.= "margin-top:2px;padding: 10px 5px 5px 5px; {CSSCOMP}\">\n{TABCONTENT}".$mBottom."</div>\n";
	}

	public function append($type)
	{
		/* para uso do powerform e outros objetos */
		if (!strcmp(gettype($type),'object')) {
			$this->contentBody.= $type->outPut();
			unset($type);
		}
		/* para uso em strings */
		elseif (!strcmp(gettype($type),'string')) {
			$this->contentBody.= $type;
			unset($type);
		}

		return $this;
	}

	/**
	 * TabPanelContent::style()
	 *
	 * @param		string
	 * @param		string
	 * @access		public
	 *
	 * usage:
	 * $objTabPanel->create('aba1','idaba1')->style(array('border'=>'1px solid yellow','background'=>'#ccc'));
	 * $objTabPanel->create('aba1','idaba1')->style('border:1px solid yellow;background:#ccc');
	 */
	public function style($s)
	{
		$arrProibido = array('position','float','margin','padding','width','bottom','right','left');

		// para string
		if (!strcmp(gettype($s),'string')) {
			$s1 = preg_replace('/;$/',NULL,$s);
			unset($s);
			$s = array();

			foreach(explode(';',$s1) as $d) {
	   		list($p,$v) = explode(':',$d);
		   	$s[$p] = $v;
			}
		}

		// se border n�o for setada
		// aplica border default
		if (!isset($s['border']))
			$s['border'] = '1px solid #979797;';

		// se background n�o for setado
		// aplica background padr�o
		if (!isset($s['background']))
			$s['background'] = '#fff;';

		// loop com parametros
		// nega apenas alguns css
		$st = '';
		foreach ($s as $attr => $value) {
			if (!in_array($attr,$arrProibido))
				$st.= "{$attr}:{$value};";
		}

		$this->style = $st;

		return $this;
	}

	public function header()
	{
		$tab = preg_replace('/\{CSSCOMP\}/',$this->style,$this->tab);
	
		if (isset($this->jsCallBack[1])) {
			$tab = preg_replace('/\{CALLBACK\}/',$this->jsCallBack,$tab);
		} else {
			$tab = preg_replace('/\{CALLBACK\}/',NULL,$tab);
		}
		
		return $tab;
	}

	public function body()
	{
		$body = preg_replace('/\{TABCONTENT\}/',$this->contentBody,$this->tabContent);
		$body = preg_replace('/\{CSSCOMP\}/',$this->style,$body);

		return $body;
	}

	/**
	 * TabPanelContent::event()
	 * 
	 * @param 	evento (click,change)
	 * @param 	fun�ao
	 * @param 	parametros da fun��o, n�o obrigat�rio
	 * 
	 * $obj->event('ajax.search',array('23'))	// onclick="ajax.search('23')"
	 * $obj->event('ajax.search',array())		// onclick="ajax.search()"
	 * $obj->event('location=""')					// onclick="location=''"
	 */
	public function event($f,$p='')
	{
		$this->_parseEvent($f,$p);
		return $this;
	}

	private function _parseEvent($jsCall,$params)
	{
		// return jsCall(:params)
		if (!strcmp(gettype($params),'array')) {
			if (isset($params[0])) {
				foreach($params as $values)
					$_params.= (ctype_digit($values)) ? $values."," : "'$values',";
			}
			
			$call = $jsCall."(".substr($_params,0,-1).")";
		}
		// return jsCall - ex: onclick="location='/' "
		else {
			$call = $jsCall;
		}
		
		$this->jsCallBack = $call;

		unset($params);
	}
}
?>