Index: trunk/workflow/doc/change_log.txt
===================================================================
--- trunk/workflow/doc/change_log.txt	(revision 1395)
+++ trunk/workflow/doc/change_log.txt	(revision 1446)
@@ -21,4 +21,7 @@
 [2.0.000]
 
+	* Inclusão de click-to-call no organograma e outras melhorias na interface. (rodsouza)
+	* Criação do método createNewInstance na classe JobBase, que possibilita iniciar uma instância do processo a partir de um job. (rufino)
+	* Criação do plugin wf_autocomplete_input, para listar com autocomplete o resultado de uma busca ajax. (rufino)
 	* Correção de bug no método getByUser da classe wf_instance. (hermespinheiro)
 	* Melhorias no organograma, com novas visualizações nas interfaces. (rodsouza)
Index: trunk/workflow/inc/class.so_orgchart.inc.php
===================================================================
--- trunk/workflow/inc/class.so_orgchart.inc.php	(revision 1353)
+++ trunk/workflow/inc/class.so_orgchart.inc.php	(revision 1446)
@@ -1159,4 +1159,8 @@
 			'value' => $areaInfo['sigla']);
 
+		$outputInfo[] = array(
+			'name' => 'ÁreaID',
+			'value' => $employeeInfo['area_id']);
+
 		$localInfo = $orgchart->getLocal($employeeInfo['localidade_id']);
 		$outputInfo[] = array(
Index: trunk/workflow/inc/class.so_userinterface.inc.php
===================================================================
--- trunk/workflow/inc/class.so_userinterface.inc.php	(revision 1310)
+++ trunk/workflow/inc/class.so_userinterface.inc.php	(revision 1446)
@@ -352,9 +352,10 @@
 	{
 		/* initialize some variables */
-		$output = array('employees' => array());
+		$output = array('employees' => array(), 'bygroup' => array( ) );
 		$ldapResult = array();
 
 		/* search for the $searchTerm in the LDAP */
 		$ldap = &$GLOBALS['workflow']['workflowObjects']->getLDAP();
+
 		$list = @ldap_search($ldap, $GLOBALS['workflow']['factory']->getInstance('WorkflowLDAP')->getLDAPContext(), ('(&(cn=*' . $searchTerm . '*)(phpgwaccounttype=u))'), array('uidNumber', 'cn', 'telephoneNumber'));
 		if ($list === false)
@@ -367,10 +368,24 @@
 
 		/* check if any result was found */
-		if (count($ldapResult) < 1)
-			return $output;
+		//if (count($ldapResult) < 1)
+		//	return $output;
+
+		$uids = implode( ',', array_keys( $ldapResult ) );
 
 		/* load employee information */
-		$query = "SELECT f.funcionario_id AS funcionario_id, f.area_id AS area_id, a.sigla AS area FROM funcionario f, area a, funcionario_status s WHERE (f.area_id = a.area_id) AND (f.organizacao_id = $organizationID) AND (f.funcionario_id IN (" . implode(',', array_keys($ldapResult))  .")) AND (f.funcionario_status_id = s.funcionario_status_id) AND (s.exibir = 'S')";
-		$result = $this->db->query($query);
+		$query = 'SELECT f.funcionario_id AS funcionario_id, f.area_id AS area_id, a.sigla AS area';
+		$query .= ' FROM funcionario f, area a, funcionario_status s';
+		$query .= " WHERE (f.area_id = a.area_id) AND (f.organizacao_id = {$organizationID})";
+		$query .= " AND (" . ( ( ! empty( $uids ) ) ? "f.funcionario_id IN ({$uids}) OR " : '' );
+		$query .= " a.sigla LIKE UPPER(?))";
+		$query .= " AND (f.funcionario_status_id = s.funcionario_status_id) AND (s.exibir = 'S')";
+		$query .= " ORDER BY a.sigla asc";
+
+		$result = $this->db->query($query, array( "%{$searchTerm}%" ) );
+
+		if ( ! $result )
+			return array( );
+
+		$uids = array( );
 
 		$employees = $result->GetArray(-1);
@@ -379,9 +394,39 @@
 			for ($j = 0; $j < $result->_numOfFields; $j++)
 				unset($employees[$i][$j]);
-			$employees[$i]['cn'] = is_null($ldapResult[$employees[$i]['funcionario_id']]['cn']) ? '' : $ldapResult[$employees[$i]['funcionario_id']]['cn'];
-			$employees[$i]['telephoneNumber'] = is_null($ldapResult[$employees[$i]['funcionario_id']]['telephoneNumber']) ? '' : $ldapResult[$employees[$i]['funcionario_id']]['telephoneNumber'];
-		}
-
-		$output['employees'] = $employees;
+
+			if ( array_key_exists( $employees[$i]['funcionario_id'], $ldapResult ) )
+			{
+				$employees[$i]['cn'] = is_null($ldapResult[$employees[$i]['funcionario_id']]['cn']) ? '' : $ldapResult[$employees[$i]['funcionario_id']]['cn'];
+				$employees[$i]['telephoneNumber'] = is_null($ldapResult[$employees[$i]['funcionario_id']]['telephoneNumber']) ? '' : $ldapResult[$employees[$i]['funcionario_id']]['telephoneNumber'];
+			}
+			else
+			{
+				$employees[$i]['cn'] = $employees[$i]['funcionario_id'];
+				$employees[$i]['telephoneNumber'] = '';
+
+				$output['bygroup'][ $employees[$i]['funcionario_id'] ] = $employees[ $i ];
+				array_splice( $employees, $i--, 1 );
+			}
+		}
+
+		if ( count( $output['bygroup'] ) )
+		{
+			$list = ldap_search($ldap, $GLOBALS['workflow']['factory']->getInstance('WorkflowLDAP')->getLDAPContext(), ('(&(|(uidNumber=' . implode( ')(uidNumber=', array_keys( $output['bygroup'] ) ) . '))(phpgwaccounttype=u))'), array('uidNumber', 'cn', 'telephoneNumber'));
+
+			if ( $list !== false )
+			{
+				$entries = ldap_get_entries($ldap, $list);
+
+				for ( $i = 0; $i < $entries[ 'count' ]; $i++ )
+				{
+					$output[ 'bygroup' ][ $entries[$i]['uidnumber'][0] ][ 'cn' ] = $entries[$i]['cn'][0];
+					$output[ 'bygroup' ][ $entries[$i]['uidnumber'][0] ][ 'telephoneNumber' ] = $entries[$i]['telephonenumber'][0];
+				}
+			}
+		}
+
+		$output[ 'bygroup' ] = array_values( $output[ 'bygroup' ] );
+		$output[ 'employees' ] = $employees;
+
 		return $output;
 	}
