Examen transversal Aplicaciones para Internet DuocUC

Hoy fue el Examen transversal Aplicaciones para Internet en DuocUC Concepción, son transversales porque se aplica exactamente el mismo a todas las sedes de Chile. Realmente fue una burla a nuestro conocimiento ¬¬ supuestamente es para medir con la misma regla a todos los estudiantes, debo suponer que la regla fue muy baja para todos o realmente en las demás sedes (Santiago particularmente porque ahí lo crearon) no enseñan tanto como en la de concepción.
En fin, aquí dejo mi solución al examen, que realmente al ver lo que pedían no me esforcé en hacer algo que resaltara, la solución y ya.

Aquí dejo un pequeño demo, y los archivos fuente.

No dejare el código porque es solo una clase

En si el trabajo constaba de validar un formulario con javascript, hacer una clase para validar en php (la que realmente nunca se uso a menos que el cliente tuviese el JS desactivado en el navegador, pero yo igual la hice por accesibilidad) y manejo de sesiones (lo que ya he explicado en una publicación anterior), para las validaciones ocupe el sistema de clases de mootools para hacer todo una vez, de paso me quedo algo útil para algún proyectito que salga.

Espero a alguien le sea de utilidad… y… Saludos :)

Certamen #2 , aplicacion para Internet DuocUC

Afortunadamente me save de rendir este certamen, pero fui a ver como mis compañeros sucumbian ante el horror xD, de todas formas lo hice sde puro ocio y aqui lo dejo, amen.

Para conectarme a la BD

  1. <?php
  2. class MySQL {  
  3.   public $dbHost;
  4.   public $dbName;
  5.   public $usuario;
  6.   public $usuarioPass;
  7.   public $conexion;
  8.   function MySQL($dbHost,$dbName,$usuario,$usuarioPass){    
  9.     $this->dbHost = $dbHost;
  10.     $this->dbName = $dbName;
  11.     $this->usuario = $usuario;
  12.     $this->usuarioPass = $usuarioPass;
  13.   }
  14.   public function On(){
  15.     if(!$this->conexion){
  16.       $this->conexion = mysql_connect($this->dbHost, $this->usuario, $this->usuarioPass);
  17.       if(!$this->conexion){
  18.         throw new Exception('No se pudo conectar a la base de datos');
  19.       }
  20.       if(function_exists('mysql_set_charset')){
  21.         mysql_set_charset("utf8", $this->conexion);
  22.       }
  23.       if(!mysql_select_db($this->dbName)){
  24.         throw new Exception('No se pudo seleccionar la base de datos, problemas de propietario o no existe');
  25.       }
  26.     }
  27.   }  
  28.   public function Off(){
  29.     if($this->conexion){
  30.       if(!@mysql_close($this->conexion)){
  31.         throw new Exception('No se pudo desconectar');
  32.       }
  33.     }
  34.   }    
  35.   public function Begin(){
  36.     return @mysql_query('BEGIN', $this->conexion);
  37.   }    
  38.   public function End($Bool=true){
  39.     if($Bool==true){
  40.       return @mysql_query('COMMIT', $this->conexion);
  41.     }else{
  42.       return @mysql_query('ROLLBACK', $this->conexion);
  43.     }
  44.   }
  45.   public function Exe($Q){
  46.         $res = @mysql_query($Q, $this->conexion);
  47.         if($res){
  48.             return $res;
  49.         }else{
  50.             throw new Exception('Error MySQL :');
  51.         }
  52.   }
  53.   public function ExeGet($Q){
  54.     return $this->ResultToArray($this->Exe($Q));
  55.   }
  56.   public function ResultToArray($Result){
  57.     $Salida = array();
  58.     while( $unRegistro = @mysql_fetch_assoc($Result) ) {
  59.       $Salida[] = $unRegistro;
  60.     }
  61.     return $Salida;
  62.   }  
  63.   public function UltimoAutoincrement(){
  64.     $res = @mysql_insert_id($this->conexion);
  65.     if($res){
  66.        return $res;
  67.     }else{
  68.         throw new Exception('Error MySQL : No se puede recuperar el registro');
  69.     }
  70.   }
  71.   public function Afectadas(){
  72.     return @mysql_affected_rows($this->conexion);
  73.   }
  74. }
  75. ?>

Para validar Profesores

  1. <?php
  2. class Profesor {  
  3.   public $id;
  4.   public $nombre;
  5.   public $horas;
  6.   public $valorHoras;  
  7.   function Profesor($id,$nombre,$horas,$valorHoras){    
  8.     $this->setId($id);
  9.     $this->setNombre($nombre);
  10.     $this->setHoras($horas);
  11.     $this->setValorHoras($valorHoras);
  12.   }  
  13.   public function setId($v){
  14.     if(is_int($v)){
  15.       $this->id = intval($v);
  16.     }else{
  17.       throw new Exception("El ID debe ser un numero");
  18.     }
  19.   }
  20.   public function setNombre($v){
  21.     $v = trim($v);
  22.     if($v==''){
  23.       throw new Exception("El nombre no puede estar vacio");      
  24.     }else{
  25.       $this->nombre = $v;
  26.     }
  27.   }
  28.   public function setHoras($v){
  29.     if(is_int($v)){
  30.       $v = intval($v);
  31.       if($v>0){
  32.         $this->horas = $v;
  33.       }else{
  34.         throw new Exception("Las horas no pueden ser negativas");
  35.       }
  36.     }else{
  37.       throw new Exception("Las horas deben ser numericas");
  38.     }
  39.   }
  40.   public function setValorHoras($v){
  41.     if(is_int($v)){
  42.       $v = intval($v);
  43.       if($v>0){
  44.         $this->valorHoras = $v;
  45.       }else{
  46.         throw new Exception("El valor horas no pueden ser negativas");
  47.       }
  48.     }else{
  49.       throw new Exception("El valor horas debe ser numerico");
  50.     }
  51.   }  
  52.   public function getId(){
  53.     return $this->id;  
  54.   }
  55.   public function getNonmbre(){
  56.     return $this->nombre;
  57.   }
  58.   public function getHoras(){
  59.     return $this->horas;
  60.   }
  61.   public function getValorHoras(){
  62.     return $this->valorHoras;
  63.   }
  64. }
  65. ?>

