Identifícate...

...o regístrate

codeando.net

Categoría: Tutoriales

vie, 15 oct 2010 - Archivado en Javascript, CSS, Libs, Diseño y Tutoriales

Una excelente recopilación de plugins, tutoriales y técnicas de jQuery:

All About jQuery: Plugins, Tutorials and Resources

http://www.noupe.com/jquery/all-about-jquery-plugins-tutorials-and-resources.html

Por Jose. Han entrado 4588 veces.  Comentarios
mar, 03 feb 2009 - Archivado en Javascript, CSS, Diseño y Tutoriales

Hola de nuevo, esta vez hemos estado más tiempo del que habríamos querido sin actualizar, pero aquí estamos de nuevo. Hoy vamos a explicar cómo hemos implementado el nuevo formulario de login (y de registro) que podéis ver si pulsais sobre el enlace que deberíais ver en la parte derecha de la cabecera y que está basado en el que podéis encontrar en este estupendo post de NETTUTS.

Bueno, para empezar crearemos la estructura HTML:

<div id="wrapper">
    <div id="panel">
        <div id="panel_contents">
        </div>
    </div>
    <div id="show_button"><a href="#">Login</a></div>
    <div id="hide_button"><a href="#">Esconder</a></div>
</div>

Como podéis ver, el código HTML es totalmente limpio, ni siquiera los enlaces llaman a funciones javascript (esto lo arreglamos luego gracias a las virtudes de jQuery). El contenido del panel irá, como ya habreis supuesto, en #panel_contents; en codeando.net hemos decidido incluir dos formularios, el de login y el de registro, pero cada uno puede colocar lo que desee.

El siguiente paso, será definir los estilos básicos (visibilidad, tamaño y posicionamiento):

#wrapper{
	text-align: center;
}
 
#toppanel {
	position: absolute;
	top: 134px;
	width: 612px;
	z-index: 25;
	text-align: center;
	margin-left: auto;
	margin-right: auto;
}
 
#panel {
	width: 612px;
	position: relative;
	top: 1px;
	height: 400px;
	margin-left: auto;
	margin-right: auto;
	height: 0px;
	z-index: 10;
	overflow: hidden;
	text-align: left;
}
 
#panel_contents {
	height: 100%;
	width: 616px;
	position: absolute;
	z-index: -1;
}
 
#show_button {
	position: relative;
	top: -30px;
	left: 460px;
}
 
#hide_button {
	position: relative;
	font-size: 90%;
	font-weight: bold;
	z-index: 26;
	margin-top: -36px;
}

Por supuesto, el aspecto y el posicionamiento final dependerá de vuestras necesidades de diseño; este ejemplo está basado en la implementación que hemos hecho en codeando.net.

Y por último el código javascript que hará que funcione nuestro panel desplegable:

<script type="text/javascript"><!--
	$(document).ready(function() {
		$("div#show_button").click(function(){
			$("div#show_button").toggle();
			$("div#panel").animate({
				height: "460px"
			}, "fast", "swing", function() {$("div#hide_button").toggle();});
 
		});
 
		$("div#hide_button").click(function(){
			$("div#hide_button").toggle();
			$("div#panel").animate({
				height: "0px"
			}, "fast", "swing", function(){$("div#show_button").toggle();});
 
		});
 
	});
--></script>

Y con esto ya deberíamos tener nuestro panel funcionando, todo comentario será bien recibido. En otra entrega veremos cómo implementar un sistema de registro de usuarios con activación por email.

Por Jose. Han entrado 32398 veces. Hay 13 comentarios       
mié, 17 dic 2008 - Archivado en PHP, Libs, Tutoriales y Bases de datos

En la segunda entrega de esta serie, vamos a implementar métodos para la extracción y manipulación de datos. Comenzaremos con las funciones de acceso a datos, que serán las siguientes:

  • getrow() nos devuelve un array con todos los campos de un registro determinado.
  • getassoc() como getrow() pero los índices del array son una cadena con el nombre del campo.
  • getarrayassoc() nos devuelve un array multidimensional que contiene un rango de registros, cada uno de los cuales con todos sus campos en un array asociativo.