Index: trunk/workflow/inc/class.bo_userinterface.inc.php
===================================================================
--- trunk/workflow/inc/class.bo_userinterface.inc.php	(revision 1277)
+++ trunk/workflow/inc/class.bo_userinterface.inc.php	(revision 1446)
@@ -1059,4 +1059,55 @@
 		return $employees;
 	}
+
+	function callVoipConnect($params)
+	{
+		$cachedLDAP = $GLOBALS['workflow']['factory']->newInstance('CachedLDAP');
+		$cachedLDAP->setOperationMode($cachedLDAP->OPERATION_MODE_LDAP);
+
+		$entry = $cachedLDAP->getEntryByID( $_SESSION['phpgw_info']['workflow']['account_id'] );
+		if ( $entry && ! is_null($entry['telephonenumber']) )
+			$fromNumber = $entry['telephonenumber'];
+
+		if ( $fromNumber == false )
+			return false;
+
+		$toNumber	= $params['to'];
+
+		$voipServer	= $_SESSION['phpgw_info']['workflow']['server']['voip_server'];
+		$voipUrl	= $_SESSION['phpgw_info']['workflow']['server']['voip_url'];
+		$voipPort	= $_SESSION['phpgw_info']['workflow']['server']['voip_port'];
+
+		if(!$voipServer || !$voipUrl || !$voipPort)
+			return false;
+
+		$url		= "http://".$voipServer.":".$voipPort.$voipUrl."?magic=1333&acao=liga&ramal=".$fromNumber."&numero=".$toNumber;			
+		$sMethod = 'GET ';
+		$crlf = "\r\n";
+		$sRequest = " HTTP/1.1" . $crlf;
+		$sRequest .= "Host: localhost" . $crlf;
+		$sRequest .= "Accept: */* " . $crlf;
+		$sRequest .= "Connection: Close" . $crlf . $crlf;            
+		$sRequest = $sMethod . $url . $sRequest;    
+		$sockHttp = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);            
+		if (!$sockHttp)  {
+			return false;
+		}
+		$resSocketConnect = socket_connect($sockHttp, $voipServer, $voipPort);
+		if (!$resSocketConnect) {
+			return false;
+		}
+		$resSocketWrite = socket_write($sockHttp, $sRequest, strlen($sRequest));
+		if (!$resSocketWrite) {
+			return false;
+		}    
+		$sResponse = '';    
+		while ($sRead = socket_read($sockHttp, 512)) {
+			$sResponse .= $sRead;
+		}            
+
+		socket_close($sockHttp);            
+		$pos = strpos($sResponse, $crlf . $crlf);
+		return substr($sResponse, $pos + 2 * strlen($crlf));									
+	}
 }
 ?>