Para controlar informacion de Profesores

  1. <?php
  2. class ControlProfesor {  
  3.   public $conexion;
  4.   function ControlProfesor($SQL){    
  5.     $this->conexion = $SQL;
  6.     $this->conexion->On();
  7.   }
  8.   public function add($nombre,$horas,$valorHoras){
  9.     $P = new Profesor($this->getNextID(),$nombre,$horas,$valorHoras);
  10.     try{
  11.       $this->conexion->Exe("
  12.        insert into profesor (pr_id,pr_nombre,pr_horas,pr_valorhora)
  13.        values (".$P->getId().",'".$P->getNombre()."',".$P->getHoras().",".$P->getValorHora().")
  14.      ");
  15.       return $P;
  16.     }catch(Exception $e){
  17.       throw new Exception("No se pudo insertar en la la BD : ".$e->getMessage());
  18.     }
  19.   }
  20.   public function del($id){
  21.     $id = intval(id);
  22.     // get() Lanzara exception si no existe el que quiero eliminar
  23.     $this->get($P->getId());
  24.     try{
  25.       $this->conexion->Exe("delete from profesor where pr_id=".$id);
  26.     }catch(Exception $e){
  27.       throw new Exception("No se pudo eliminar en la la BD : ".$e->getMessage());
  28.     }
  29.   }
  30.   public function upd($id,$nombre,$horas,$valorHoras){
  31.     $P = new Profesor($id,$nombre,$horas,$valorHoras);
  32.     // get() Lanzara exception si no existe el que quiero actualizar
  33.     $this->get($P->getId());
  34.     try{
  35.       $this->conexion->Exe("
  36.        update profesor set
  37.          pr_id=".$P->getId().",
  38.          pr_nombre='".$P->getNombre()."',
  39.          pr_horas=".$P->getHoras().",
  40.          pr_valorhora=".$P->getValorHora()."
  41.      ");
  42.       return $P;
  43.     }catch(Exception $e){
  44.       throw new Exception("No se pudo actualizar en la la BD : ".$e->getMessage());
  45.     }
  46.   }
  47.   public function get($id){
  48.     $r = $this->conexion->ExeGet("select * from profesor where pr_id=".intval($id)." limit 1");
  49.     if(isset($r[0])){
  50.       return $r[0];
  51.     }else{
  52.       throw new Exception("El profesor no existe");
  53.     }
  54.   }
  55.   public function getTodos(){
  56.     return $this->conexion->ExeGet("select * from profesor");
  57.   }
  58.   public function getPorSueldo($min,$max){
  59.     if(!is_int($min) or !is_int($max)){
  60.       throw new Exception("El rango debe ser numerico, valores invalidos");
  61.     }
  62.     $min  = intval($min);
  63.     $max  = intval($max);
  64.     if($min<=$max){
  65.       return $this->conexion->ExeGet("
  66.        select *
  67.        from profesor
  68.        where
  69.          ".$min."<=(pr_horas*pr_valorhora) and
  70.          ".$max.">=(pr_horas*pr_valorhora)
  71.      ");
  72.     }else{
  73.       throw new Exception("El minimo debe ser menor o igual al maximo");
  74.     }
  75.   }
  76.   public function getNextID(){
  77.     $r = $this->conexion->ExeGet("select pr_id from profesor order by desc limit 1");
  78.     if(isset($r[0])){
  79.       return intval($r[0]['pr_id'])+1;
  80.     }else{
  81.       return 0;
  82.     }
  83.   }
  84. }
  85. ?>

Interfaz o “Pagina” mega fea

  1. <?php
  2. session_start();
  3. session_register('sesion');
  4. if(!isset($_SESSION['sesion']['login']) or isset($_GET['salir'])){
  5.   $_SESSION['sesion']['login']=false;
  6. }
  7. if(isset($_POST['entrar'])){
  8.   if($_POST['usr']=='yo' and $_POST['pas']=='yo'){
  9.     $_SESSION['sesion']['login']=true;
  10.   }
  11. }
  12. if($_SESSION['sesion']['login']==true){
  13.   require('clases/MySQL.php');
  14.   require('clases/Profesor.php');
  15.   require('controles/ControlProfesor.php');
  16.   ?>
  17.   <html>
  18.   <head>
  19.     <title>Certamen 2</title>
  20.     <?php
  21.     try{
  22.       $conexion = new MySQL('localhost','C2','root','');
  23.       $control = new ControlProfesor($conexion);    
  24.       if(isset($_GET['eliminar'])){
  25.         $control->del($_GET['eliminar']);
  26.       }
  27.       if(isset($_GET['upd'])){
  28.         $control->upd($_POST['id'], $_POST['nombre'], $_POST['horas'], $_POST['valor_horas']);
  29.       }
  30.     }catch(Exception $e){
  31.       echo "<script type=\"text/javascript\">alert('".$e->getMessage()."');</script>";
  32.     }
  33.     ?>  
  34.   </head>
  35.   <body>
  36.     <a href="index.php?salir=salir">Salir del Sistema</a><br>
  37.     <?php
  38.     if(isset($_GET['editar'])){
  39.       try{
  40.         $P = $control->get($_GET['editar']);
  41.         ?>
  42.         Editar      
  43.         <form action="index.php" method="post">
  44.           <input type="hidden" name="id" value="<?php echo $P['pr_id']; ?>" />
  45.           <label>
  46.             Nombre: <input type="text" name="nombre" value="<?php echo $P['pr_nombre']; ?>" />
  47.           </label>
  48.           <label>
  49.             Horas: <input type="text" name="horas" value="<?php echo $P['pr_horas']; ?>" />
  50.           </label>
  51.           <label>
  52.             Valor Horas: <input type="text" name="valor_horas" value="<?php echo $P['pr_valorhora']; ?>" />
  53.           </label>
  54.           <input type="submit" name="upd" value="Guardar" />
  55.         </form>
  56.         <br />
  57.         <br />
  58.         <br />
  59.         <?php
  60.       }catch(Exception $e){
  61.         echo "<script type=\"text/javascript\">alert('".$e->getMessage()."');</script>";
  62.       }
  63.     }
  64.     ?>
  65.     Ingresar
  66.     <form action="index.php" method="post">
  67.       <label>
  68.         Nombre: <input type="text" name="nombre" />
  69.       </label>
  70.       <label>
  71.         Horas: <input type="text" name="horas" />
  72.       </label>
  73.       <label>
  74.         Valor Hora: <input type="text" name="valor_horas" />
  75.       </label>
  76.       <input type="submit" name="add" value="Agregar" />
  77.     </form>
  78.    
  79.     <br />
  80.     <br />
  81.     <br />
  82.     Buscar Por sueldos
  83.     <form action="index.php" method="post">
  84.       <label>
  85.         Minimo: <input type="text" name="min" />
  86.       </label>
  87.       <label>
  88.         Maximo: <input type="text" name="max" />
  89.       </label>
  90.       <input type="submit" name="buscarPorRango" value="Buscar" />
  91.     </form>
  92.    
  93.     <br />
  94.     <br />
  95.     <br />
  96.     Lista completa de Profesores <?php if(isset($_POST['buscarPorRango'])){?><a href="index.php">Ver lista completa</a><?php } ?>
  97.     <table>
  98.       <thead>
  99.         <tr>
  100.           <th>ID</th>
  101.           <th>Nombre</th>
  102.           <th>Horas</th>
  103.           <th>Valor Hora</th>
  104.           <th>&nbsp;</th>
  105.         </tr>
  106.       </thead>
  107.       <tbody>
  108.         <?php
  109.         if(!isset($_POST['buscarPorRango'])){
  110.           $r = $control->getTodos();
  111.         }else{
  112.           try{
  113.             $r = $control->getPorSueldo($_POST['min'], $_POST['max']);
  114.           }catch(Exception $e){
  115.             echo "<script type=\"text/javascript\">alert('".$e->getMessage()."');</script>";
  116.             $r = $control->getTodos();
  117.           }
  118.         }
  119.        
  120.         foreach($r as $P){
  121.         ?>
  122.         <tr>
  123.           <td><?php echo $P['pr_id']; ?></td>
  124.           <td><?php echo $P['pr_nombre']; ?>Nombre</td>
  125.           <td><?php echo $P['pr_horas']; ?>Horas</td>
  126.           <td><?php echo $P['pr_valorhora']; ?>Valor Hora</td>
  127.           <td><a href="index.php?editar=<?php echo $P['pr_id']; ?>">Editar</a><a href="index.php?eliminar=<?php echo $P['pr_id']; ?>">Eliminar</a></td>
  128.         </tr>
  129.         <?php } ?>
  130.       </tbody>
  131.     </table>
  132.  
  133.   </body>
  134.   </html>
  135. <?php }else{ # fin de IF PARA SESION ?>
  136. Entrar
  137. <form action="index.php" method="post">
  138.   <label>
  139.     Usuario: <input type="text" name="usr" />
  140.   </label>
  141.   <label>
  142.     Pass: <input type="text" name="pas" />
  143.   </label>
  144.   <input type="submit" name="entrar" value="Entrar" />
  145. </form>
  146. <?php } ?>

Buenas Prácticas en MySQL

Aunque sepamos mucho sobre un lenguaje o cierta tecnología, siempre existen pequeñas cosas que aprender y que ayudan mucho al rendimiento, sea lo que sea.

Leyendo uno de los tantos Blogs que sigo me encontré con un muy interesante articulo de cómo mejorar mucho el rendimiento de nuestras bases de datos MySQL con pequeños cambios que la mayoria de las veces pasamos por alto, en especial al momento de pasar a código nuestos modelos.

Espero sepan un poco de ingles porque esta muy bueno :)

Link en NetTutsPlus.com: Visitar Publicación, Buenas practicas MySQL

Manejo de Arreglos o Vectores en Javascript

Una parte fundamentar para crear cualquier programa es saber manejar Arreglos, Vectores o Arrays.

En Javascript no es diferente, y muchas veces nos dedicamos a hacer tareas que el lenguaje ya tenía consideradas y pueden ser solucionadas con una simple función.

Aquí dejare unas cuantas funciones que sirven bastante para ahorrar tiempo y sacan de mas de un apuro.
He comentado el código, pero a grandes rasgos lo que hace es:

  1. Ordenar Array por criterios comunes o personalizados.
  2. Revertir un Array o Vector.
  3. Unir el contenido de un vector.
  4. Saber si algún elemento de un vector cumple cierta condición.

Por supuesto hay mas métodos y dejo estos aquí con el solo propósito de que sepan que existen y no se quemen la cabeza pensando cosas que ya están ahí :) , por supuesto ya me paso y aprendí.

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4.   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5.   <title>Manejo de Arreglos o Vectores en javascript :: www.elsoma.net</title>
  6.   <script type="text/javascript">
  7.  
  8.     var vector = [
  9.       'Windows XP',
  10.       'Windows 7',
  11.       'Ubuntu',
  12.       'Mac OS X',
  13.       'Redhat',
  14.       'Mac OS Leopard'
  15.     ];
  16.    
  17.     //> Funcion para oredenar Vector
  18.       //> Ordenar por criterio de javascript, menor mayor o literal a-z
  19.       vector.sort();
  20.      
  21.       //> Ordenar personalizado, en este caso ordeno por largo de string
  22.       //> el ultimo valor sera el mas largo y el primero el mas corto como dice la condicion
  23.       vector.sort(function(ultimoValor,primerValor){
  24.         return ultimoValor.length>primerValor.length;
  25.       });
  26.      
  27.     //> Funcion para revertir un Vector o Array
  28.       //> Retorna el array en posicion inversa
  29.       vector.reverse();
  30.    
  31.     //> Concatenar todos los valores
  32.       //> Une todos los valores del array separados por el/los caracter que espesifiques
  33.       vector.join('*');
  34.    
  35.     //> Saber si algun elemento cumple con sierta condicion
  36.       //> En este caso, saber si hay algun elemento con mas de 100 caracteres
  37.       vector.some(function(elemento){
  38.         return elemento.length>100;
  39.       });
  40.   </script>
  41. </head>
  42. <body>
  43. </body>
  44. </html>

El problema del juego caracteres en PHP y MySQL

utf8

Uno de los problemas más comunes que uno conoce al entrar al desarrollo web es relacionado a los caracteres que componen el sitio y su contenido.

Es habitual que por ejemplo, un usuario ingrese caracteres considerados “poco comunes” según los gringos, y desde PHP lo tomemos e insertemos en MySQL, asumiendo que ese valor es la pabla “araña” lo que sucederá es que en MySQL se registrará esto : “araÁça”, algo muy similar o incluso peor.

El problema radica en la configuración de caracteres con que trabaja PHP y MySQL, creo que esto se puede coordinar para que ambos tengan el mismo juego de caracteres, pero muchas veces ni siquiera tenemos acceso a ese nivel de configuración en el servidor, por lo que mi solución ha sido otra (si alguien conoce otra por Dios que me la cuente :) ).

