Ordenar y votar:una encuesta de jQuery

Hoy vamos a hacer una encuesta de clasificación y votación arrastrable, que permitirá a los visitantes de nuestro sitio web elegir su tutorial favorito del sitio. Después de votar, un gráfico de CSS amigable les mostrará cómo se clasifican los tutoriales y el número total de votantes.

Para lograr esto, usaremos jQuery , interfaz de usuario de jQuery , PHP , CSS &MySQL .

Puedes usar el código que proporciono aquí para hacer tus propias versiones y mash-ups.

Paso 1 - XHTML

Para comprender mejor estos pasos, sería bueno tener los archivos de descarga cerca y abiertos, para que pueda rastrear de dónde se origina el código que explico aquí.

Empezamos con el marcado XHTML. PHP agrega una gran parte de este código programáticamente. A continuación se muestra la sección extraída de demo.php :

demo.php

<div id="main">

<?php
/* ... */
?>

<div class="clear"></div>

<!-- The form below is not directly available to the user -->
<form action="?results" id="sform" method="post">
<input name="sortdata" id="sortdata" type="hidden" value="" />
</form>

Cabe destacar la forma forma. Contiene un único campo de texto oculto:sortdata . Se llena con jQuery en el momento en que presionamos el botón de envío de la encuesta y contiene una cadena que representa el orden y las ID únicas de los tutoriales que estamos clasificando. Volveremos a esto en un momento.

Quizás más interesante aquí es la parte de PHP en las líneas 3-5. Contiene el código que maneja la generación de los elementos de la lista ordenable y la creación del gráfico. He incluido a continuación solo el marcado XHTML que se usa para construir la lista. Echaremos un vistazo más de cerca al resto de este código en la sección PHP de este tutorial.

<li id="<?php echo $row['id']?>">

<div class="tut">
<div class="tut-img">
<img src="<?php echo $row['img']?>" width="100" height="100" alt="<?php echo $row['title']?>" />
<div class="drag-label"></div>
</div>

<div class="tut-title">
<a href="<?php echo $row['url']?>" target="_blank" title="Open it in a new window!"><?php echo $row['title']?></a>
</div>

<div class="tut-description"><?php echo $row['description']?></div>

<div class="clear"></div>

</div>
</li>

Este código se coloca dentro de un ciclo while, que lo genera para cada elemento de la lista. Y porque hemos incluido algunos echo -s, esto nos permite insertar datos dinámicos, en este caso títulos y urls extraídos de la base de datos.

Ahora profundicemos un poco más en los estilos CSS.

Paso 2:CSS

En el código a continuación, puede ver cómo hemos diseñado el XHTML que generamos anteriormente. Debido a la longitud del código, solo he incluido lo que la encuesta usa directamente. Puede ver el resto del código, que le da estilo a la página de demostración, en demo.css .

demo.css - Parte 1

.tut-title{
    font-size:20px;
    font-weight:bold;
}

.tut-description{
    color:#DDDDDD;
    font-family:Arial,Helvetica,sans-serif;
    font-size:11px;
    padding-top:5px;
}

.tut-img{
    border:1px solid white;
    float:left;
    margin:0 15px 0 0;

    width:100px;
    height:100px;
    overflow:hidden;

    /* CSS3 Box Shadow */
    -moz-box-shadow:2px 2px 3px #333333;
    -webkit-box-shadow:2px 2px 3px #333333;
    box-shadow:2px 2px 3px #333333;
    cursor:n-resize;
    position:relative;
}

.drag-label{
    /* The DRAG label that scrolls into visibility on hover */
    background:url(img/label_small.png) no-repeat;
    width:71px;
    height:25px;
    position:relative;
    margin-left:25px;
}

a.button{
    /* The pretty buttons on the bottom are actually hyperlinks.. */
    color:#434343 !important;
    display:block;
    float:left;
    font-size:10px;
    font-weight:bold;
    height:23px;
    margin:10px;
    padding:12px 10px 0 12px;
    position:relative;
    text-shadow:none;
    text-transform:uppercase;

    /* This is the left part of the button background image */

    background:transparent url(img/button_gray_bg.png) no-repeat;
}

a.button:hover{
    text-decoration:none !important;
    background-position:bottom left;
}

a.button:active{
    /* Offsetting the text 1px to the bottom on mouse-click*/
    padding-top:13px;
    height:22px;
}

a.button span{
    /* This span holds the right part of the button backgound */
    background:transparent url(img/button_gray_bg.png) no-repeat right top;
    height:35px;
    position:absolute;
    right:-2px;
    top:0;
    width:10px;
    display:block;
}

a.button:hover span{
    background-position:bottom right;
}

Hay algunas técnicas y propiedades interesantes utilizadas en el código anterior. Una de ellas es la propiedad box-shadow de propiedad especial de CSS3, que agrega una sombra debajo de cada miniatura.

En la siguiente ilustración, puede ver cómo creé los elegantes botones de envío/resultado.