Index: trunk/workflow/js/userinterface/orgchart.js
===================================================================
--- trunk/workflow/js/userinterface/orgchart.js	(revision 1353)
+++ trunk/workflow/js/userinterface/orgchart.js	(revision 1446)
@@ -34,5 +34,5 @@
 
 	var content = '<ul class="horizontalMenu">';
-	content += '<li style="margin: 5px 5px 0 5px">Visualizar : <select onclick="this.parentNode.parentNode.lastChild.style.display = (this.options[1].selected) ? \'block\' : \'none\' ">'
+	content += '<li><a onclick="return false;">Visualizar : <select onclick="this.parentNode.parentNode.parentNode.lastChild.style.display = (this.options[1].selected) ? \'block\' : \'none\' ">'
 	content += '<option onclick="getAlphabeticalEmployees( )">Alfabética</option>'
 	content += '<option onclick="getHierarchicalArea( );" selected="true">Áreas</option>'
@@ -42,5 +42,5 @@
 	content += '<option onclick="getUsefulPhones( );">Telefones Úteis</option>'
 	content += '<option onclick="getCategoriesList( )">Vínculos</option>'
-	content += '</select></li>';
+	content += '</select></a></li>';
 	content += '<li><a href="#" onclick="window.open(\'' + enderecoImagem + '\', \'extwindow\'); return false;"><img src="templateFile.php?file=images/Process.gif">&nbsp;&nbsp;Gráfico</a></li>';
 	content += '<li><a><input type="text" name="search_term" id="search_term" onkeypress="if (((event.which) ? event.which : event.keyCode) == 13) $(\'search_span\').onclick(); return true;" /><span id="search_span" style="cursor: pointer;" onclick="tmp = $$(\'div#orgchartAreas a.destaque\'); if (tmp[0]) tmp[0].removeClassName(\'destaque\'); orgchartSearchEmployee($F(\'search_term\')); return false;">&nbsp;busca</span></a></li>';
@@ -51,4 +51,6 @@
 
 	$('orgchartMenu').innerHTML = content;
+
+	$( 'search_term' ).focus( );
 }
 
@@ -102,5 +104,5 @@
 	}
 
-	var content = '';
+	var content = '<center><h2>Centros de Custo</h2></center>';
 	content += '<table class="employeeList">';
 	content += '<tr><th>Nome</th><th>Número</th><th>Grupo</th></tr>';
@@ -110,5 +112,5 @@
 	{
 		current = data[i];
-		content += '<tr class="linha'+ i%2 + '">';
+		content += '<tr class="linha'+ i%2 + '" onmouseover="this.className=\'highlight0\'" onmouseout="this.className=\'linha' + i%2 + '\'">';
 		content += '<td>' + current['descricao'] + '</td>';
 		content += '<td>' + current['nm_centro_custo'] + '</td>';
@@ -132,13 +134,12 @@
 	}
 