Entrando en materia, una solución muy conocida es transformar los caracteres “extraños” de nuestro texto a formas que sean aceptadas por MySQL sin tener mayor configuración. Básicamente lo que debemos hacer es pasar todo a Entidades HTML.

¿Qué son la Entidades HTML?

La forma que se ha definido como estándar para mostrar nuestros tan lindos acentos y eñes es definiendo un código que representa a cierto carácter que es llamado “Entidad HTML”.

Es decir que existe una tabla con todas las letras y símbolos poco comunes con su respectivo código que al escribirlo dentro de un documento HTML se mostrará al visitante como lo que simboliza, es decir “la letra extraña”.

Sin ir más allá puedo dar algunos ejemplos muy utilizados como:

Codigo Simbolo
Á &Aacute;
É &Eacute;
Í &Iacute;
Ó &Oacute;
Ú &Uacute;

Viendo lo anterior podemos ver que el código es de la forma “&”+código+”;”

Naturalmente nadie recordará semejante tabla, considerando que son TODOS los caracteres es imposible, yo solo conozco de memoria las vocales y la ñ, que es suficiente para escribir documentos estáticos (paginas HTML, no PHP, ni ASP).

Una solución viable

Como siempre PHP y otros lenguajes de servidor tienen soporte para este problema, en el caso de PHP existen 2 funciones muy útiles en este aspecto, “htmlentities()” y “html_entity_decode()”
htmlentities()

