Autocompletar con scriptaculous
Lo que vamos a hacer es un cuadro search box como el google suggest, que a diferencia de este, no haremos una petición ajax al servidor ya que tendremos los valores precargados en una variable javascript, útil cuando los registros son pocos y estáticos.
Reconozco que a estas alturas medio mundo usa jquery, pero como persona de escaso conocimiento en el área, para el propósito me sirvió prototype y scriptaculous.
Lo primero que tenemos que hacer es descargar scriptaculous, y extraemos todos los js dentro de una carpeta javascripts.
El siguiente paso es crear el archivo css.css para darle un diseño bonito al recuadro de opciones que aparecerán conforme vayamos escribiendo, el código de css.css es
div.autocomplete { margin:0px; padding:0px; width:250px; background:#fff; border:1px solid #888; position:absolute; } div.autocomplete ul { margin:0px; padding:0px; list-style-type:none; } div.autocomplete ul li.selected { background-color:#ffb; } div.autocomplete ul li { margin:0; padding:2px; height:32px; display:block; list-style-type:none; cursor:pointer; }
El tercer paso es crear el archivo autocompletar.html donde incluiremos los javascripts de prototype y scriptaculous, automáticamente se incluirán todas las dependencias.
<script type="text/javascript" src="javascripts/prototype.js"></script> <script type="text/javascript" src="javascripts/scriptaculous.js?load=effects,controls"> </script> <script type="text/javascript"> var bandsList = [ 'ABBA', 'AC/DC', 'Aerosmith', 'America', 'Bay City Rollers', 'Black Sabbath', 'Boston', 'David Bowie', 'Can', 'The Carpenters', 'Crass', 'Deep Purple', 'The Doobie Brothers', 'Eagles', 'Fleetwood Mac', 'Haciendo Punto en Otro Son', 'Heart', 'Iggy Pop and the Stooges', 'Journey', 'Judas Priest', 'KC and the Sunshine Band', 'Kiss', 'Kraftwerk', 'Led Zeppelin', 'Lindisfarne (band)', 'Lipps, Inc', 'Lynyrd Skynyrd', 'Pink Floyd', 'Queen', 'Ramones', 'REO Speedwagon', 'Rhythm Heritage', 'Rush', 'Sex Pistols', 'Slade', 'Steely Dan', 'Stillwater', 'Styx', 'Supertramp', 'Sweet', 'Three Dog Night', 'The Village People', 'Wings (fronted by former Beatle Paul McCartney)', 'Yes' </script><script type="text/javascript"> window.onload = function() { new Autocompleter.Local( 'bands_from_the_70s', 'band_list', bandsList, {ignoreCase:false} ); } </script> <body> <p> <label for="bands_from">Your favorite rock band from the 70's:</label> <br /> <input id="bands_from_the_70s" autocomplete="off" size="40" type="text" value="" /> </p> <div class="autocomplete" id="band_list" style="display:none"></div>
Y listo ya con eso debemos tener un textbox con sugerencias.
Enlaces
Autocompleter.Local para ver los parámetros aceptados.
Busquedas de filtros complejos en CakePHP
Para comprender la situación mejor, necesitamos ver el screenshot de la vista.
Hay varias formas de hacer esto, la mas común es usar la función query de CakePHP para armar la consulta SQL en base a condiciones by (@el_keogh) , está la función find, pero no se pueden poner condiciones dentro, así que lo que se puede hacer es armar el array conditions desde afuera de la siguiente forma:
<?php //Bloque #1 asignacion de variables para comodidad $alumnoid=$this->data['Examene']['cuenta']; $user=$this->data['Examene']['user']; $fechaInicio=$this->data['Examene']['Fecha de Inicio']; $fechaFin=$this->data['Examene']['Fecha de Fin']; $formadepago=$this->data['Examene']['forma_de_pago']; $resultado=$this->data['Examene']['resultado']; $conditions=array(); //Bloque #2 Condiciones tabla Alumnos if(!empty($this->data['Examene']['nombre'])){ $conditions['Alumno.nombre LIKE']='%'.$this->data['Examene']['nombre'].'%'; } if(!empty($this->data['Examene']['apellido_paterno'])){ $conditions['Alumno.apellido_paterno LIKE']='%'.$this->data['Examene']['apellido_paterno'].'%'; } if(!empty($this->data['Examene']['apellido_materno'])){ $conditions['Alumno.apellido_materno LIKE']='%'.$this->data['Examene']['apellido_materno'].'%'; } //Bloque #3 Condiciones tabla Examenes if(!empty($alumnoid)){ $conditions['Examene.alumno_id']=$alumnoid; } if(!empty($user)){ $conditions['Examene.user_id']=$user; } //Bloque #4 Condiciones de intervalos de fecha if(!empty($fechaInicio)){ $conditions['Examene.created >'] = $fechaInicio; } if(!empty($fechaFin)){ $conditions['Examene.created <='] =$fechaFin.' 23:59:59'; } if(!empty($formadepago)){ $conditions['Examene.forma_de_pago'] =$formadepago; } if(!empty($resultado)){ $conditions['Examene.resultado'] =$resultado; } //Bloque #5 query $conditions['Examene.statusid <>']=4; $examenes= $this->paginate($conditions); ?>
Bloque #1 asignación de variables
En este caso se manejan dos tablas distintas de la base de datos, están relacionadas entre si, Alumnos y Examenes, utilicé asignación de variables para mas comodidad en su manejo, pero no son necesarias.
Bloque #2 Condiciones de tabla Alumnos
Las condiciones determinan cuando hay datos en los campos, si no hay datos, no hay condición que aplicar y nada que meter en el array, las primeras tres condiciones pertenecen a la tabla alumnos, de la cual se va a buscar por nombre NO exacto por eso los LIKE y la concatenación del símbolo de porcentaje. Para que esto funcione, las relaciones en el modelo deben estar previamente establecidas.
Bloque #3 Condiciones de tabla Examenes
En el segundo bloque ponemos las condiciones de la otra tabla, nada especial ya que los valores de esos campos deben ser exactos.
Bloque #4 Condiciones de intervalos de fecha
Para cuando tenemos intervalos de fechas y tenemos el formato en Datetime, es necesario concatenar la hora en la que termina el dia, si no lo hiciéramos contaría hasta la hora 00:00:00 no devolviéndonos los resultados del ultimo dia especificado.
Bloque #5 Query
La función paginate, se utiliza casi de la misma manera que un find y listo automagicamente cakephp devolverá solo los exámenes de los campos donde se les haya especificado algun dato, notese que este tipo de búsqueda es de tipo AND, o sea cada campo va filtrando aun mas la búsqueda, en lugar de añadir nuevas coincidencias.
Cualquier duda o comentario es bienvenido.
Referencias
Complex Find Conditions
Pagination in cakephp
cakephp-instaweb
cakephp-instaweb server es un webserver pequeño con todas las configuraciones necesarias para desarrollar en cakephp, no necesitas instalar todo el entorno php. Funciona igual al django-runserver, solo en la terminal te colocas en la carpeta de la aplicación, corres el comando y listo, tendrás tu app funcionando en http://localhost.com:3000
Si usas Ubuntu 10.10 y cakephp 1.3.8 te marcará un error
CGI Script Error
Premature end of script headers.
Si instalaste cakephp-instaweb desde los repositorios de maverick se habrá instalado la versión 0.4.X, el error anterior se soluciona con la versión mas nueva 0.5-1 para instalarlo primero debes desinstalar completamente el cakephp-instaweb y luego descargar el .deb desde launchpad para Ubuntu Natty, no causa conflicto alguno.
Con eso se habrá solucionado el problema.
Como Actualizar un Div con Ajax y CakePHP 1.2
Empezaré suponiendo que tienes nociones básicas sobre CakePHP1.2 y sabes hacer de perdida un CRUD.
Agregar las librerías javascript
Cakephp tiene una buena integración con las librerías javascript de prototype y scriptaculous, las cuales debemos descargarlas primero desde la pagina de descarga de scriptaculous y la de descargas de prototype, la de prototype es un archivo js. Renombrar a prototype.js y ponlo en "app/webroot/js".
La librería de scriptaculous es un archivo .zip que contiene una carpeta src que a su vez contiene muchos archivos js los cuales debemos copiar y ponerlos también en la app/webroot/js.
Añadir los helpers javascript y ajax al controlador
Ahora necesitamos agregar los helpers de javascript y de ajax. Una opcion es agregarlos a cada controlador a como la vayamos necesitando o agregarlos al app_controller para que estén disponibles en todos los controladores.
class AppController extends Controller {
var $helpers = array('Html','Form','Javascript','Ajax');
}
<h3>Vistas</h3>
Cada vista que sue javascript debemos añadirle las siguientes etiquetas
<?php
echo $javascript->link('prototype');
echo $javascript->link('scriptaculous');
?>
<h2>Ajax 3 - testing ajax link and button</h2>
<?php
$link_array1 = array('controller'=>'tweets' ,'action'=>'simple_ajax1_fcn');
//the function to execute: function ajaxfcn1 in controller tests
$link_array2 = array( 'update' => 'divout');
echo ($ajax->link('this an ajax link', $link_array1,$link_array2));
echo "<br/><br/>";
?>
<br/>
<div id="divout">
the div to update
</div>Controlador
<?php class TweetsController extends AppController { var $name = 'Tweets'; var $uses = array(); // prevent cake from looking for a database model var $helpers = array('Html','Ajax','Javascript'); function index() { } function simple_ajax1_fcn() { $this->autoRender = false; echo "text from ajax call"; } }?>
Configurar Eclipse Para Colorear Sintaxis De Los Archivos .CTP de CakePHP
CakePHP 1.2 maneja las vistas con una extensión .CTP lo cual hace que no puedas ver coloreado los archivos, que son en esencia HTML y PHP combinado.
Para solucionar esto debemos hacer lo siguiente en el Eclipse:
Window -> Preferences -> General -> Content Type -> Text
Y en el recuadro seleccionamos donde dice HTML, al hacer esto, un poco mas abajo está el botón Add y después de presionarlo escribimos *.ctp y damos aceptar.
Ahora así como seleccionamos HTML seleccionaremos PHP Source File, y añadimos de la misma forma.
Damos aceptar dos veces, y automáticamente los nuevos archivos que abras aparecerán coloreados.