<?php
 
	public function getrow( $row = 0, $query = 'main' ) {
 
		$return = false;
 
		for ($ct=0;$ct<$this->queries[$query]['numfields'];$ct++) {
			$return[$ct] = $this->get($row, $ct);
		}
 
		return $return;
 
	}
 
	public function getassoc( $row = 0, $query = 'main' ) {
 
		$return = false;
 
		for ($ct=0;$ct<$this->queries[$query]['numfields'];$ct++) {
			$return[$this->queries[$query]['fields'][$ct]['name']] = $this->get($row, $ct);
		}
 
		return $return;
 
	}
 
	public function getarrayassoc( $start = 0, $end = 0, $query = 'main' ) {
 
		$return = false;
 
		if ($end == 0) {
			$end = $this->queries[$query]['numrows'];
		}
 
		for ($ctr=$start;$ctr<=$end;$ctr++) {
			$return[$ctr] = $this->getassoc($ctr, $query);
		}
 
		return $return;
 
	}
 
?>

Con estas funciones ya tenemos solucionados nuestros requerimientos de acceso a datos, ahora vamos con las funciones que nos permitirán manipularlos:

  • insert() nos facilitará la tarea de insertar nuevos datos en una tabla.
  • Con update() podremos modificar registros.
  • delete() será la función que utilizaremos para eliminar registros.

Seguir leyendo...

Por Jose. Han entrado 5984 veces. Hay 2 comentarios       
mié, 26 nov 2008 - Archivado en PHP, Tutoriales y Bases de datos

Hola de nuevo, hoy vamos a comenzar una clase de artículos en los que crearemos una librería de abstracción de bases de datos ¿que qué es eso? pues vamos a verlo.

De entrada, una capa de abstracción de bases de datos, nos permitirá cambiar el motor de la base de datos, de forma fácil y sencilla, de forma que la aplicación continúe funcionando de forma normal y sin efectuar ningún cambio en ella. Esto significa, que también podremos desarrollar aplicaciones que trabajen contra cualquier motor de bases de datos, sin cambiar nuestra sintaxis ni las funciones a utilizar.

Además, podemos implementar métodos para realizar selects, inserts, updates y deletes, entre otros, con lo que nuestro código podría quedar limpio de sentencias SQL (personalmente, es una práctica que prefiero no usar; a mí me es muy útil leer mis sentencias SQL de forma literal, pero para gustos... colores)

Bueno, pongámonos manos a la obra, lo primero que debemos hacer es crear la clase y establecer una conexión con la base de datos:

class MyDBLayer {
 
	private $db = '';				// Base de datos.
	private $host = 'localhost';	// Servidor.
	private $user = 'user';			// Usuario.
	private $password = 'password';	// Password.
 
	public $handler = null;			// Handler de la conexión.
 
	private $engine = 'mysql';		// Motor de base de datos.
	private $autoconnect = false;	// Indica si debemos autoconectar al crear el objeto.
	private $connected = false;		// Indica si estamos conectados.
	private $queries = array();		// Contiene los queries ejecutados.
 