Este función recibe como parámetro un String que puede o no tener caracteres extraños y convierte todo a entidades, o sea que deja listo el String para insertarlo en la base de datos.

htmlentities tiene más parámetros que no detallare, pienso que los que utilizo en el siguiente demo son la mejor solución, pero si no me creen pueden saber más aquí.

Como usar htmlentities:

  1. <?php
  2.   echo htmlentities('ñáéíúó',ENT_QUOTES,'UTF-8');
  3.   //> Genera como salida: &ntilde;&aacute;&eacute;&iacute;&uacute;&oacute;
  4. ?>
html_entity_decode()

Es simplemente la contraparte de htmlentities, convierte entidades a caracteres especiales, o sea ñ a ñ.

Esta función se usa más que nada para no hacer dos veces la conversión de carácter especial a entidad.

Como usar html_entity_decode :

  1. <?php
  2.   echo html_entity_decode('&ntilde;&aacute;&eacute;&iacute;&uacute;&oacute ;',ENT_QUOTES,'UTF-8');
  3.   //> Genera como salida: ñáéíúó;
  4. ?>

Con esto ya podemos asegurar que los caracteres que escriba el usuario serán realmente los que tengamos almacenados en la DB. Además al obtenerlos desde la misma podemos imprimirlos de inmediato en el documento HTML porque serán identificados por el navegador como lo que significan, es decir, si imprimimos ñ el navegador mostrara ñ.

Espero sea de utilidad
Saludos

Crear Simple Menu desplegable en Javascript

Recuerdo que hace tiempo busque como hacer un menú de este tipo, la idea era simple, agrupar enlaces dentro de otros elementos para no saturar la pagina con links, pero siempre habían soluciones demasiado rebuscadas, con efectos o con cosas innecesarias, que si bien muchas veces son útiles, no lo son tanto a la hora de aprender que se esta haciendo, por lo tanto el que haré yo sera very easy :)

Ahora un compañero me pidió le explicara como hacer un menú desplegable así que aquí lo dejo, realmente no hace nada de otro mundo, de hecho debe tener alguna que otra falla, pero como todos somos ingenieros el problema sera solucionado :)

Solución lógica:

Lo que haré será, Agrupar los enlaces en menús, identificar a uno de esos links como principal y hacer que al presionar un link, se designe su menú particular como “abierto”.