-	var content = '';
+	var content = '<center><h2>Telefones Úteis</h2></center>';
 	content += '<table class="employeeList">';
 	content += '<tr><th>Localidade</th><th>Número</th></tr>';
 	var current;
-	var usefulPhoneCount = data.length;
-	for (var i = 0; i < usefulPhoneCount; i++)
+	for (var i = 0; i < data.length; i++)
 	{
 		current = data[i];
-		content += '<tr class="linha'+ i%2 + '">';
+		content += '<tr class="linha'+ i%2 + '" onmouseover="this.className=\'highlight0\'" onmouseout="this.className=\'linha' + i%2 + '\'">';
 		content += '<td>' + current[ 'descricao' ] + '</td>';
 		content += '<td>' + current[ 'numero' ] + '</td>';
@@ -161,13 +162,12 @@
 	}
 
-	var content = '';
+	var content = '<center><h2>Substituição de Chefia</h2></center>';
 	content += '<table class="employeeList">';
 	content += '<tr><th>Área</th><th>Titular</th><th>Substituto</th></tr>';
 	var current;
-	var usefulPhoneCount = data.length;
-	for (var i = 0; i < usefulPhoneCount; i++)
+	for (var i = 0; i < data.length; i++)
 	{
 		current = data[i];
-		content += '<tr class="linha'+ i%2 + '">';
+		content += '<tr class="linha'+ i%2 + '" onmouseover="this.className=\'highlight0\'" onmouseout="this.className=\'linha' + i%2 + '\'">';
 		content += '<td>' + current['area'] + '</td>';
 		content += '<td>' + current['titular'] + '</td>';
@@ -188,5 +188,5 @@
 		for (var i = 0; i < subdata.length; i++)
 		{
-			div.innerHTML += '<br />' + '&nbsp;&nbsp;&nbsp;&nbsp;'.repeat(subdata[i]['depth']) + '<a href="javascript:void(0)" id="area_' + subdata[i]['area_id'] + '" onmouseover="getAreaInfoTimer(event, ' + subdata[i]['area_id'] + '); return false;" onmouseout="hideAreaInfo(); return false;" onclick="tmp = $$(\'div#orgchartAreas a.destaque\'); if (tmp[0]) tmp[0].removeClassName(\'destaque\'); this.addClassName(\'destaque\'); loadAreaEmployees(' + subdata[i]['area_id'] + ')">' + subdata[i]['sigla'] + '</a>';
+			div.innerHTML += '<br />' + '&nbsp;&nbsp;&nbsp;&nbsp;'.repeat(subdata[i]['depth']) + '<a href="javascript:void(0)" id="area_' + subdata[i]['area_id'] + '" onmouseover="getAreaInfoTimer(event, ' + subdata[i]['area_id'] + '); return false;" onmouseout="hideAreaInfo(); return false;" onclick="tmp = $$(\'div#orgchartAreas a.destaque\'); if (tmp[0]) tmp[0].removeClassName(\'destaque\'); this.addClassName(\'destaque\'); loadAreaEmployees(' + subdata[i]['area_id'] + ', \'' + subdata[i]['sigla'] + '\')">' + subdata[i]['sigla'] + '</a>';
 			if (subdata[i]['children'].length > 0)
 				recursivePrint(subdata[i]['children']);
@@ -246,5 +246,5 @@
 		var content = '<center><strong>VÍNCULOS</strong></center>';
 		for (var i = 0; i < data.length; i++)
-			content += '<br/>' + '&nbsp;&nbsp;<a href="javascript:void(0)" id="categoria_' + data[i]['funcionario_categoria_id'] + '" onclick="tmp = $$(\'div#orgchartAreas a.destaque\'); if (tmp[0]) tmp[0].removeClassName(\'destaque\'); this.addClassName(\'destaque\'); loadCategoryEmployees(' + data[i]['funcionario_categoria_id'] + ')">' + data[i]['descricao'] + ' (' + data[i]['contagem'] + ')</a>';
+			content += '<br/>' + '&nbsp;&nbsp;<a href="javascript:void(0)" id="categoria_' + data[i]['funcionario_categoria_id'] + '" onclick="tmp = $$(\'div#orgchartAreas a.destaque\'); if (tmp[0]) tmp[0].removeClassName(\'destaque\'); this.addClassName(\'destaque\'); loadCategoryEmployees(' + data[i]['funcionario_categoria_id'] + ', \'' + data[i]['descricao'] + '\')">' + data[i]['descricao'] + ' (' + data[i]['contagem'] + ')</a>';
 		content += '<br/><br/>';
 		$('orgchartAreas').innerHTML = content;
@@ -268,5 +268,5 @@
 		var content = '<center><strong>Localidades</strong></center>';
 		for ( var i = 0; i < data.length; i++ )
-			content += '<br/>' + '&nbsp;<a href="javascript:void(0)" id="localidade_' + data[i]['localidade_id'] + '" onclick="tmp = $$(\'div#orgchartAreas a.destaque\'); if (tmp[0]) tmp[0].removeClassName(\'destaque\'); this.addClassName(\'destaque\');loadManningEmployees(' + data[i]['localidade_id'] + ')">' + data[i]['descricao'] + '</a>';
+			content += '<br/>' + '&nbsp;<a href="javascript:void(0)" id="localidade_' + data[i]['localidade_id'] + '" onclick="tmp = $$(\'div#orgchartAreas a.destaque\'); if (tmp[0]) tmp[0].removeClassName(\'destaque\'); this.addClassName(\'destaque\');loadManningEmployees(' + data[i]['localidade_id'] + ', \'' + data[i]['descricao'] + '\')">' + data[i]['descricao'] + '</a>';
 
 		content += '<br/><br/>';
@@ -287,5 +287,5 @@
 
 	/* no employee to list */
-	if (data['employees'].length == 0)
+	if ( ( ! data['employees'] || data['employees'].length == 0 ) && ( ! data['bygroup'] || data['bygroup'].length == 0 ) )
 	{
 		div.innerHTML = '<br/><br/><center><strong>Nenhum registro encontrado</strong></center>';
@@ -293,59 +293,68 @@
 	}
 
-	/* initialize varivables */
-	var content = '';
-	var employees = data['employees'];
-	var useCategories = false;
-	var useArea = false;
-
-	/* check the informations that will be displayed */
-	if (data['categories'])
-		if (data['categories'].length > 1)
-			useCategories = true;
-	if (employees[0]['area'])
-		useArea = true;
-
-	/* build the display table (headers)*/
-	content += '<table id="employeeList" class="employeeList" style="clear: both">';
-	content += '<tr>';
-	content += '<th>Funcionário</th>';
-	if (useArea)
-		content += '<th>Área</th>';
-	content += '<th>Telefone</th>';
-	content += '</tr>';
-
-	/* if available, insert a menu to filter the categories */
-	if (useCategories)
-	{
-		content += '<tr><td colspan="' + (useArea ? '3' : '2') + '">';
-		content += '<ul class="horizontalMenu">';
-		for (var i = 0; i < data['categories'].length; i++)
-			content += '<li><a href="#" style="height: 2em; line-height: 2em;" onclick="highlightCategory(' + data['categories'][i]['funcionario_categoria_id'] + '); return false;">' + data['categories'][i]['descricao'] + ' (' + data['categories'][i]['contagem'] + ')</a></li>';
-		content += '</ul>';
-		content += '</td></tr>';
-	}
-
-	/* list the employees */
-	var complement = '';
-	for (var i = 0; i < employees.length; i++)
-	{
-		if (employees[i]['chief'])
-			complement = ' <strong>(' + ((employees[i]['chief'] == 1) ? 'Titular' : 'Substituto') + ')</strong>';
+	if ( data['employees'] && data['employees'].length )
+	{
+		/* initialize varivables */
+		var content = '';
+		var employees = data['employees'];
+		var useCategories = false;
+		var useArea = false;
+
+		/* check the informations that will be displayed */
+		if (data['categories'])
+			if (data['categories'].length > 1)
+				useCategories = true;
+		if (employees[0]['area'])
+			useArea = true;
+
+		/* build the display table (headers)*/
+		content += '<table id="employeeList" class="employeeList" style="clear: both">';
+		content += '<tr>';
+		content += '<th>Nome</th>';
+		if (useArea)
+			content += '<th>Área</th>';
+		content += '<th>Telefone</th>';
+		content += '</tr>';
+
+		/* if available, insert a menu to filter the categories */
+		if (useCategories)
+		{
+			content += '<tr><td colspan="' + (useArea ? '3' : '2') + '">';
+			content += '<ul class="horizontalMenu">';
+			for (var i = 0; i < data['categories'].length; i++)
+				content += '<li><a href="#" style="height: 2em; line-height: 2em;" onclick="highlightCategory(' + data['categories'][i]['funcionario_categoria_id'] + '); return false;">' + data['categories'][i]['descricao'] + ' (' + data['categories'][i]['contagem'] + ')</a></li>';
+			content += '</ul>';
+			content += '</td></tr>';
+		}
+
+		/* list the employees */
+		var complement = '';
+		for (var i = 0; i < employees.length; i++)
+		{
+			if (employees[i]['chief'])
+				complement = ' <strong>(' + ((employees[i]['chief'] == 1) ? 'Titular' : 'Substituto') + ')</strong>';
+			else
+				complement = '';
+			if (employees[i]['removed'])
+				complement += ' <font color="red">(excluído)</font>';
+			content += '<tr class="linha'+ i%2 + (useCategories ? ' categoria_' + employees[i]['funcionario_categoria_id'] : '') + '" onmouseover="this.className=\'highlight0\'" onmouseout="this.className=\'linha'+ i%2 + (useCategories ? ' categoria_' + employees[i]['funcionario_categoria_id'] : '') + '\'">';
+			content += '<td><a href="javascript:void(0);" onmouseover="getEmployeeInfoTimer(event, ' + employees[i]['funcionario_id'] + '); return false;" onmouseout="hideEmployeeInfo(); return false;">' + employees[i]['cn'] + complement + '</a></td>';
+			if (useArea)
+				content += '<td><a href="javascript:void(0);" onclick="loadAreaEmployees(\''+employees[i]['area_id']+'\', \'' + employees[i]['area'] + '\')">' + employees[i]['area'] + '</a></td>';
+			content += '<td align="center"><a href="javascript:void(0);"';
+			content += ' onclick="callVoipConnect(\''+employees[i]['telephoneNumber']+'\')">' + employees[i]['telephoneNumber'] + '</a></td>';
+			content += '</tr>';
+		}
+		content += '</table>';
+
+		if ( arguments[ 1 ] != 'returnResult' )
+		{
+			/* display the employees list and go to the top of the page */
+			div.innerHTML = content;
+			window.scrollTo(0,0);
+		}
 		else
-			complement = '';
-		if (employees[i]['removed'])
-			complement += ' <font color="red">(excluído)</font>';
-		content += '<tr class="linha'+ i%2 + (useCategories ? ' categoria_' + employees[i]['funcionario_categoria_id'] : '') + '">';
-		content += '<td><a href="javascript:void(0);" onmouseover="getEmployeeInfoTimer(event, ' + employees[i]['funcionario_id'] + '); return false;" onmouseout="hideEmployeeInfo(); return false;">' + employees[i]['cn'] + complement + '</a></td>';
-		if (useArea)
-			content += '<td>' + employees[i]['area'] + '</td>';
-		content += '<td align="center">' + employees[i]['telephoneNumber'] + '</td>';
-		content += '</tr>';
-	}
-	content += '</table>';
-
-	/* display the employees list and go to the top of the page */
-	div.innerHTML = content;
-	window.scrollTo(0,0);
+			return content;
+	}
 }
 
@@ -369,20 +378,38 @@
 }
 
