dsite.es
2mar/1031

TinyTable v3 con jQuery Context Menu y Dialog UI

Introducción

Hace ya algún tiempo que en la Web de anieto2k encontré un interesante artículo sobre TinyTable v3.

TinyTable v3 es un script Javascript que agrega ordenación, búsqueda, promedios de columna y totales, paginación... en tablas HTML. Todo esto lo hace con tan sólo 7Kb!!

Partiendo de esta base y después de usar TinyTable en diferentes proyectos he visto la necesidad de extender sus funcionalidades, concretamente el uso de jQuery Context Menu y jQuery Dialog UI.

Librerías usadas

Listado de librerías usadas para este desarrollo:

  • JQuery 1.4.2
  • TinyTable v3
  • jQuery Context Menu
  • jQuery Dialog UI

Motor del sistema

Para poder controlar todas las acciones que intervienen en el Script programado he creado un "controller" para canalizarlas y así simplificar el código:

function Controller(action, el)
{
	//COLUMNA de TinyTable con el id principal
	var idColumn = 0;
	//COLUMNA de TinyTable con el nombre más destacado
	var nameColumn = 1;
	var ids = $(el).children('td').eq(idColumn).text();

	switch(action)
	{
		case "eliminarAction":
			alert("Eliminar "+$('#dialogTable #idEliminar').text());
			break;
		case "eliminar":
			$('#dialogTable').dialog('open');
			$('#dialogTable #nomEliminar').text($(el).children('td').eq(nameColumn).text());
			$('#dialogTable #idEliminar').text(ids);
			break;
		case "editar":
			alert("Eliminar fila: "+ids);
			break;
	}
}

Como queremos que el menú secundario aparezca en cada fila de la tabla, creamos un método para poder inicializar las propiedades de las fila "TR" al finalizar la carga de la página y al realizar una reordenación de la tabla.

function initFuncionsTaula()
{
//Iniciamos el menú secundario personalizado para las filas de la tabla
	$('#tableData tbody tr').contextMenu({
			menu: 'contextMenuElements',
			inSpeed: 10,
			outSpeed: 10
		},
		function(action, el, pos) {
			Controller(action, el)
		}
	);
//Permitimos que se pueda editar la fila con doble click de ratón.
	$('#tableData tbody tr').dblclick(
		function() {
			Controller('editar', this)
		}
	);
}

Modificaciones a Tiny Table v3

Tiny Table al ordenar y al hacer un reset en las filas, reescribe el contenido de ellas una vez ordenadas internamente, esto hace que las inicializaciones de initFunctionsTaula() no tengan efecto. Es por eso que he hecho unas pequeñas modificaciones a Tiny Table para que inicialice nuestros métodos cada vez que se cambia la estructura:

Fichero tinytable/script-new.js