En código de lo antes dicho seria algo como esto: (Porfavor leer los comentarios en el javascript) y (Ver demo)

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4.   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5.   <title>Demostracion Submenu en Javascript</title>
  6.   <style type="text/css">
  7.     #menu {
  8.       position:absolute;
  9.     }
  10.       #menu div {
  11.         float:left;
  12.         padding:5px;
  13.       }
  14.         #menu div a {
  15.           display:none;
  16.           padding:4px;
  17.         }
  18.         #menu div.active a {
  19.           display:block;
  20.         }
  21.         #menu div a.principal {
  22.           display:block;
  23.           position:relative
  24.         }
  25.   </style>
  26.   <script type="text/javascript">
  27.   // Esta funcion se ejecuta cuando la pagina carga completamente
  28.   function inicia(){
  29.    
  30.     //> Obtengo los enlaces "principales" que defini con class="principal"
  31.     var enlaces = document.getElementsByClassName('principal');
  32.     //> Recorreo los enlaces <a>
  33.     for(var i=0; i<enlaces.length; i++){
  34.       //> Asigno el evento on click a cada enlace <a>
  35.       enlaces[i].onclick = function(e){
  36.         //> Obtengo los divs que estan dentro de <div id="menu"> y que tengan class="active"
  37.         var divs = document.getElementById('menu').getElementsByClassName('active');
  38.         //> recorro los div
  39.         for(var j=0; j<divs.length; j++){
  40.           //> A cada <div> le elimino la clase css
  41.           divs[j].className = '';
  42.         }
  43.         //> Al <div> que esta "cubriendo" mi enlace le asigno la clase 'active'
  44.         this.parentNode.className = 'active';
  45.       }
  46.     }
  47.    
  48.   }
  49.   </script>
  50. </head>
  51. <body onload="inicia();">
  52.   <div id="menu">
  53.     <div>
  54.       <a href="#" class="principal">Menu 1</a>
  55.       <a href="#">Sub Menu 1</a>
  56.       <a href="#">Sub Menu 2</a>
  57.       <a href="#">Sub Menu 3</a>
  58.     </div>
  59.     <div>
  60.       <a href="#" class="principal">Menu 2</a>
  61.       <a href="#">Sub Menu 1</a>
  62.       <a href="#">Sub Menu 2</a>
  63.       <a href="#">Sub Menu 3</a>
  64.     </div>
  65.     <div>
  66.       <a href="#" class="principal">Menu 3</a>
  67.       <a href="#">Sub Menu 1</a>
  68.       <a href="#">Sub Menu 2</a>
  69.       <a href="#">Sub Menu 3</a>
  70.     </div>
  71.   </div>
  72. </body>
  73. </html>

Programación Orientada a Objeto en Javascript, conceptos básicos.

poo-javascipt

Durante estos años Javascript ha tomado vital importancia en el desarrollo web y la interacción con el usuario y gracias a Ajax también con el servidor.

Muchos programadores que se inician en este tema no tienen idea o al menos no consideran la POO en Javascript, teniendo como concepto de este lenguaje nada más que funciones que sirven para validar datos, cuando realmente es posible crear un mini programa dentro del navegador sin tener que interactuar con el servidor, y digo “mini aplicación” por el hecho de que al ser un lenguaje del que se espera un respuesta rápida tiene algunas limitaciones, y una de las más importantes es la seguridad pero ese es otro tema.

Como ya deberías saber al momento de entrar a este post, la POO se basa en el concepto de Objeto y Método para trabajar más que en el desarrollo del código como tal. Así que lo debemos definir (por supuesto) es como crear un objeto y como trabar con él.

Debemos saber que Javascript es un lenguaje basado en definiciones, eso quiere decir que -todo- trabaja conforme a asignaciones a variables, una variable puede ser un Número, una Letra, un String, un Decimal, un Booleano, un Objeto o una Función, pero esto se entenderá más claramente un poco más adelante.

Consideraciones para no espantarnos.

  1. Javascript POO es extremadamente básico, pero expandible o sea que realmente se puede hacer casi cualquier cosa de un lenguaje POO avanzado como Java, pero no nativamente (o sea, a la mala).
  2. En Javascript no existe la Herencia (pero si a la mala)
  3. En Javascript no existen las funciones constructoras como tal
  4. Javascript al ser un lenguaje basado en definiciones se pueden asignar propiedades o métodos a la clase “al vuelo”, pero no es muy buena idea así que ni lo mencionaré :)

¿Cómo crear una Clase?

Hay varias formas, pero yo usare la más “universal” llamada “Función constructora” en donde simplemente de define una función normalmente y dentro de esta se definen propiedades y métodos para esta.

Entonces para crear una clase Saturno debería ser algo así:

  1. function Saturno(){
  2.   // Propiedades y Metodos aquí
  3. }

Lo que en java seria esto:

  1. public class Saturno {
  2.   // Propiedades y Metodos aquí
  3. }

Agregando un poco de complejidad al asunto sería algo como esto:

  1. function Saturno(){
  2.   this.lunas = ['Mimas','Encelado','Tetis','Dione','Rea','Titan','Hiperion','Japeto','Febe'];
  3.   this.getLuna = function(indice){
  4.     return this.lunas[indice];
  5.   };
  6.   this.cuantasLunas = function(){
  7.     return 'Saturno tiene '+this.lunas.length+' lunas';
  8.   };  
  9. }

Lo que en java sería algo asi:

  1. public class Saturno {
  2.   public ArrayList lunas = new ArrayList(
  3. "Mimas","Encelado","Tetis","Dione","Rea","Titan","Hiperion","Japeto","Febe");
  4.   public String getLuna(int indice){
  5.     return (String)this.lunas.get(indice);
  6.   }
  7.   public String cuantasLunas (){
  8.     return “Saturno tiene “+ this.lunas.size()+” lunas”;
  9.   }
  10. }

En el caso anterior (Refiriéndome al caso Javascript por supuesto) debemos notar que todas las propiedades se definen como “ this.propiedad = algo “ donde algo puede ser una variable cualquiera de tipo nativo u otra función que pasaría a ser un método.

