Fancy Quotes With jQuery, AJAX & CSS

22 January 2010 Friday

This application was viewed 840 times




Fancy Quotes With jQuery, AJAX & CSS

Today we are making a fancy quote rating system that will display a number of famous quotes and will enable our site visitors to rate their favorites.

We are using PHP and MySQL on the back-end and jQuery and jQuery UI on the front.

As an addition, we are using two jQuery plugins – qTip for fancy tips and the Star Rating plugin for great looking star-based ratings for each quote.

In the process we are also implementing a dynamic font replacement with Cufon.

So go ahead, grab the download archive and continue with step one.

View The DEMO

Step 1 – XHTML

As usual, we start with the XHTML part of the tut. The quote system is divided in two – the left part, which is a sort of a “full view” mode for the quote, featuring a beautiful font replacement with Cufon, and the right part, which shows the quotes in a browse or “thumbnail” mode.

You can see the code below.

demo.php

01.<div id="main">
02.<div id="box">    <!-- Holds the full view of the quote -->
03.  
04.<div id="topPart">    <!-- The top part of the view -->
05.  
06.<div id="quote-content"<!-- The quote text and author -->
07.<h1 class="quote"></h1>
08.<span id="author"></span>
09.</div>
10.  
11.</div>
12.  
13.<div id="botPart"></div>
14.<div class="clear"></div>
15.</div>
16.  
17.<div id="quotes-list">    <!-- The quote list on the right, scrollable on mouse move -->
18.<div id="quotes-hide">
19.<div id="quotes-slide">
20.  
21.<?php
22.// Outputting the list
23.echo $str;
24.?>
25.  
26.</div>
27.</div>
28.</div>
29.  
30.<div class="clear"></div>
31.</div>

The markup is pretty straightforward. We define the main structure of the rating system.

On lines 21-24 we echo the quotes, contained in the $str PHP variable. We will come back to this in a few moments.

Now lets take a closer look at the styling.

Step 2 – CSS

Because the code is too long for a single take, I’ve divided it into two parts. I’ve also removed some of the styles that are not directly used by the quote system. You can view those in the demo files.

demo.css – Part 1

01.#box{
02.    /* This holds the full view of the quote */
03.    background:url(img/mid_part.png) repeat-y;
04.    width:574px;
05.    margin:10px auto;
06.    float:left;
07.}
08.  
09.#topPart{
10.    /* Positioned inside the #box div, holds the top part of the view */
11.    background:url(img/top_part.png) no-repeat;
12.  
13.    min-height:195px;
14.  
15.    /* Providing height for browsers that do not support min-height (e.g. IE6) */
16.    height:195px;
17.  
18.    float:left;
19.    margin-top:-10px;
20.    width:100%;
21.    padding-top:20px;
22.}
23.  
24.div > #topPart{
25.    /* Setting the height to auto for non-IE6 browsers */
26.    height:auto;
27.}
28.  
29.#botPart{
30.    /* Bottom part of the full view */
31.    background:url(img/bot_part.png) no-repeat;
32.    height:24px;
33.    float:left;
34.    width:100%;
35.    margin-bottom:-10px;
36.}
37.  
38.h1.quote{
39.    /* This is the text of the quote in the full view. Replaced by Cufon */
40.    font-size:45px;
41.    color:#616161;
42.    text-align:right;
43.    padding:15px 40px 0 40px;
44.    line-height:60px;
45.}
46.  
47.#author{
48.    /* The span that holds the name of the author */
49.    color:#9C9C9C;
50.    float:right;
51.    font-size:14px;
52.    font-style:italic;
53.    font-weight:bold;
54.    letter-spacing:1px;
55.    margin-right:40px;
56.    text-transform:uppercase;
57.}

Although I recently stopped supporting IE6 in my works, I decided to make an exception this time, mainly because the only thing needed for it to work in that version are two lines of code.

As you may have heard, IE6 does not support the min-height property. It also incorrectly interprets height as specifying minimum height.

This is why I provide both in the #topPart rules and later set height to auto for browsers that support the > CSS selector. As IE6 does  not understand this operator, it is left with a height behaving like min-height and ignoring the original one.

demo.css – Part 2