-function loadAreaEmployees(areaID)
+function loadAreaEmployees(areaID, areaName)
 {
 	workflowUserInterfaceCurrentAreaID = areaID;
-	cExecute('$this.bo_userinterface.getAreaEmployees', printEmployeesHandler, 'areaID=' + areaID);
-}
-
-function loadCategoryEmployees(categoryID)
-{
-	workflowUserInterfaceCurrentAreaID = 0;
-	cExecute('$this.bo_userinterface.getCategoryEmployees', printEmployeesHandler, 'categoryID=' + categoryID);
-}
-
-function loadManningEmployees( locationID )
-{
-	workflowUserInterfaceCurrentAreaID = 0;
-	cExecute('$this.bo_userinterface.getManningEmployees', printEmployeesHandler, 'locationID=' + locationID);
+	$('orgchartEmployees').innerHTML = '';
+	cExecute('$this.bo_userinterface.getAreaEmployees', function( data )
+	{
+		var content = printEmployeesHandler( data, 'returnResult' );
+		if ( content )
+			$('orgchartEmployees').innerHTML = '<center><h2>Área: ' + areaName + '</h2></center>' + content;
+	}, 'areaID=' + areaID);
+}
+
+function loadCategoryEmployees(categoryID, categoryName)
+{
+	workflowUserInterfaceCurrentAreaID = 0;
+	$('orgchartEmployees').innerHTML = '';
+	cExecute('$this.bo_userinterface.getCategoryEmployees', function( data )
+	{
+		var content = printEmployeesHandler( data, 'returnResult' );
+		if ( content )
+			$('orgchartEmployees').innerHTML = '<center><h2>Vínculo: ' + categoryName + '</h2></center>' + content;
+	}, 'categoryID=' + categoryID);
+}
+
+function loadManningEmployees( locationID, locationName )
+{
+	workflowUserInterfaceCurrentAreaID = 0;
+	$('orgchartEmployees').innerHTML = '';
+	cExecute('$this.bo_userinterface.getManningEmployees', function( data )
+	{
+		var content = printEmployeesHandler( data, 'returnResult' );
+		if ( content )
+			$('orgchartEmployees').innerHTML = '<center><h2>Localidade: ' + locationName + '</h2></center>' + content;
+	}, 'locationID=' + locationID);
 }
 