Si entramos a detallar mejor lo que contiene la clase podemos ver:

  1. Existe una variable “lunas” que es de tipo Array de Strings
  2. Existe una función llamada “getLuna” que resibe un numero y retorna un String
  3. Existe una función llamada “cuantasLunas” que retorna un String
Constructores en Javascript

Realmente como dije antes No Existen “funciones constructoras” sino que la “clase” recibe el o los valor y se le asigna directamente a las propiedades.
De nuevo una comparación JavaScript v/s Java

La aburrida y reusada Clase Persona en Javascipt:

  1. function Persona(nombre, rut){
  2.   this.rut = rut;
  3.   this.nombre = nombre;
  4. }
  5. // Usar la clase
  6. var instancia = new Persona(“Soma”,”11.111.111-1);

La misma clase Persona en Java:

  1. public class Persona{
  2.   public String rut;
  3.   public String nombre;
  4.   public Persona(String nombre, String rut){
  5.     this.rut = rut;
  6.     this.nombre = nombre;
  7.   }
  8. }
  9. // Usar la clase
  10. Persona instancia = new Persona(“Soma”,”11.111.111-1);

En el ejemplo Javacript anterior lo que se hace es asignar directamente a las propiedades las variables que las clase/función recibe.

Y es todo lo que debemos saber de los constructores, es la triste verdad, pero de validar las cosas deberían preocuparse los métodos.

Conclusión

Como pudimos ver (que no es que realmente sea mucho) ya tenemos como hacer nuestro pequeño sistema de clases en Javascript y trabajar un “poco mas mejor” y empezar a pensar en recursivo nuevamente y no estructurado :) , Sinceramente en cuanto a diseño de clases no es posible hacer gran cosa de una manera estándar, pero siempre hay soluciones que espero postear en un futuro.

Espero sea de utilidad

Manejo de días en Select según mes elegido con javascript

Calendar

Unos compañeros estaban un poco complicados con el manejo de fechas y sus correspondientes días en un formulario HTML, así que como buena persona que soy, decidí ayudarles con un poco de javascript (Ver Demo).

Aquí explico mas menos como manejar los Select en este caso especifico, que es un tema bastante recurrente y con miles de soluciones en Google, pero quizá aquí lo pueda explicar un tanto mejor y con menos código.

Básicamente lo que debemos hacer es:
Al seleccionar un Mes en un Select llamar a una función que según el mes seleccionado vacíe otro Select correspondiente a los días del mes y luego lo llene con la cantidad de números correspondientes.

Ejemplo claro aquí :)

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4.   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5.   <title>Manejo de Meses y dias correspondientes con javascript : ElSoma.net</title>
  6.   <script type="text/javascript">
  7.     function cambiarMeses(s){
  8.       // Cantidad de Dias correspondientes al Mes
  9.       var nMeses = [31,28,31,30,31,30,31,31,30,31,30,31];
  10.       //> Elimino todas las OPTION del select asigandole un valor NULL
  11.       var i=0;
  12.       while(document.getElementById('dias').options.length>0){
  13.         document.getElementById('dias').options[i] = null;
  14.       }
  15.       //> Creo los OPTIONS en 'dias' segun la cantidad correspondiente al mes seleccionado en 'meses'
  16.       for(var i=1; i<=nMeses[s.selectedIndex]; i++){
  17.         document.getElementById('dias').options[i-1] = new Option(i,i);
  18.       }
  19.     }
  20.   </script>
  21. </head>
  22. <body>
  23.   <select id="meses" onchange="cambiarMeses(this)">
  24.     <option value="1">Enero</option>
  25.     <option value="2">Febrero</option>
  26.     <option value="3">Marzo</option>
  27.     <option value="4">Abril</option>
  28.     <option value="5">Mayo</option>
  29.     <option value="6">Junio</option>
  30.     <option value="7">Julio</option>
  31.     <option value="8">Agosto</option>
  32.     <option value="9">Septiembre</option>
  33.     <option value="10">Octubre</option>
  34.     <option value="11">Noviembre</option>
  35.     <option value="12">Diciembre</option>
  36.   </select>
  37.   <select id="dias">
  38.     <option value="">Vacio</option>
  39.   </select>
  40. </body>
  41. </html>

Cálculo de Direccionamiento de red con PHP

Subredes Broadcast Mascara de red calculo automatico

Hace unos días rendí un pequeño certamen en donde debía, por una parte, calcular las IP , Mascaras y Broadcast de las subredes desde cierta IP Base.

Tuve la grandiosa idea de crear un mini-programa con fines de estudio (Ver Demo), y que hiciera esa tarea por mi.
Así que dejaré el resultado de mi arduo trabajo aquí :)