[...]
TINY.table=function(){
	function sorter(n,t,p,r){this.n=n; this.id=t; this.p=p; if(r == undefined ) r = function(){}; this.r = r; if(this.p.init){this.init()}}
[...]

Ahora Tiny Table v3 tiene un cuarto parámetro que es una función que se llamará en sorter.prototype.reset y sorter.prototype.sort, como this.r().

Inicialización de Tiny Table y jQuery Dialog UI

Para finalizar nuestro código Javascrit para que todo funcione nos falta iniciar Tiny Table con el método initFunctionsTaula() y jQuery Dialog UI usando $(document).ready() de Jquery:

var sorter = null;
$(document).ready( function() {
	//INICIAR TINYTABLE
	sorter = new TINY.table.sorter('sorter','tableData',{
		headclass:'head',
		ascclass:'asc',
		descclass:'desc',
		evenclass:'evenrow',
		oddclass:'oddrow',
		evenselclass:'evenselected',
		oddselclass:'oddselected',
		paginate:true,
		size:10,
		colddid:'columns',
		currentid:'currentpage',
		totalid:'totalpages',
		startingrecid:'startrecord',
		endingrecid:'endrecord',
		totalrecid:'totalrecords',
		hoverid:'selectedrow',
		pageddid:'pagedropdown',
		navid:'tablenav',
		sortcolumn:1,
		sortdir:1,
		sum:[8],
		avg:[6,7,8,9],
		columns:[{index:7, format:'%', decimals:1},{index:8, format:'$', decimals:0}],
		init:true
		},
		function() {initFuncionsTaula()}
	);
	//INICIALIZAR EL MÓDULO DE DIALOGO
	$("#dialogTable").dialog({
		bgiframe: true,
		resizable: false,
		autoOpen: false,
		modal: true,
		overlay: {
			backgroundColor: '#000',
			opacity: 0.5
		},
		buttons: {
			'Cancelar': function() {
				$(this).dialog('close');
			},
			'Eliminar esta fila': function() {
				Controller('eliminarAction',this);
				$(this).dialog('close');
			}
		}
	});
});

Para el menú secundario ContextMenu será necesario algo como esto:


Y esto para el contenido del diálogo de eliminar:

 Está intentando eliminar la fila: ¿Está seguro que desea continuar?

Ejemplo y descarga

Aquí os dejo un ejemplo y el código para que lo podáis usar fácilmente.

Puedes ver un ejemplo aquí

Descargar código completo

¿Te gustó este artículo?

¡Suscríbete a nuestro feed RSS!

Comentarios (31) Trackbacks (1)
  1. Muchas Gracias por responder mi comentario esta seria mi tabla :) es para administrar Altas Bajas Y actualizaciones de usuario tengo 1 boton que me da de alta con el jquery dialog y las modificaciones las ago normalmente con php y eliminacion igual…. pero en si eso no importa ya que si lo implemento con TiniTable me ahorarria muchos problemas…. este seria mi código:

    <?php            //include_once 'Prueba.php'; ?>
        <table align="center" Width="100%" class="table">
            <?php
            $mysqli = new mysqli("localhost", "root", "root");
            $mysqli->select_db("zer");
            $datos = $mysqli->query("CALL Mostrar_Usuarios()");
    
            if ($fila = $datos->fetch_object()) {
            ?>
    
            <thead class="thead">
                <tr class="tr"><th scope="col" class="th">Usuario</th>
                    <th scope="col" class="th">Password</th>
                    <th scope="col" class="th">Tipo_Usuario</th>
                    <th scope="col" class="th">Nombre</th>
                       <th scope="col" class="th">Email</th>
                    <th scope="col" class="th">Modificar</th>
                    <th scope="col" class="th">Eliminar</th>
                </tr>
            </thead>
            <tbody>
    <? do { ?>
                   <tr class="tr"><th scope="row" id="r100" class="th"><?php echo $fila->Usuario ?></th>
                        <td class="td"><?php echo $fila->Pass ?></td>
                        <td class="td"><?php echo $fila->Tipo_Usuario ?></td>
                        <td class="td"><?php echo $fila->Nombre ?></td>
                            <td class="td"><?php echo $fila->Email?></td>
                        <td class="td"><a href="EditarU.php?id=<?php echo $fila->idUsuario ?>" >
                                <center><img src="images/edit.png"></center></a></td>
                        <td class="td"><a href="EliminarU.php?id=<?php echo $fila->idUsuario ?>" >
                                <center><img src="images/delete.png"></center></a></td>
                    </tr>
    <? } while ($fila = $datos->fetch_object()); ?>
        </table>
    <?php } else { ?>
                <table align="center">
                    <tr><td>No Existen Usuarios</td></tr>
                    <tr><td><a href="Usuarios.php"><center><img src="images/add1.png" width="80" height="100"/></center></a><br><b>Agregar Usuario</b></td>';
                    </tr></table>
    <? } ?>
    
    </tbody>
    </body>
    </html>
  2. Hola a todos, tratare de dejar mi aporte en el tema de la consulta a MySql para mostrarlos en el formato de presentacion de TinyTable:

    Asumo que cuestiones como conexión, ya no son ningun problema para ustedes… asi que no me enfocare en este tema.

    Dependiendo con que herramienta de desarrollo esten trabajando, es bastante sencillo crear un juego de registros (Result Set), para hacer uso del mismo posteriormente. En Dreamweaver es bastante sencillo ya teniendo la conexión a la BD MySql, es solo cuestion de ir a Vinculaciones y de alli generar un Juego de Registros a partir de X tabla de la BD.

    El te generara algo como esto:

    // archivo de conexion
    <?php

    // esto lo utiliza para validar que version de php tienes y asi utilizar determinada funcion
    // con el fin de clasificar el tipo de dato devuelto por la consulta.

    if (!function_exists("GetSQLValueString")) {
    function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "")
    {
    if (PHP_VERSION < 6) {
    $theValue = get_magic_quotes_gpc() ? stripslashes($theValue) : $theValue;
    }

    $theValue = function_exists("mysql_real_escape_string") ? mysql_real_escape_string($theValue) : mysql_escape_string($theValue);

    switch ($theType) {
    case "text":
    $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
    break;
    case "long":
    case "int":
    $theValue = ($theValue != "") ? intval($theValue) : "NULL";
    break;
    case "double":
    $theValue = ($theValue != "") ? doubleval($theValue) : "NULL";
    break;
    case "date":
    $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
    break;
    case "defined":
    $theValue = ($theValue != "") ? $theDefinedValue : $theNotDefinedValue;
    break;
    }
    return $theValue; //devuelve el tipo de dato
    }
    }

    $maxRows_clientes = 10; //por si te interesa la paginacion o rendimiento de la consulta, limitas el numero de registros devueltos por cada consulta a la BD
    $pageNum_clientes = 0; //inicializas la paginacion en 0 e incrementara segun el total de registros
    if (isset($_GET['pageNum_clientes'])) {
    $pageNum_clientes = $_GET['pageNum_clientes'];
    }
    $startRow_clientes = $pageNum_clientes * $maxRows_clientes;

    mysql_select_db($database_usuarios, $usuarios);
    $query_clientes = "SELECT * FROM cliente"; //lanzas la consulta
    $query_limit_clientes = sprintf("%s LIMIT %d, %d", $query_clientes, $startRow_clientes, $maxRows_clientes);
    $clientes = mysql_query($query_limit_clientes, $usuarios) or die(mysql_error());
    $row_clientes = mysql_fetch_assoc($clientes);

    if (isset($_GET['totalRows_clientes'])) {
    $totalRows_clientes = $_GET['totalRows_clientes']; //total de filas
    } else {
    $all_clientes = mysql_query($query_clientes); //total de registros
    $totalRows_clientes = mysql_num_rows($all_clientes); //total de filas en base a los registros
    }
    $totalPages_clientes = ceil($totalRows_clientes/$maxRows_clientes)-1; //paginas.

    Teniendo ya la consulta cargada… es bastante sencillo e intuitivo como mandar a llamar los datos o cargarlos dentro de la estructura de la Tabla…

    para el compañero que tenia duda sobre como repetir el ciclo para mostrar todos los registros, ps es bastante sencillo, solo se agregan dos lineas mas de codigo…

    // Primera linea

    // Segunda Linea.

    bueno con esto ya tienen ustedes formateada la consulta a MySql, dentro de la estructura de la tabla TinyTable. Espero les sirva y sea eso lo que buscaban…

    un saludo.

  3. Hola buenas tardes buen documental soy novato y no se como implementar esa tabla con php ya tengo una tabla con css y con php pero no se como aplicarlo dentro de tinytable

  4. I am totally delighte with incredibly blog greatly that save me! Thank you

  5. a mi tambien me interesa cargar los datos en la tabla por medio de una consulta a mysql.

    alguien ya sabe como?

    gracias

  6. Hola este es un gran trabajo, estoy tratando de usarlo para una aplicación en php, la cual recupera datos de mysql y los muestra al administrador.

    El problema es que no me da la funcion de repetir region, es decir, que a partir de una sola fila se generen todos los datos encontrados en mysql.

    Agradezco su ayuda.

    • Hola, para iniciar la tabla desde MySQL y usando PHP debes hacer alguna cosa así:

      $rs = mysql_query(“SELECT id, nombre FROM datos”);
      while($row = mysql_fetch_array())
      {
      echo “
      “.$row['id'].” “.$row['nombre'].”

      “;
      }

      De hecho, no se si se puede cargar directamente los datos en la tabla de otra forma, ya que TinyTable formatea la tabla HTML.
      Igual, se pueden cargar los datos mediante AJAX. Pero no lo he desarrollado. Si lo encuentras espero que lo hagas público para todos ;-)

  7. Muchas gracias David, voy a probarlo

  8. Gracias David!!! Genio!!!

  9. Si seria perfecto, yo sigo buscando alguan solucion pero todavia no doy una, gracias de antemano

    • Hola Daniel, ya tengo la solución para lo que me pides.

      Debes modificar el fichero jquery.contextMenu.js y agregar estas líneas:

      var menuW = menu.width();
      var parentRightPosition = $(this).position().left+$(this).width();
      if((x+menuW) > parentRightPosition)
      {
      x -= menuW;
      }

      Este código lo tienes que poner antes de:
      $(menu).css({ top: y, left: x }).fadeIn(o.inSpeed);

      Una vez hayas puesto esto, al mostrar el menú contextual, si este sale más que el objeto parent en vez de mostrarse hacia la derecha, se mostrará hacia la izquierda.

      Saludos,

      David

  10. Hola de nuevo yo, ya logre resolver el problema, pero tengo una duda, si hago la tabla mas pequeña (720px), el menú contextual queda bastante desplazado a la derecha, como puedo evitarlo?

    • Hola Daniel, me imagino que al aparecer de la posición del ratón a la derecha, el menú contextual puede salir de la pantalla o de la zona de la tabla. Voy a investigar cómo se puede controlar que salga hacia la derecha si queda fuera de la tabla… con esto bastaría?

  11. Hola david, estoy intentando utilizar tu version de tinytable con tablñas dinamicas generadas desde php y mysql, pero no logro iniciar el objeto, tienes alguna idea de por que pueda pasar?

  12. Hola David, cuando hago búsquedas con tiny table en un apellido con tilde, por ej. Villaró, si está cargado Villaro sin tilde no lo encuentra, hay forma de cambiarlo?

    Gracias!!!

  13. buena ayuda, pero no se me podrian ayudar necesito seleccionar una fila al hacer clic con el mouse y obtener un dato o varios datos de la fila y dejarlo seleccionado y cuando seleccione otra fila hacer el mismo proceso del anterior y se desmarque y sobre las otras filas tenga la misma funcionalidad de tinytable me podrian decir donde puedo editar los archivos para hacer este proceso agradeceria mucho esta ayuda

  14. buen articulo! ahora como hago para borrar la fila resaltada … gracias por el aporte

  15. Buen artículo! Gracias.


Leave a comment

(required)