Cotizaciones de lujo con jQuery, AJAX y CSS

Hoy estamos creando un elegante sistema de calificación de citas que mostrará una serie de citas famosas y permitirá a los visitantes de nuestro sitio calificar sus favoritas.

Estamos usando PHP y MySQL en el back-end y jQuery y interfaz de usuario de jQuery en el frente.

Además, estamos usando dos complementos de jQuery:qTip para obtener consejos sofisticados y el complemento Star Rating para obtener excelentes calificaciones basadas en estrellas para cada cita.

En el proceso también estamos implementando un reemplazo dinámico de fuentes con Cufon.

Así que adelante, tome el archivo de descarga y continúe con el paso uno.

Paso 1 - XHTML

Como de costumbre, comenzamos con la parte XHTML del tut. El sistema de cotizaciones se divide en dos:la parte izquierda, que es una especie de "vista completa " modo para la cita, que presenta un hermoso reemplazo de fuente con Cufon, y la parte derecha, que muestra las citas en una navegación o "miniatura modo ".

Puedes ver el código a continuación.

demo.php

<div id="main">
<div id="box">    <!-- Holds the full view of the quote -->

<div id="topPart">    <!-- The top part of the view -->

<div id="quote-content">  <!-- The quote text and author -->
<h1 class="quote"></h1>
<span id="author"></span>
</div>

</div>

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

<div id="quotes-list">    <!-- The quote list on the right, scrollable on mouse move -->
<div id="quotes-hide">
<div id="quotes-slide">

<?php
// Outputting the list
echo $str;
?>

</div>
</div>
</div>

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

El marcado es bastante sencillo. Definimos la estructura principal del sistema de calificación.

En las líneas 21-24 hacemos eco de las comillas, contenidas en el $str variables PHP. Volveremos a esto en unos momentos.

Ahora echemos un vistazo más de cerca al estilo.

Paso 2:CSS

Como el código es demasiado largo para una sola toma, lo he dividido en dos partes. También eliminé algunos de los estilos que el sistema de cotizaciones no utiliza directamente. Puede verlos en los archivos de demostración.

demo.css - Parte 1

#box{
    /* This holds the full view of the quote */
    background:url(img/mid_part.png) repeat-y;
    width:574px;
    margin:10px auto;
    float:left;
}

#topPart{
    /* Positioned inside the #box div, holds the top part of the view */
    background:url(img/top_part.png) no-repeat;

    min-height:195px;

    /* Providing height for browsers that do not support min-height (e.g. IE6) */
    height:195px;

    float:left;
    margin-top:-10px;
    width:100%;
    padding-top:20px;
}

div > #topPart{
    /* Setting the height to auto for non-IE6 browsers */
    height:auto;
}

#botPart{
    /* Bottom part of the full view */
    background:url(img/bot_part.png) no-repeat;
    height:24px;
    float:left;
    width:100%;
    margin-bottom:-10px;
}

h1.quote{
    /* This is the text of the quote in the full view. Replaced by Cufon */
    font-size:45px;
    color:#616161;
    text-align:right;
    padding:15px 40px 0 40px;
    line-height:60px;
}

#author{
    /* The span that holds the name of the author */
    color:#9C9C9C;
    float:right;
    font-size:14px;
    font-style:italic;
    font-weight:bold;
    letter-spacing:1px;
    margin-right:40px;
    text-transform:uppercase;
}

Aunque recientemente dejé de soportar IE6 en mis trabajos, decidí hacer una excepción esta vez, principalmente porque lo único que se necesita para que funcione en esa versión son dos líneas de código.

Como habrá escuchado, IE6 no es compatible con min-height propiedad. También interpreta incorrectamente altura como especificando la altura mínima.

Es por eso que proporciono ambos en #topPart reglas y luego establezca la altura en automático para los navegadores que admiten > Selección de CSS. Como IE6 no entiende este operador, se queda con una altura que se comporta como min-height e ignora la original.

demo.css - Parte 2