Nota: La clase no valida entradas, se asume que las ip enviadas y todos los datos son reales y coherentes, estaba apurado

  1. <?php
  2.   class IP {
  3.     public $ip;
  4.     // Crea el obtjeto segun String de IP decimal, y una bandera que si es true hace necesario que la IP este en formato binario
  5.     public function IP($valor, $enBinaria=false){
  6.       $this->ip = $valor;
  7.       if($enBinaria==true){
  8.         $this->ip = $this->getDec();
  9.       }
  10.     }
  11.     //> Retorna un String con la IP de forma binaria de largo 8 bits
  12.     public function getBin(){
  13.       $x=0;
  14.       $IPBin = '';
  15.       foreach(explode('.',$this->ip) as $T){
  16.         $IPBin .= str_pad(substr((intval(decbin($T))), 0,8), 8, '0', STR_PAD_LEFT).($x<3?'.':'');
  17.         $x++;
  18.       }
  19.       return $IPBin;
  20.     }  
  21.     //> Retorna un String con la IP de forma decimal
  22.     public function getDec(){
  23.       return $this->ip;
  24.     }
  25.     //> Setea un campo de la IP con un valor decimal cualsea
  26.     public function setIn($n,$seccion){
  27.       $partes = explode('.',$this->ip);
  28.       $x=0;
  29.       $this->ip = '';
  30.       foreach($partes as $T){
  31.         if($seccion==$x){
  32.           $this->ip .= $n.($x<3?'.':'');
  33.         }else{
  34.           $this->ip .= $T.($x<3?'.':'');
  35.         }
  36.         $x++;
  37.       }
  38.     }
  39.     //> Aumenta en N la ip
  40.     public function addHosts($n,$seccion=4){
  41.       $seccion–;
  42.       $parte = explode('.',$this->ip);
  43.       $nuevoValor = $parte[$seccion]+$n;
  44.         while($nuevoValor>255){
  45.           if($seccion==0){
  46.             throw new Exception('La IP no tiene mas valores posibles');
  47.           }
  48.           $this->addHosts(1, $seccion);
  49.           $nuevoValor = $nuevoValor-256;
  50.         }
  51.       $this->setIn($nuevoValor,$seccion);
  52.       return $this->ip;
  53.     }
  54.     //> Retorna un objeto IP que reprecenta la ultima ip disponible segun pa mascara
  55.     public function getBroadcast($mascara){      
  56.       $BroadcastT = $this->getBin();
  57.       $bits = $mascara->getBitsHost();
  58.       for($i=0; $i<$bits; $i++){
  59.         if($BroadcastT[(strlen($BroadcastT)-1)-$i]!='.'){
  60.           $BroadcastT[(strlen($BroadcastT)-1)-$i] = '1';
  61.          
  62.         }else{
  63.           $bits++;
  64.         }
  65.       }
  66.       $x=0;
  67.       $IPBin = '';
  68.       foreach(explode('.',$BroadcastT) as $T){
  69.         $IPBin .= str_pad(substr((bindec($T)), 0,3), 3, '0', STR_PAD_LEFT).($x<3?'.':'');
  70.         $x++;
  71.       }
  72.       return new IP($IPBin);      
  73.     }
  74.     //> Retorna un objeto IPMascara segun la clase de la IP
  75.     public function getDefaultMask(){
  76.       $parte = explode('.',$this->ip);
  77.       $parte = $parte[0];
  78.       if($parte<=127){
  79.         return new IPMascara(8);
  80.       }else if($parte<=191){
  81.         return new IPMascara(16);
  82.       }else if($parte<=223){
  83.         return new IPMascara(24);
  84.       }else{
  85.         echo "Advertencia Mascara de red incorrecta\n";
  86.         return new IPMascara(32);
  87.       }
  88.     }
  89.   }
  90.   class IPMascara extends IP {
  91.     // Crea una mascara segun cantidad de bists de RED definidos
  92.     public function IPMascara($n){
  93.       parent::IP('');
  94.       for($i=1; $i<=32; $i++){
  95.         $ip = ($i<(32-$n+1)?'0':'1').$ip;    
  96.         if($i==8 or $i==16 or $i==24 ){
  97.           $ip = '.'.$ip;
  98.         }
  99.       }
  100.       $x=0;
  101.       $this->ip = '';
  102.       foreach(explode('.',$ip) as $T){
  103.         $this->ip .= str_pad(substr((bindec($T)), 0,3), 3, '0', STR_PAD_LEFT).($x<3?'.':'');
  104.         $x++;
  105.       }
  106.     }
  107.     // Retorna un array asociativo [red,host] con los bits disponibles de Red y Host
  108.     public function getBits(){
  109.       $mascara = str_replace('.','',$this->getBin());    
  110.       $red  = 0;
  111.       $host = 0;
  112.       for($i=0; $i<strlen($mascara); $i++){
  113.         if($mascara[$i]=='1'){
  114.           $red++;
  115.         }else{
  116.           $host++;        
  117.         }
  118.       }
  119.       return array('red'=>$red, 'host'=>$host);
  120.     }
  121.     // Retorna los bits de red
  122.     public function getBitsRed(){
  123.       $b = $this->getBits();
  124.       return intval($b['red']);
  125.     }
  126.     // Retorna los bits de host
  127.     public function getBitsHost(){
  128.       $b = $this->getBits();
  129.       return intval($b['host']);
  130.     }
  131.   }  
  132.   if(isset($_POST['salvameSoma'])){
  133.     echo '<textarea style="width:100%; height:500px">';
  134.     $datoIp   = str_replace(' ','',$_POST['ip']);
  135.     $datoMa   = str_replace(' ','',$_POST['mascara']);
  136.     $datoHots   = explode(',',str_replace(' ','',$_POST['hosts']));
  137.     arsort($datoHots);    
  138.     $IP = new IP($datoIp);
  139.     $Ma = ($datoMa=='' or $datoMa=='m')?$IP->getDefaultMask():new IPMascara($datoMa);    
  140.     echo "La IP base es \t\t: ".$IP->getDec()."\t\t:  ".$IP->getBin()."\n";
  141.     echo "La Mascara base es \t: ".$Ma->getDec()."\t:  ".$Ma->getBin()." (Red:".$Ma->getBitsRed().", Host:".$Ma->getBitsHost().")\n";    
  142.     echo "\nHost Solicitados:\n\n";    
  143.     foreach($datoHots as $h){
  144.       echo "\tHost para ".$h."\n";
  145.       echo "\t——————\n";      
  146.       $bits = 0;
  147.       while(pow(2,$bits)-2 < $h){ $bits++; }      
  148.       echo "\tBits de host necesarios : ".$bits."\n";      
  149.       echo "\tIP\t  : ".$IP->getBin()." : ".$IP->getDec()."    \t/".(32-$bits)."\n";  
  150.       $Ma = new IPMascara(32-$bits);
  151.       echo "\tMascara\t  : ".$Ma->getBin()." : ".$Ma->getDec()."\n";
  152.       $Br = $IP->getBroadcast($Ma);
  153.       echo "\tBroadcast : ".$Br->getBin()." : ".$Br->getDec()."    \t/".(32-$bits)."\n";
  154.       $Br->addHosts(1);
  155.       $IP = new IP($Br->getDec());
  156.       echo "\n\n";
  157.     }
  158.     echo '</textarea>';
  159.   }
  160. ?>
  161. <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
  162.   <fieldset>
  163.     <label>IP Base</label>
  164.     <input type="text" name="ip" /><i> Ej: 1.1.1.1</i>
  165.   </fieldset>
  166.   <fieldset>
  167.     <label>Largo Mascara</label>
  168.     <input type="text" name="mascara" /> <i>Ej: 24</i>
  169.   </fieldset>
  170.   <fieldset>
  171.     <label>Hosts separados por coma</label>
  172.     <input type="text" name="hosts" /> <i>Ej: 200,100,20,4,6 (da lo mismo el orden)</i>
  173.   </fieldset>
  174.   <fieldset>
  175.     <input type="submit" name="salvameSoma" value="Ver resultado" />
  176.   </fieldset>
  177. </form>