01.#quotes-list{
02.    /* The list on the right */
03.    background:#444444 none repeat scroll 0 0;
04.    border:1px solid #333333;
05.    float:left;
06.    margin-left:50px;
07.    padding-top:10px;
08.    width:230px;
09.    height:350px;
10.    overflow:hidden;
11.}
12.  
13.#quotes-hide{
14.    /* Positioned inside #quotes-list, but a 15px smaller */
15.    height:335px;
16.    overflow:hidden;
17.}
18.  
19..star-rating{
20.    margin-top:2px;
21.}
22.  
23..thumb{
24.    /* Each quote that is positioned in the list on the right of the page */
25.    background:url(img/top_part.png) no-repeat 50% 70%;
26.    color:#777777;
27.    font-size:16px;
28.    font-weight:bold;
29.    height:40px;
30.    margin:0 10px 15px;
31.    overflow:hidden;
32.    padding:15px;
33.    width:180px;
34.    cursor:pointer;
35.    text-align:left;
36.}
37.  
38..thumb:hover{
39.    background:white;
40.}
41.  
42.#quotes-list,.thumb,p.tut{
43.    /* Using CSS3 rounded corners */
44.    -moz-border-radius:6px;
45.    -webkit-border-radius:6px;
46.    border-radius:6px;
47.}
48.  
49..points{
50.    /* The points next to the quote title */
51.    color:#999999;
52.    font-size:12px;
53.    font-weight:normal;
54.}

The second part of the code styles the sliding list on the right side. All the quotes are positioned one after another and they overflow their parent container. Then, setting overflow to hidden hides those that do not fit and we are ready to use jQuery to code that fancy mousemove interactivity. We will come back to this in the jQuery part.

Now we can continue with the next step.

Step 3 – PHP

PHP generates the quote list by running an SQL query against the database, and selecting all the quotes. This data is also passed to the JavaScript front end with the help of the fillData() JS function.

demo.php