	public function __construct( $db, $host, $user = '', $password = '', $connect = false, $engine = 'mysql' ) {
 
		//
		// Inicializamos variables
		//
		$this->db = $db;
		$this->host = $host;
		if (strpos($host,'@') !== false) {
			$tmp = explode( '@', $host );
			$this->host = $tmp[0];
			$this->user = $tmp[1];
			if (count($tmp) > 2) {
				$this->password = $tmp[2];
			}
			if (count($tmp) > 3) {
				$this->autoconnect = (in_array($tmp[4],array('yes','true','1') ? true : false;
			}
		} else if (is_array($host)) {
			$this->host = $host[0];
			$this->user = $host[1];
			$this->password = $host[2];
			if (count($host) > 3) {
				$this->autoconnect = (in_array($host[4],array('yes','true','1') ? true : false;
			}
		} else {
			$this->user = $user;
			$this->password = $password;
			$this->autoconnect = $connect;
		}
 
		if ($engine != 'mysql') $this->engine = $engine;
 
		if ($this->autoconnect) {	// Si debemos conectar al inicio lo hacemos...
			$this->connect();
		}
 
	}
 
	public function connect() {
 
		if ($this->engine == 'mysql') {
			$this->handler = @mysql_connect( $this->host, $this->user, $this->password );
		}
 
		if ($this->handler) {
			if (!mysql_select_db($this->db, $this->handler)) {
				$this->errors[] = 'Error de selección de base de datos: ' . mysql_error();
				return false;
			}
			$this->connected = true;
			return true;
		} else {
			$this->errors[] = 'Error de conexión con el servidor: ' . mysql_error();
			return false;
		}
 
	}
  

Bien, como vereis, el constructor lo hemos montado de forma que sea capaz de recibir los parámetros de distintas formas: le podemos pasar los parámetros de forma tradicional o podemos agrupar los parámetros de conexión en el parámetro $host, ya sea como una cadena con el caracter "@" como separador (ej: host@usuario@password[@autoconectar[@motor]]) o como un array numérico, mantiendo el mismo orden de parámetros (host, usuario, password, autoconectar y motor) y una vez ha establecido las propiedades base de la clase, es capaz de realizar la conexión llamando a la función "connect", si se lo especificamos, claro.

En la función "connect", realizamos la conexión al servidor y seleccionamos la base de datos, comprobando el motor seleccionado, lo que nos da la posibilidad de extender nuestra clase para que sea capaz de trabajar sobre cualquier motor, ya sea mysql, postgre, mssql, odbc, etc...

Y para acabar con la primera entrega de esta serie, vamos a darle un poco de funcionalidad a la clase, implementando los métodos necesarios para extraer datos:

public function query( $sql, $query = 'main' ) {
 
	if (!$this->connected) {		// Comprobamos si estamos conectados, si no lo hacemos.
		$this->connect();
	}
 
	if ($this->connected) {
 
		if ($this->engine == 'mysql') {
 
			//
			// Realizamos el query y almacenamos el resultado en el array "queries"
			//
			$this->queries[$query]['query'] = $sql;
			$this->queries[$query]['result'] = mysql_query( $this->queries[$query]['query'], $this->db ) || $this->SendError();
 
			if ($this->queries[$query]['result']) {
 
				//
				// Si el query ha tenido éxito, extraemos información del resultado.
				//
				$this->queries[$query]['recno'] = 0;
 
				if ((substr( strtoupper(trim($this->queries[$query]['query'])), 0, 6 ) == "SELECT") || (substr( strtoupper(trim($this->queries[$query]['query'])), 0, 7 ) == "EXPLAIN") || (substr( strtoupper(trim($this->queries[$query]['query'])), 0, 4 ) == "SHOW")) {
 
					$this->queries[$index]['numfields'] = mysql_num_fields( $this->queries[$index]['result'] );
					$this->queries[$index]['numrows']   = mysql_num_rows( $this->queries[$index]['result'] );
 
					for ($ct=0;$ct<$this->queries[$index]['numfields'];$ct++) {
						$this->queries[$index]['fields'][$ct]['name'] = mysql_field_name( $this->result, $ct );
						$this->queries[$index]['fields'][$ct]['type'] = mysql_field_type( $this->result, $ct );
						$this->queries[$index]['fields'][$ct]['size'] = mysql_field_len( $this->result, $ct );
					}
 
				}
 
			}
 
			return $this->queries[$index]['result'];
 
		}
 
	}
 
}
 
public function get( $row, $col, $query = 'main' ) {
 
	$return = false;
 
	if ($this->engine == "mysql") {
		$return = mysql_result( $this->queries[$query]['result'], $row, $col );
	}
 
	return $return;
 
}

Como se puede observar, el método "query" realiza una consulta sobre la base de datos y la almacena en un array con un índice definido por nosotros, o usando uno por defecto. Además, si la consulta debe devolver resultados (es decir, no es un UPDATE ni un INSERT) extrae y almacena información sobre el resultado, como número de registros o número de campos, así como el nombre, tipo y tamaño de los mismos.

El método "get", símplemente extrae y devuelve un valor del resultado de cualquiera de las consultas realizadas o false si hay algún error.

Y aquí terminamos la entrega de hoy, en las siguientes iremos implementando nuevos métodos de acceso a datos y agregaremos nuevos motores de bases de datos a nuestra clase.

Por Jose. Han entrado 9341 veces. Hay 5 comentarios       
vie, 07 nov 2008 - Archivado en (X)HTML, CSS, Diseño y Tutoriales

Uno de los elementos clave en una página web es el menú de navegación. Hay muchos factores que influyen en el diseño de un menú, pero ante todo:

  • Debe ser bien visible a primera vista.
  • Debe ser claro.
  • Ha de estar bien formado y ser accesible.
  • Debe cumplir los estándares del W3C.

Bien, para construir nuestro menú, primero crearemos la estructura, usando una lista desordenada (<ul>). Muchos de vosotros direis ¿porqué todo el mundo se empeña en que tengo que utilizar listas para construir un menu? La respuesta es bien sencilla: el XHTML es un lenguaje diseñado para estructurar datos, y un menú no deja de ser una lista de enlaces, por lo que lo más natural sería representarlo como lo que es, una lista.

Como ejemplo real, cogeré una web que desarrollé hace poco, www.almirantelibros.com. Lo primero, como decíamos es crear la estructura del menú:

  1. <ul id="lmenu">
  2. <li id="lmenu1"><span class="selected">Inicio</span></li>
  3. <li id="lmenu2"><a href="http://www.almirantelibros.com/almirante/">Quienes somos</a></li>
  4. <li id="lmenu3"><a href="http://www.almirantelibros.com/coleccion/">La colecci&oacute;n</a></li>
  5. <li id="lmenu4"><a href="http://www.almirantelibros.com/blog/">El Blog</a></li>
  6. <li id="lmenu5"><a href="http://www.almirantelibros.com/noticias/">Noticias</a></li>
  7. <li id="lmenu6"><a href="http://www.almirantelibros.com/contacto/">Contacto</a></li>
  8. </ul>

Esto nos daría como resultado algo parecido a lo siguiente:

Ya tenemos un menú que, aunque completamente funcional, necesita que le demos forma, lo cual haremos a continuación utilizando CSS y una imagen que habremos preparado previamente. Lo primero es preparar la lista para mostrarla de forma horizontal:

  1. ul#lmenu {
  2. padding: 0;
  3. margin: 0;
  4. }
  5.  
  6. ul#lmenu li {
  7. list-style-type: none; /* Eliminamos el punto de los elementos de la lista */
  8. float: left; /* Con esta línea ya tenemos el menú en horizontal */
  9. height: 38px; /* Establecemos el alto, para adaptarlo a la imagen */
  10. }

Una vez tenemos el menú en horizontal, cargaremos la imagen del menú, y digo "la imagen" porque utilizaremos una técnica llamada "CSS Sprites" que ya revisaremos a fondo, y que consiste en cargar una sola imagen como si fuera un "mapa" con todas las imágenes que vamos a utilizar, en este caso en el menú:

 

 Y ahora vamos con el código CSS:

  1. ul#lmenu li a,
  2. ul#lmenu li span {
  3. display: block; /* Convertimos los enlaces y el "span" en bloques */
  4. background-image: url(/images/menu.jpg); /* Les asignamos a todos la misma imagen, así sólo la cargamos una vez */
  5. background-repeat: no-repeat;
  6. text-indent: -24000px; /* Escondemos el texto, indentándolo fuera de la página hacia la izquierda */
  7. }
  8.  
  9. /* A continuación, con "background-position" y "width", posicionamos la imagen de fondo para cada elemento del menú */
  10.  
  11. li#lmenu1 a {
  12. background-position: left 1px;
  13. width: 72px;
  14. }
  15.  
  16. li#lmenu1 a:hover {
  17. background-position: left -37px;
  18. }
  19.  
  20. li#lmenu1 span {
  21. background-position: left -75px;
  22. width: 72px;
  23. }
  24.  
  25. li#lmenu2 a {
  26. background-position: -100px 1px;
  27. width: 166px;
  28. }
  29.  
  30. li#lmenu2 a:hover {
  31. background-position: -100px -37px
  32. }
  33.  
  34. li#lmenu2 span {
  35. background-position: -100px -75px;
  36. width: 166px;
  37. }
  38.  
  39. li#lmenu3 a {
  40. background-position: -292px 1px;
  41. width: 105px;
  42. }
  43.  
  44. li#lmenu3 a:hover {
  45. background-position: -292px -37px
  46. }
  47.  
  48. li#lmenu3 span {
  49. background-position: -292px -75px;
  50. width: 105px;
  51. }
  52.  
  53. li#lmenu4 a {
  54. background-position: -423px 1px;
  55. width: 78px;
  56. }
  57.  
  58. li#lmenu4 a:hover {
  59. background-position: -423px -37px
  60. }
  61.  
  62. li#lmenu4 span {
  63. background-position: -423px -75px;
  64. width: 78px;
  65. }
  66.  
  67. li#lmenu5 a {
  68. background-position: -528px 1px;
  69. width: 92px;
  70. }
  71.  
  72. li#lmenu5 a:hover {
  73. background-position: -528px -37px
  74. }
  75.  
  76. li#lmenu5 span {
  77. background-position: -528px -75px;
  78. width: 92px;
  79. }
  80.  
  81. li#lmenu6 a {
  82. background-position: -645px 1px;
  83. width: 105px;
  84. }
  85.  
  86. li#lmenu6 a:hover {
  87. background-position: -645px -37px
  88. }
  89.  
  90. li#lmenu6 span {
  91. background-position: -645px -75px;
  92. width: 105px;
  93. }