Manejo de Cookies en PHP para identificación de usuario

php cookies

En estos días supe que un compañero se le ocurrió autenticar usuarios en su proyecto semestral, y que su compañero de trabajo no le tomo mucha importancia, y eso me dio la idea de dejar aquí explicado cómo lograr identificar a un usuario que ingreso usuario y contraseña en nuestro sitio para fines de privacidad.

En si el ejemplo siguiente no tiene mucha ciencia y es bastante poco usado, pero para fines de estudio es la mejor opción según mi criterio.

¿Qué demonios es un Cookie?

Una cookie es un archivo que el servidor almacena en el computador del cliente, contiene un nombre y valor especifico y además tiene una duración.

Este archivo y su “dato” por supuesto pueden ser recuperados y/o eliminados por el servidor que lo creó, que para fines prácticos obviamente es lo que nos interesa :)

Consideración importante

Como el archivo cookie se guarda en el cliente quedara desprotegido ante el posible mal uso del propio usuario y/o de programas que tenga instalado el usuario en su maquina. Eso quiere decir que NO debes almacenar información importante en las cookies, solo info de referencia o banderas.

No creo que te sea de mucha gracia entrar al tu correo y que el servidor guarde un archivo con tu e-mail y contraseña para que luego un insignificante “virus” lea el archivo y te agregue a su lista de mails robados :)

Conocimientos previos necesarios

Básicamente para hacer funcionar esto debemos conocer las funciones setcookie() y time() de PHP.

Time()

Esta función simplemente retorna un numero que representa la cantidad de segundos que han transcurrido desde el Enero-01-1970 (es una fecha elegida por los sistema Unix vaya a saber alguien de donde salió), y es todo lo que debemos saber de ella.

Setcookie()

Esta función es la que almacena el archivo cookie en la maquina del cliente y le asigna un valor al mismo tiempo. Debe ser usada en la primera línea del código igual que las sesiones y no puede existir antes ningún echo, print() o cualquier cosa que imprima algo.

Se usa de la siguiente manera:

  1. <?php
  2. setcookie(  'ID de la cookie'  ,  'Valor'  , 'fecha de fin de validez en segundos desde 1970' );
  3. ?>

Y para accesar el valor que hemos guardado hacemos lo siguiente:

  1. <?php
  2. echo $_COOKIE['ID de la cookie'];
  3. ?>

Un ejemplo practico

A continuación haremos un pequeño “sistema” de login, la idea es que el usuario ingrese usuario ‘root’ y contraseña ‘redhat’ y entre a una sección privada (que no será nada más que un mensaje), y que también pueda salir o “matar la cookie”

Nota: El número 604800 es el total de segundos que hay en una semana, o sea que “time () + 604800″ quiere decir desde hoy (time()) + una semana (604800 )

  1. <?php
  2. //> Acciones en caso de que se haya enviado el formulario
  3. if(isset($_POST['btnLogin'])){
  4.   if($_POST['usuario']=='root' and $_POST['clave']=='redhat'){
  5.     // Guardo la cookie en el navegador del usuario
  6.     setcookie('indicador','estas dentro', time () + 604800);
  7.     // Actualizo la pagina o "Buelvo a entrar" que es lo mismo =D
  8.     header('location: /cookies.php');
  9.   }else{
  10.     echo 'Esa no es la clave hijo';
  11.     // Elimino la cookie del navegador del cliente
  12.     setcookie('indicador','valor que no sirbe', time () - 604800);
  13.     header('location: /cookies.php');
  14.   }  
  15. }
  16.  
  17. // Si mando por GET la accion salir .. archivo.php?accion=salir, mato la cookie
  18. if($_GET['accion']=='salir'){
  19.   // Asigna un valor Inutil a la cookie
  20.   setcookie('indicador','valor que no sirbe', time () - 604800);
  21.   header('location: /cookies.php');
  22. }
  23.  
  24. // Si el valor de la cookie es "'estas dentro'" Muetro el mensaje de bienvenida
  25. if($_COOKIE['indicador']=='estas dentro'){
  26.  
  27.   // Esta sera la seccion "Privada"
  28.   echo 'Usted esta en el sistema, <a href="cookies.php?accion=salir">Aqui puede salir</a>';
  29.  
  30.  
  31. }else{
  32.  
  33.   // Esta sera la seccion publica en donde mostraremos el usuario
  34.   echo '<form method="post">
  35.    Usuario : <input type="text" name="usuario" /><br>
  36.    Clave : <input type="text" name="clave" /><br>
  37.    <input type="submit" name="btnLogin" value="Entrar" />
  38.  </form>';
  39.  
  40. }
  41. ?>