@@ -417,7 +444,9 @@
 		}
 
-		printEmployeesHandler( data );
-
-		div.innerHTML += '<br /><center>' + output + '</center>';
+		var content = '<center><h2>Vizualização Alfabética</h2></center>';
+		content += printEmployeesHandler( data, 'returnResult' );
+		content += '<br /><center>' + output + '</center>';
+		div.innerHTML = content;
+
 	}, 'p_page='+p_page);
 }
@@ -426,5 +455,23 @@
 {
 	workflowUserInterfaceCurrentAreaID = 0;
-	cExecute('$this.bo_userinterface.searchEmployee', printEmployeesHandler, 'searchTerm=' + searchTerm);
+	var div = $('orgchartEmployees');
+	div.innerHTML = '';
+	cExecute('$this.bo_userinterface.searchEmployee', function( data )
+	{
+		div.innerHTML = '<center><h2>Resultado da Busca</h2>';
+		var content = printEmployeesHandler( data, 'returnResult' );
+		if ( content )
+			div.innerHTML += '</center><span style="color:red">Busca pelo nome: ' + searchTerm.toUpperCase( ) + '</span>' + content;
+
+		if ( data['bygroup'] && data['bygroup'].length )
+		{
+			employees = [ ];
+			employees[ 'employees' ] = data['bygroup'];
+			content = printEmployeesHandler( employees, 'returnResult' );
+			if ( content )
+				div.innerHTML += '<br/><br/><span style="color:red">Busca pelo setor: ' + searchTerm.toUpperCase( ) + '</span><br/>' + content;
+		}
+
+	}, 'searchTerm=' + searchTerm);
 }
 