Y con esto, ya tenemos terminado el menú, el ejemplo lo teneis en: www.almirantelibros.com

Por Jose. Han entrado 6173 veces.  Comentarios
mié, 05 nov 2008 - Archivado en PHP, Javascript y Tutoriales

Sigamos con el ejercicio que empezamos la semana pasada, hoy vamos a retocar el ejemplo para que nuestro script no nos muestre las etiquetas ya seleccionadas. Para ello, modificaremos las opciones del plugin "autocomplete" para que envíe el contenido ya seleccionado a nuestro script PHP, quedando así nuestro código en javascript:

  1. <script type="text/javascript"><!--
  2. $().ready(function(){
  3. $("#tags").autocomplete('gettags.php', { multiple: true, cacheLength: 0, autoFill: true, selectFirst: true, extraParams: { t: function() { return $("#tags").val() } }, formatItem: formatItem, formatResult: formatResult } );
  4. });
  5. function formatItem(row) {
  6. return row[0] + " (" + row[1] + ")";
  7. }
  8. function formatResult(row) {
  9. return row[0];
  10. }
  11. --></script>

Como vereis, hemos añadido un nuevo parámetro en la llamada a la función autocomplete:

extraParams: { t: function() { return $("#tags").val() } }

Con esto, hacemos que el plugin entregue el valor del campo "#tags" en el parámetro "t" en cada llamada (para que esto funcione, debemos también desactivar la caché con el parámetro: cacheLength: 0) el cual utilizaremos para crear un filtro en nuestra sentencia SQL:

  1. <?php
  2.  
  3. $db = mysql_connect( 'localhost', 'user', 'password' );
  4. mysql_select_db( 'my_db', $db );
  5. if ($_GET['t'] > '') {
  6. $filter = ' AND tag NOT IN ("' . str_replace( ', ', '", "', $_GET['t'] ) . '")';
  7. } else {
  8. $filter = '';
  9. }
  10. $result = mysql_query( 'SELECT tag, COUNT(tag) FROM blogs_arts_tags WHERE tag LIKE "' . $_GET['q'] . '%"' . $filter . ' GROUP BY tag ORDER BY tag', $db );
  11. while ($row = mysql_fetch_row( $result )) {
  12. echo $row[0], "|", $row[1], "\n";
  13. }
  14.  
  15. ?>