demo.css - Parte 2

.button-holder{
    padding-left:107px;
}

ul.sort{
    /* This UL gets converted to a sortable by jQuery */
    font-family:"Myriad Pro",Arial,Helvetica,sans-serif;
    font-size:20px;
}

ul.sort li{
    margin:25px 50px 25px 0;
    height:102px;
    list-style:none;
}

.chart{
    /* Styling the chart container */
    background:#002A3C;
    border:1px solid #005A7F;
    height:300px;
    width:550px;
}

.bar{
    /* Each bar in the chart is a div. Colors and width are assigned later */
    height:17px;
    margin:15px;
    overflow:hidden;
    padding:15px 10px 10px;
    text-shadow:none;
    white-space:nowrap;
}

.bar a, .bar a:visited{
    color:white;
    font-size:12px;
}

.tot-votes{
    float:right;
    font-size:10px;
    font-weight:bold;
    position:relative;
    right:50px;
    text-transform:uppercase;
    top:18px;
}

En esta parte del código tenemos las clases que dan estilo al gráfico. Como puede ver, en este punto no hemos asignado colores ni anchos a las barras, principalmente porque esos dos estilos se generan de acuerdo con la cantidad de votos que recibió cada entrada. Volveremos a esto en un momento.

Paso 3 - PHP

PHP genera los elementos de la lista ordenable, se comunica con la base de datos y genera el gráfico.

A continuación puede ver el código que mencionamos anteriormente. En primer lugar, obtiene todos los objetos de la base de datos y, en segundo lugar, genera la lista ordenable.

demo.php

// Checking whether the user has voted today:
$voted=false;