01.// Error reporting
02.error_reporting(E_ALL^E_NOTICE);
03.  
04.// Including file for the DB connection:
05.define("INCLUDE_CHECK",1);
06.require ´connect.php´;
07.require ´functions.php´;
08.  
09.// Converting the visitor´s IP to a long int:
10.$ip = ip2long($_SERVER[´REMOTE_ADDR´]);
11.  
12.$today = date("Y-m-d");
13.  
14.// Selecting the quotes and LEFT JOIN-ing them to the votes:
15.  
16.$result = mysql_query("
17.SELECT q.*, IF(v.id,1,0) AS voted
18.FROM quotes AS q
19.LEFT JOIN quotes_votes AS v
20.    ON  q.id = v.qid
21.    AND v.ip =".$ip."
22.    AND v.date_submit = ´".$today."´
23.");
24.  
25.$i=1;
26.$str=´´;
27.$script=´´;
28.  
29.while($row=mysql_fetch_assoc($result))
30.{
31.    // Looping through all the quotes and generating the list on the right of the page:
32.    $str.= ´<div class="thumb" id="q-´.$i.´">´.substr($row[´txt´],0,20).
33.    ´<span class="points">...</span><div class="star-rating" id="rating-´.$i.´">´;
34.  
35.    $row[´rating´] = round($row[´rating´]);
36.    for($z=0;$z<5;$z++)
37.    {
38.        $str.=´<input type="radio" name="rate-´.$i.´" value="´.($z+1).´" ´.($z+1==$row[´rating´]?´checked="checked"´:´´).´ disabled="disabled" />´;
39.    }
40.  
41.    $str.=´</div></div>´;
42.  
43.    // Each quote calls the fillData JS function
44.    $script.="fillData(".formatJSON($row).");".PHP_EOL;
45.  
46.    $i++;
47.}

The $str variable is then outputted to the page, as you saw in the first step.

PHP also handles the voting for the quotes. You can view the code from vote.php below.

vote.php

01.// Error reporting
02.error_reporting(E_ALL^E_NOTICE);
03.  
04.define("INCLUDE_CHECK",1);
05.require "connect.php";
06.  
07.if(!$_POST[´qid´] || !$_POST[´vote´]) die(´0´);
08.  
09./* Converting the visitor´s IP into a long int: */
10.$ip = ip2long($_SERVER[´REMOTE_ADDR´]);
11.  
12./* Converting the parameters to int will prevent any malpractices */
13.$qid = (int)$_POST[´qid´];
14.$v = (int)$_POST[´vote´];
15.  
16./* Inserting the vote in the votes DB */
17.mysql_query(´   INSERT INTO quotes_votes (qid,ip,vote,date_submit)
18.                VALUES (´.$qid.´,´.$ip.´,´.$v.´,CURDATE())´);
19.  
20./* There is an unique index set up that prevents duplicate votes */
21.if(mysql_affected_rows($link)==1)
22.{
23.    mysql_query("UPDATE quotes SET votes=votes+1, vsum=vsum+".$v.", rating=vsum/votes WHERE id=".$qid);
24.    echo´1´;
25.}
26.else echo ´0´;

The script outputs 1 on success and 0 on failure. This is later used by jQuery to decide whether voting was successful. This brings us to the next step.

Step 4 – jQuery

jQuery handles all the user interactions with the quote rating system. It shows the quote in full view, issues the replacement of the fonts with Cufon and handles the voting process.

Before being able to use the jQuery library, we have to include a few files in the page.

01.<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
02.<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"></script>
03.<script type="text/javascript" src="star-rating/ui.stars.min.js"></script>
04.<script type="text/javascript" src="q-tip/jquery.qtip-1.0.0-rc3.min.js"></script>
05.<script src="cufon/cufon-yui.js" type="text/javascript"></script>
06.<script src="cufon/ChunkFive_400.font.js" type="text/javascript"></script>
07.  
08.<script type="text/javascript">
09.Cufon.replace(´h1.quote´);
10.</script>
11.  
12.<script type="text/javascript" src="script.js"></script>
13.  
14.<script type="text/javascript">

15.<!-- Outputting the JS generated on the PHP-side -->

16.<?php echo $script ?>
17.</script>

The first two lines include the jQuery library and jQuery UI (an addition to jQuery for interface components) in the page. After this we include the Star Rating plugin, qTip, and the Cufon text replacement along with the ChunkFive converted font.

Now lets take a look at script.js, which holds all of our JavaScript.

Because of the length of the code, I’ve divided it into three parts.

script.js – Part 1

01.$(document).ready(function(){
02.    /* Executed on DOM load */
03.  
04.    $(".star-rating").stars();
05.    /* Converts all the radio groups into star ratings */
06.  
07.    $("#quotes-hide").mousemove(function(e){
08.  
09.        /* The scrollable quote container */
10.  
11.        if(!this.hideDiv)
12.        {
13.            /* These variables are initialized only the first time the function is run: */
14.            this.hideDiv = $(this);
15.            this.scrollDiv = $(´#quotes-slide´);
16.            this.pos = this.hideDiv.offset();
17.  
18.            this.pos.top+=20;
19.            /* Adding a 20px offset, so that the scrolling begins 20px from the top */
20.  
21.            this.slideHeight = this.scrollDiv.height();
22.            this.height = this.hideDiv.height();
23.            this.height-=20;
24.            /* Adding a bottom offset */
25.  
26.            this.totScroll = this.slideHeight-this.height;
27.        }
28.  
29.        this.scrollDiv.css({
30.  
31.            /* Remember that this.scrollDiv is a jQuery object, as initilised above */
32.            marginTop:´-´+this.totScroll*(Math.max(e.pageY-this.pos.top,0)/this.height)+´px´
33.  
34.            /* Assigning a negative top margin according to the position of the mouse cursor, passed
35.            with e.pageY; It is relative to the page, so we substract the position of the scroll container */
36.        });
37.    });
38.  
39.    $(´.thumb´).click(function(e){
40.        /* Executed once a quote from the list on the right is clicked */
41.  
42.        var obj = quotes[parseInt(e.target.id.replace(´q-´,´´))-1];
43.        /* The e.target.id of the quote corresponds to its position in the quotes array */
44.  
45.        $(´#quote-content´).fadeOut(´fast´,function(){
46.            /* This is a callback function, run once the quote container on the left has faded out */
47.  
48.            if(!obj) return false;
49.  
50.            /* Replacing the contents of the quote text and author */
51.            $(this).find(´h1´).html(obj.txt);
52.            $(this).find(´span´).html(obj.author);
53.  
54.            /* Changing the background color: */
55.            if(obj.bgc) $(´body´).stop().animate({backgroundColor:obj.bgc},´slow´);
56.  
57.            /* Generating the radio boxes for the tool-tip star rating */
58.            var tmpstr=´´;
59.            for(var z=0;z<5;z++)
60.            {
61.                tmpstr+=´<input type="radio" name="voteQ" value="´+(z+1)+´" ´;
62.                if(z+1==obj.rating) tmpstr+=´checked=checked ´;
63.                if(parseInt(obj.voted)) tmpstr+=´disabled="disabled" ´;
64.                tmpstr+=´/>´;
65.            }
66.  
67.            tmpstr=´<div id="voteRating">´+tmpstr+´</div>´;
68.  
69.            /* Updating the content of the tool-tip and converting it to a star rating */
70.            $(´#box´).qtip("api").updateContent(tmpstr);
71.  
72.            $(´#voteRating´).stars({
73.                cancelShow: false,
74.                oneVoteOnly: true,
75.                callback:function(ui, type, value){vote(obj,value);}
76.            });
77.  
78.            /* Regenerating the cufon text replacement for the new quote text on the left */
79.            Cufon.refresh();
80.  
81.            /* Show the new quote with a fade-in effect */
82.  
83.            $(this).fadeIn(´fast´);
84.        });
85.    });

First we bind a mousemove event with the DIV with a quotes-hide id. Inside the callback function, the container is scrolled with the help of a negative top margin. This way we save a lot of real estate on the page and provide a some nice interactivity.

Next we set up a click event handler on the thumbs, which shows the appropriate quote in the view.

script.js – Part 2

01.    /* Creating and configuring the tool-tip with the help
02.   of the qtip plugin: */
03.    $(´#box´).qtip({
04.        content: {
05.            text:´This is an active list element´,
06.            title: { text: ´Vote for this quote´},
07.            prerender:true
08.        },
09.        show: ´mouseover´,
10.        hide: {
11.            delay:1000,
12.            fixed:true,
13.            when:´mouseout´
14.        },
15.        position: {
16.            corner: {
17.                target: ´bottomMiddle´,
18.                tooltip: ´topMiddle´
19.            },
20.            adjust:{
21.                y:20
22.            }
23.        },
24.        style: {
25.            border: {
26.                width: 2,
27.                radius: 6
28.            },
29.            name:´light´,
30.            tip: ´topMiddle´
31.        }
32.    });
33.  
34.    /* After the page has loaded, click the first quote on the right */
35.    setTimeout(function(){$(´#q-1´).click();},250);
36.});

In the second part of the code, we are configuring the qTip plugin. It provides countless options and customizations, so it would be a good idea to have the documentation ready if you plan to modify the code. You can consult with the plugin’s homepage for more info.

Also we issue a click on the first quote, so that the view is not empty on page load.

script.js – Part 3

01./* The global array holding all the data about the quotes.
02.Filled in on page load. */
03.var quotes = new Array();
04.function fillData(obj)
05.{
06.    quotes.push(obj);
07.}
08.  
09.function vote(ob,value)
10.{
11.    /* Sending the votes to vote.php */
12.    $.post(´vote.php´,{qid:ob.id,vote:value},function(data){
13.  
14.        if(data=="1")
15.        {
16.            /* If the vote was saved successfully, update the quote data.. */
17.            ob.voted=1;
18.            ob.votes=ob.votes+1;
19.            ob.vsum=ob.vsum+parseInt(value);
20.            ob.rating = Math.round(ob.vsum/ob.votes);
21.  
22.            /* ..and update the star rating */
23.            $(´#rating-´+ob.id).stars("select", ob.rating);
24.            quotes[ob.id-1]=ob;
25.        }
26.    });
27.}

The first function – fillData() takes a JavaScript object as a parameter, and adds it to the quotes array for later use.

As you remember, in the PHP step we converted the $row arrays, returned by mysql_fetch_array, to JSON objects with our custom formatJSON() function and enclosed them in a fillData function call.

This is later outputted as JS code which is executed before document.ready(), and as a result we have all the data about the quotes available to jQuery in the quotes array.

The second function handles the AJAX requests to vote.php and updates the interface if necessary.

Step 5 – MySQL

If you plan to run this demo on your own, you’ll need to create the tables by executing the SQL code in tables.sql on your server (you can do this via the phpMyAdmin interface).

Also you’ll need to fill in your MySQL credentials in connect.php.

With this our fancy quote manager is complete!

Tags: jquery, ajax, css, quotes,


Fancy Quotes With jQuery, AJAX & CSSBookmark and Share

You write your thoughts

Please login to post comments here from the right corner.

your add
icon free icon icon set vector icon free catalog catalog template jquery news ticker widget tools tutorial php slider video youtube effects menu thumbnail forms facebook zoom image combo multiselect modal polaroid gallery expand code feedback contact navigation slider tagcloud Skateboard psd templates files badges subscribe panel login temlate file free office holland free template tabs prototype css scriptaculous opacity moo autocomplete wordpress themes design theme button images photoshop fonts font nav pdf logo style high javascript pretty photo jqery lightbox Themes Blog popular blog desing joomla xhtml brushes hair footer admin mootols slide show blackbox new download class first plugin upload browse Page effect modalbox web application urlitooltips sliding boxes captions flatchat chat ajax messaging browser hoverlightbox CSS Dev General Javascript PHP SQL search avatar vector Drupal Joomla Oscommerce javaScript phototype manager ajaxplorer flash xml rotator bookmarking pageflip slideshow poll text component script mediaplayer imagegallery pictograms car poster player mp3 radio onlineradio navigations drop-down collection brush tree textures paper pop-up bumpbox web2.0 iphone film frame twitter page fan mail delete dynamic calender form handbook city social paint timeline clock connect bar sharing accordion quotes ticker photo-effects background 3D media player graphic rss leaf green glossy bubble icon comic clean cool web 2.0 png actionscript ietter rotating Menu animated textured site masking pasword app layer sponge bob popup bubble tooltips horizontal prototip tooltip pack charachters comics blog action icon.psd flavour navi tango gradients istanbul mixed css3 sleek animations program html5 website Layer styles ultimate candy Media icons dropdown snow icon innerfade hover sub tag