Y ya lo tenemos, podéis volver a pasar por la página de demostración para comprobar su funcionamiento, espero que lo disfrutéis ;)

Ver demostración.

Por Jose. Han entrado 5399 veces. Hay 1 comentario       
mar, 28 oct 2008 - Archivado en Javascript y Tutoriales

En el primer artículo técnico de codeando.net vamos a explicar como hemos implementado en el motor de este blog un sistema de "tags" o "etiquetas", utilizando un "autocomplete" (en este caso un plugin para jQuery).

El primer paso es incluir los ficheros necesarios para la librería y el plugin:

  1. <link rel="stylesheet" type="text/css" href="/javascript/jquery/plugins/jquery-autocomplete/jquery.autocomplete.css" />
  2. <script type="text/javascript" src="/javascript/jquery.js"></script>
  3. <script type="text/javascript" src="/javascript/jquery/plugins/jquery-autocomplete/lib/jquery.bgiframe.min.js"></script>
  4. <script type="text/javascript" src="/javascript/jquery/plugins/jquery-autocomplete/jquery.autocomplete.pack.js"></script>

Ahora inicializaremos el plugin para el campo deseado:

  1. $().ready(function(){
  2. $("#tags").autocomplete('gettags.php', { multiple: true, autoFill: true, selectFirst: true, formatItem: formatItem, formatResult: formatResult } );
  3. });
  4. function formatItem(row) {
  5. return row[0] + " (" + row[1] + ")";
  6. }
  7. function formatResult(row) {
  8. return row[0];
  9. }