$vcheck=mysql_query("   SELECT 1 FROM sort_votes
            WHERE ip='".$_SERVER['REMOTE_ADDR']."'
            AND date_submit=CURDATE()");

if(mysql_num_rows($vcheck)==1)
    $voted=true;

// If we are not on the data.php?results page:
if(!array_key_exists('results',$_GET))
{
    echo '<ul class="sort">';

    // Showing the tutorials by random
    $res = mysql_query("SELECT * FROM sort_objects ORDER BY RAND()");

    while($row=mysql_fetch_assoc($res))
    {?>

    <li id="<?php echo $row['id']?>">
    <div class="tut">
    <div class="tut-img">
    <img src="<?php echo $row['img']?>" width="100" height="100" alt="<?php echo $row['title']?>" />

    <div class="drag-label"></div>
    </div>

    <div class="tut-title">

    <a href="<?php echo $row['url']?>" target="_blank" title="Open it in a new window!"><?php echo $row['title']?></a>

    </div>
    <div class="tut-description"><?php echo $row['description']?></div>

    <div class="clear"></div>
    </div>
    </li>
    <?php }  ?>

</ul>

<div class="button-holder">
<?php if(!$voted):?><a href="" id="submitPoll" class="button">Submit Poll<span></span></a><?php endif;?>
<a href="?results" class="button">View The Results<span></span></a>
</div>

<?php
}
else require "results.php";
// The above require saves us from having to create another separate page

Una vez que el usuario haya reorganizado las entradas y enviado el formulario, resultados.php se incluye dinámicamente en la página con el uso de requerir función.

resultados.php

// If the poll has been submitted:

if($_POST['sortdata'])
{
    // The data arrives as a comma-separated string,
    // so we extract each post ids:

    $data=explode(',',$_POST['sortdata']);

    // Getting the number of objects
    list($tot_objects) = mysql_fetch_array(mysql_query("SELECT COUNT(*) FROM sort_objects"));

    if(count($data)!=$tot_objects) die("Wrong data!");

    foreach($data as $k=>$v)
    {
        // Building the sql query:
        $str[]='('.(int)$v.','.($tot_objects-$k).')';
    }

    $str = 'VALUES'.join(',',$str);

// This will limit voting to once a day per IP:
mysql_query("   INSERT INTO `sort_votes` (ip,date_submit,dt_submit)
        VALUES ('".$_SERVER['REMOTE_ADDR']."',NOW(),NOW())");

//  If the user has not voted before today:
    if(mysql_affected_rows($link)==1)
    {
        mysql_query('   INSERT INTO `sort_objects` (id,votes) '.$str.'
                ON DUPLICATE KEY UPDATE votes = votes+VALUES(votes)');
    }

}

//  Selecting the sample tutorials and ordering
//  them by the votes each of them received:

$res = mysql_query("SELECT * FROM sort_objects ORDER BY votes DESC");

$maxVote=0;
$bars=array();
while($row=mysql_fetch_assoc($res))
{
    $bars[]=$row;

    // Storing the max vote, so we can scale the bars of the chart:
    if($row['votes']>$maxVote) $maxVote = $row['votes'];
}

$barstr='';

// The colors of the bars:
$colors=array('#ff9900','#66cc00','#3399cc','#dd0000','#800080');

foreach($bars as $k=>$v)
{
    // Buildling the bar string:
    $barstr.='
    <div class="bar" style="width:'.max((int)(($v['votes']/$maxVote)*450),100).'px;background:'.$colors[$k].'">
        <a href="'.$v['url'].'" title="'.$v['title'].'">'.$v['short'].'</a>
    </div>';
}

// The total number of votes cast in the poll:

list($totVotes) = mysql_fetch_array(mysql_query("SELECT COUNT(*) FROM sort_votes"));

Después de enviar la encuesta, este script extrae el id s de las entradas clasificables y agrega de 1 a 5 votos a cada una, dependiendo de su posición. Posteriormente se añaden los nuevos votos a los sort_objects mesa.

Es importante que los usuarios puedan votar solo una vez al día. Es por eso que insertamos una nueva fila en sort_votes tabla cada vez que un usuario envía el formulario.

Lo especial de esta tabla es que tiene una clave única definida en el campo ip y fecha. Esto significa que MySQL arrojará un error si intentamos insertar una fila duplicada en la tabla y, por lo tanto, limitar los votos por IP.

Otra cosa mencionada anteriormente es cómo generamos las barras. Puede ver que asignamos dos propiedades CSS en el atributo de estilo de las barras:un ancho y un fondo color. Se asignan dinámicamente según el número de votos, como puede ver en la línea 59.

Más tarde, el $barstr generado la variable se muestra en la página y el gráfico está completo.

Paso 4 - jQuery

Antes de poder usar jQuery, debemos incluir todos los archivos necesarios. En este tutorial, usamos tanto jQuery biblioteca y jQuery UI (para la lista ordenable), por lo que los incluimos a ambos, así como nuestro propio script.js personalizado archivo y la hoja de estilo.

demo.php

<link rel="stylesheet" type="text/css" href="demo.css" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"></script>
<script type="text/javascript" src="script.js"></script>

Bien, pero ¿qué es esta lista ordenable de la que he estado hablando?

Este es un componente especial de la interfaz de usuario de jQuery (toda la interfaz de usuario de jQuery se enfoca en las interfaces de usuario y es una adición a la biblioteca principal de jQuery), que permite al desarrollador convertir cualquier lista ordenada o desordenada (OL o UL) en un usuario que se puede arrastrar y clasificar. componente de interfaz. La biblioteca también proporciona métodos para obtener el orden de los elementos en JavaScript, que luego puede usar en su aplicación.

Bastante ordenado en realidad.

Ahora veamos cómo funciona esto.

secuencia de comandos.js

$(document).ready(function(){
    // Executed once all the page elements are loaded

    // Convert the UL with all the tutorials into a sortable list:
    $("ul.sort").sortable({
        handle : '.tut-img', // We provide the thumbnails as drag handles
        axis:'y',
        containment: 'document', // The elements cannot be dragged outside the document
        opacity: 0.6
    });

    // The hover method takes a mouseover and a mouseout function:
    $(".tut").hover(
        function(){
            $(this).find('.drag-label').stop().animate({marginTop:'-25px'},'fast');
        },
        function(){
            $(this).find('.drag-label').stop().animate({marginTop:'0'},'fast');
        }
    );

    // Binding an action to the submitPoll button:
    $('#submitPoll').click(function(e){

        // We then turn the sortable into a comma-separated string
        // and assign it to the sortdata hidden form field:
        $('#sortdata').val($('ul.sort').sortable('toArray').join(','));

        // After this we submit the form:
        $('#sform').submit();

        // Preventing the default action triggered by clicking on the link
        e.preventDefault();
    });

});

Sí, es así de simple:solo use sortable() método con algunas opciones y listo.

Luego simplemente tomamos el orden de clasificación de los elementos con sortable('toArray') . Lo que esto hace es devolver todos los id s de los elementos de la lista en el orden en que están ordenados.

Cuando submitPoll se presiona el botón, tomamos los datos del método mencionado anteriormente, los unimos en una cadena y los asignamos a sortdata campo en el formulario formulario que luego se envía a results.php .

Paso 5:MySQL

Si planea ejecutar esta demostración por su cuenta, asegúrese de crear los sort_votes y ordenar_objetos tablas en una base de datos MySQL, y luego complete los detalles de su conexión en connect.php .

Puede ejecutar el código desde tables.sql en su administrador de base de datos favorito (por ejemplo, PHPMyAdmin) y las dos tablas se crearán automáticamente.

¡Con esto, nuestra encuesta de clasificación y votación arrastrable está completa!

Conclusión

Hoy usamos jQuery y el método ordenable, creamos un gráfico elegante con solo un poco de PHP y CSS y demostramos algunas interacciones interesantes con la base de datos.

Eres libre de usar el código resultante en tus propios sitios. El script se puede modificar fácilmente para adaptarse a casi cualquier necesidad.

También asegúrese de consultar nuestro feed de Twitter:de vez en cuando compartimos enlaces a cosas increíbles creadas por la comunidad e inspiradas en nuestros tutoriales.