#quotes-list{
    /* The list on the right */
    background:#444444 none repeat scroll 0 0;
    border:1px solid #333333;
    float:left;
    margin-left:50px;
    padding-top:10px;
    width:230px;
    height:350px;
    overflow:hidden;
}

#quotes-hide{
    /* Positioned inside #quotes-list, but a 15px smaller */
    height:335px;
    overflow:hidden;
}

.star-rating{
    margin-top:2px;
}

.thumb{
    /* Each quote that is positioned in the list on the right of the page */
    background:url(img/top_part.png) no-repeat 50% 70%;
    color:#777777;
    font-size:16px;
    font-weight:bold;
    height:40px;
    margin:0 10px 15px;
    overflow:hidden;
    padding:15px;
    width:180px;
    cursor:pointer;
    text-align:left;
}

.thumb:hover{
    background:white;
}

#quotes-list,.thumb,p.tut{
    /* Using CSS3 rounded corners */
    -moz-border-radius:6px;
    -webkit-border-radius:6px;
    border-radius:6px;
}

.points{
    /* The points next to the quote title */
    color:#999999;
    font-size:12px;
    font-weight:normal;
}

La segunda parte del código diseña la lista deslizante del lado derecho. Todas las comillas se colocan una tras otra y desbordan su contenedor principal. Luego, establecer el desbordamiento en oculto oculta aquellos que no encajan y estamos listos para usar jQuery para codificar esa elegante interactividad del movimiento del mouse. Volveremos a esto en la parte de jQuery.

Ahora podemos continuar con el siguiente paso.

Paso 3 - PHP

PHP genera la lista de cotizaciones ejecutando una consulta SQL en la base de datos y seleccionando todas las cotizaciones. Estos datos también se pasan al front-end de JavaScript con la ayuda de fillData() Función JS.

demo.php

// Error reporting
error_reporting(E_ALL^E_NOTICE);

// Including file for the DB connection:
define("INCLUDE_CHECK",1);
require 'connect.php';
require 'functions.php';

// Converting the visitor's IP to a long int:
$ip = ip2long($_SERVER['REMOTE_ADDR']);

$today = date("Y-m-d");

// Selecting the quotes and LEFT JOIN-ing them to the votes:

$result = mysql_query("
SELECT q.*, IF(v.id,1,0) AS voted
FROM quotes AS q
LEFT JOIN quotes_votes AS v
    ON  q.id = v.qid
    AND v.ip =".$ip."
    AND v.date_submit = '".$today."'
");

$i=1;
$str='';
$script='';

while($row=mysql_fetch_assoc($result))
{
    // Looping through all the quotes and generating the list on the right of the page:
    $str.= '<div class="thumb" id="q-'.$i.'">'.substr($row['txt'],0,20).
    '<span class="points">...</span><div class="star-rating" id="rating-'.$i.'">';

    $row['rating'] = round($row['rating']);
    for($z=0;$z<5;$z++)
    {
        $str.='<input type="radio" name="rate-'.$i.'" value="'.($z+1).'" '.($z+1==$row['rating']?'checked="checked"':'').' disabled="disabled" />';
    }

    $str.='</div></div>';

    // Each quote calls the fillData JS function
    $script.="fillData(".formatJSON($row).");".PHP_EOL;

    $i++;
}

El $str Luego, la variable se envía a la página, como vio en el primer paso.

PHP también maneja la votación de las cotizaciones. Puede ver el código desde vote.php a continuación.

votar.php

// Error reporting
error_reporting(E_ALL^E_NOTICE);

define("INCLUDE_CHECK",1);
require "connect.php";

if(!$_POST['qid'] || !$_POST['vote']) die('0');

/* Converting the visitor's IP into a long int: */
$ip = ip2long($_SERVER['REMOTE_ADDR']);

/* Converting the parameters to int will prevent any malpractices */
$qid = (int)$_POST['qid'];
$v = (int)$_POST['vote'];

/* Inserting the vote in the votes DB */
mysql_query('   INSERT INTO quotes_votes (qid,ip,vote,date_submit)
                VALUES ('.$qid.','.$ip.','.$v.',CURDATE())');

/* There is an unique index set up that prevents duplicate votes */
if(mysql_affected_rows($link)==1)
{
    mysql_query("UPDATE quotes SET votes=votes+1, vsum=vsum+".$v.", rating=vsum/votes WHERE id=".$qid);
    echo'1';
}
else echo '0';

El script genera 1 en éxito y 0 sobre el fracaso JQuery lo usa más tarde para decidir si la votación fue exitosa. Esto nos lleva al siguiente paso.

Paso 4 - jQuery

jQuery maneja todas las interacciones del usuario con el sistema de clasificación de cotizaciones. Muestra la cita a la vista, emite el reemplazo de las fuentes con Cufon y maneja el proceso de votación.

Antes de poder usar la biblioteca jQuery, debemos incluir algunos archivos en la página.

<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="star-rating/ui.stars.min.js"></script>
<script type="text/javascript" src="q-tip/jquery.qtip-1.0.0-rc3.min.js"></script>
<script src="cufon/cufon-yui.js" type="text/javascript"></script>
<script src="cufon/ChunkFive_400.font.js" type="text/javascript"></script>

<script type="text/javascript">
Cufon.replace('h1.quote');
</script>

<script type="text/javascript" src="script.js"></script>

<script type="text/javascript">
<!-- Outputting the JS generated on the PHP-side -->
<?php echo $script ?>
</script>

Las dos primeras líneas incluyen jQuery biblioteca y jQuery UI (una adición a jQuery para componentes de interfaz) en la página. Después de esto, incluimos el complemento Star Rating , qConsejo , y el Cufón reemplazo de texto junto con la fuente convertida ChunkFive.

Ahora echemos un vistazo a script.js , que contiene todo nuestro JavaScript.

Debido a la longitud del código, lo he dividido en tres partes.

script.js - Parte 1

$(document).ready(function(){
    /* Executed on DOM load */

    $(".star-rating").stars();
    /* Converts all the radio groups into star ratings */

    $("#quotes-hide").mousemove(function(e){

        /* The scrollable quote container */

        if(!this.hideDiv)
        {
            /* These variables are initialized only the first time the function is run: */
            this.hideDiv = $(this);
            this.scrollDiv = $('#quotes-slide');
            this.pos = this.hideDiv.offset();

            this.pos.top+=20;
            /* Adding a 20px offset, so that the scrolling begins 20px from the top */

            this.slideHeight = this.scrollDiv.height();
            this.height = this.hideDiv.height();
            this.height-=20;
            /* Adding a bottom offset */

            this.totScroll = this.slideHeight-this.height;
        }

        this.scrollDiv.css({

            /* Remember that this.scrollDiv is a jQuery object, as initilised above */
            marginTop:'-'+this.totScroll*(Math.max(e.pageY-this.pos.top,0)/this.height)+'px'

            /* Assigning a negative top margin according to the position of the mouse cursor, passed
            with e.pageY; It is relative to the page, so we substract the position of the scroll container */
        });
    });

    $('.thumb').click(function(e){
        /* Executed once a quote from the list on the right is clicked */

        var obj = quotes[parseInt(e.target.id.replace('q-',''))-1];
        /* The e.target.id of the quote corresponds to its position in the quotes array */

        $('#quote-content').fadeOut('fast',function(){
            /* This is a callback function, run once the quote container on the left has faded out */

            if(!obj) return false;

            /* Replacing the contents of the quote text and author */
            $(this).find('h1').html(obj.txt);
            $(this).find('span').html(obj.author);

            /* Changing the background color: */
            if(obj.bgc) $('body').stop().animate({backgroundColor:obj.bgc},'slow');

            /* Generating the radio boxes for the tool-tip star rating */
            var tmpstr='';
            for(var z=0;z<5;z++)
            {
                tmpstr+='<input type="radio" name="voteQ" value="'+(z+1)+'" ';
                if(z+1==obj.rating) tmpstr+='checked=checked ';
                if(parseInt(obj.voted)) tmpstr+='disabled="disabled" ';
                tmpstr+='/>';
            }

            tmpstr='<div id="voteRating">'+tmpstr+'</div>';

            /* Updating the content of the tool-tip and converting it to a star rating */
            $('#box').qtip("api").updateContent(tmpstr);

            $('#voteRating').stars({
                cancelShow: false,
                oneVoteOnly: true,
                callback:function(ui, type, value){vote(obj,value);}
            });

            /* Regenerating the cufon text replacement for the new quote text on the left */
            Cufon.refresh();

            /* Show the new quote with a fade-in effect */

            $(this).fadeIn('fast');
        });
    });

Primero enlazamos un movimiento de ratón evento con el DIV con quotes-hide identificación. Dentro de la función de devolución de llamada, el contenedor se desplaza con la ayuda de un margen superior negativo. De esta manera ahorramos mucho espacio en la página y brindamos una buena interactividad.

A continuación, configuramos un clic controlador de eventos en los pulgares, que muestra la cita adecuada en la vista.

script.js - Parte 2

  /* Creating and configuring the tool-tip with the help
    of the qtip plugin: */
    $('#box').qtip({
        content: {
            text:'This is an active list element',
            title: { text: 'Vote for this quote'},
            prerender:true
        },
        show: 'mouseover',
        hide: {
            delay:1000,
            fixed:true,
            when:'mouseout'
        },
        position: {
            corner: {
                target: 'bottomMiddle',
                tooltip: 'topMiddle'
            },
            adjust:{
                y:20
            }
        },
        style: {
            border: {
                width: 2,
                radius: 6
            },
            name:'light',
            tip: 'topMiddle'
        }
    });

    /* After the page has loaded, click the first quote on the right */
    setTimeout(function(){$('#q-1').click();},250);
});

En la segunda parte del código, estamos configurando el qTip enchufar. Proporciona innumerables opciones y personalizaciones, por lo que sería una buena idea tener la documentación lista si planea modificar el código. Puede consultar la página de inicio del complemento para obtener más información.

También emitimos un clic en la primera cotización, para que la vista no esté vacía al cargar la página.

script.js - Parte 3

/* The global array holding all the data about the quotes.
Filled in on page load. */
var quotes = new Array();
function fillData(obj)
{
    quotes.push(obj);
}

function vote(ob,value)
{
    /* Sending the votes to vote.php */
    $.post('vote.php',{qid:ob.id,vote:value},function(data){

        if(data=="1")
        {
            /* If the vote was saved successfully, update the quote data.. */
            ob.voted=1;
            ob.votes=ob.votes+1;
            ob.vsum=ob.vsum+parseInt(value);
            ob.rating = Math.round(ob.vsum/ob.votes);

            /* ..and update the star rating */
            $('#rating-'+ob.id).stars("select", ob.rating);
            quotes[ob.id-1]=ob;
        }
    });
}

La primera función - fillData() toma un objeto JavaScript como parámetro y lo agrega a la matriz de comillas para su uso posterior.

Como recordará, en el paso de PHP convertimos la $fila matrices, devueltas por mysql_fetch_array , a objetos JSON con nuestro formatJSON() personalizado y los encerró en una llamada a la función fillData.

Esto luego se genera como código JS que se ejecuta antes de document.ready() , y como resultado tenemos todos los datos sobre las comillas disponibles para jQuery en la matriz de comillas .

La segunda función maneja las solicitudes AJAX a vote.php y actualiza la interfaz si es necesario.

Paso 5:MySQL

Si planea ejecutar esta demostración por su cuenta, deberá crear las tablas ejecutando el código SQL en tables.sql en su servidor (puede hacerlo a través de la interfaz phpMyAdmin).

También deberá completar sus credenciales de MySQL en connect.php .

¡Con esto, nuestro elegante administrador de cotizaciones está completo!

Conclusión

Hoy creamos un elegante sistema de administración de cotizaciones y aprendimos un par de cosas sobre información sobre herramientas, reemplazos de fuentes, AJAX, PHP y mucho más.

Puede descargar y utilizar la demostración en sus propios sitios, modificándola como mejor le parezca.

Además, si te gustó este tutorial, asegúrate de suscribirte a nuestro canal RSS o síguenos en Twitter.