Pasemos ahora a explicar las opciones que definimos en el segundo parámetro que pasamos a la función autocomplete:

  • multiple: true
    Permite que la función sea llamada múltiples veces en un mismo campo, utilizando un separador, que por defecto es ", ".
  • autoFill: true
    Completa la palabra con texto resaltado, de manera que si pulsamos intro o tabulador se inserta el tag automáticamente.
  • selectFirst: true
    Automáticamente selecciona el primer elemento de la lista al pulsar intro o tabulador, aunque no haya ninguno seleccionado.
  • formatItem: formatItem
    Llama a la función especificada (en este caso "formatItem") en la que se puede manipular el texto visible en el desplegable del autoselect.
  • formatResult: formatResult
    Como el anterior, pero aplicable al valor de la opción.

Con esto queda hecha la parte del cliente, ahora pasemos al lado del servidor: el fichero gettags.php. Este fichero está recibiendo los caracteres tecleados por el usuario en el parámetro GET "q", que utilizaremos para realizar una consulta a la base de datos y devolver el resultado:

  1. $db = mysql_connect( 'localhost', 'user', 'password' );
  2. mysql_select_db( 'my_db', $db );
  3. $result = mysql_query( 'SELECT tag, COUNT(tag) FROM tags WHERE tag LIKE "' . $_GET['q'] . '%" GROUP BY tag ORDER BY tag', $db );
  4. while ($row = mysql_fetch_row( $result )) {
  5. echo $row[0], "|", $row[1], "\n";
  6. }

Y ya sólo queda mostraros el resultado final:

Ver demostración

Por Jose. Han entrado 11617 veces. Hay 6 comentarios