@@ -441,6 +488,7 @@
 {
 	var div = $('employeeInfo');
-	div.style.left = (Event.pointerX(e) + 20) + 'px';
+	div.style.left = (Event.pointerX(e) - 50) + 'px';
 	div.style.top = (Event.pointerY(e) + 14) + 'px';
+	div.hide();
 
 	if (workflowUserInterfaceEmployeeInfoTimer != null)
@@ -472,4 +520,15 @@
 		card.style.padding = '5px';
 		card.style.marginRight = '70px';
+
+		card.onmouseover = function( )
+		{
+			workflowUserInterfaceEmployeeInfoTimer = clearTimeout(workflowUserInterfaceEmployeeInfoTimer);
+			workflowUserInterfaceEmployeeInfoTimer = null;
+		}
+
+		card.onmouseout = function( )
+		{
+			workflowUserInterfaceEmployeeInfoTimer = setTimeout( "$('employeeInfo').hide( )", 1000 );
+		}
 
 		var photo = document.createElement( 'img' );
@@ -496,5 +555,21 @@
 			if ( role )
 				card.appendChild( document.createTextNode( ' - ' ) );
-			card.appendChild( document.createTextNode( card_data[ 'Área' ] ) );
+
+			var area = document.createElement( 'a' );
+			area.href = "javascript:void(0)";
+			area.appendChild( document.createTextNode( card_data[ 'Área' ] ) );
+			area.onclick = function( )
+			{
+				loadAreaEmployees( card_data[ 'ÁreaID' ], card_data[ 'Área' ] );
+				$('employeeInfo').hide( );
+			};
+			card.appendChild( area );
+		}
+
+		if ( card_data[ 'Matrícula' ] )
+		{
+			if ( role || area )
+				card.appendChild( document.createElement( 'br' ) );
+			card.appendChild( document.createTextNode( 'Matrícula : ' + card_data[ 'Matrícula' ] ) );
 		}
 
@@ -552,9 +627,16 @@
 		if ( card_data[ 'Telefone' ] )
 		{
-			var phone = document.createElement( 'span' );
+			var phone = document.createElement( 'a' );
 			phone.appendChild( document.createTextNode( card_data[ 'Telefone' ] ) );
 			phone.style.paddingLeft = '20px';
 			phone.style.whiteSpace = 'nowrap';
 			phone.style.background = 'url(templateFile.php?file=images/phone.png) no-repeat 0 0';
+
+			var phoneNumber = card_data[ 'Telefone' ];
+			phone.onclick = function( )
+			{
+				callVoipConnect( phoneNumber );
+			}
+
 			card.appendChild( phone );
 		}
@@ -565,6 +647,7 @@
 		if ( card_data[ 'e-mail' ] )
 		{
-			var mail = document.createElement( 'span' );
+			var mail = document.createElement( 'a' );
 			mail.appendChild( document.createTextNode( card_data[ 'e-mail' ] ) );
+			mail.href = '../expressoMail1_2/index.php?to=' + card_data[ 'e-mail' ];
 			mail.style.paddingLeft = '20px';
 			mail.style.whiteSpace = 'nowrap';
@@ -577,5 +660,7 @@
 		if ( card_data[ 'sitio' ] )
 		{
-			var sitio = document.createElement( 'span' );
+			var sitio = document.createElement( 'a' );
+			sitio.target = '_blank';
+			sitio.href = card_data[ 'sitio' ];
 			sitio.appendChild( document.createTextNode( card_data[ 'sitio' ] ) );
 			sitio.style.paddingLeft = '20px';
@@ -591,5 +676,8 @@
 
 		if ((parseInt(div.style.top.replace(/px/g, '')) + div.getHeight()) > pageYLimit)
-			div.style.top = (parseInt(div.style.top.replace(/px/g, '')) - (div.getHeight())) + 'px';
+			div.style.top = (parseInt(div.style.top.replace(/px/g, '')) - (div.getHeight() - 50)) + 'px';
+		else
+			div.style.top = ( parseInt(div.style.top.replace(/px/g, '')) - 50 ) + 'px';
+
 		div.show();
 	}
@@ -604,5 +692,5 @@
 		workflowUserInterfaceEmployeeInfoTimer = null;
 	}
-	$('employeeInfo').hide();
+	workflowUserInterfaceEmployeeInfoTimer = setTimeout( "$('employeeInfo').hide()", 1000 );
 }
 
@@ -659,2 +747,16 @@
 	$('areaInfo').hide();
 }
+
+function callVoipConnect( phoneNumber )
+{
+	var handler_connectVoip = function(data){
+		if(!data) {
+			alert("Error contacting VoIP server.");
+		}
+		else{
+			alert("Requesting a VoIP call"+":\n"+data);
+		}
+	}
+
+	cExecute( '$this.bo_userinterface.callVoipConnect&to='+phoneNumber+"&typePhone=com", handler_connectVoip );
+}
