Ajax Updates

Ajax Updates


Making a Really Cool jQuery Gallery

Posted: 06 Oct 2009 12:59 PM PDT

Introduction
One of the main benefits of using a popular java script library, such as jQuery, is the incredible number of available plug-ins that will kick-start any development project.

Today we are going to build a custom gallery that scans a folder of images and outputs a slick gallery, utilizing PHP, CSS, jQuery and the jQuery Lightbox plug-in.

There is no need to download the plug-in – I've included it in the demo files, so grab them and get on reading.

The XHTML

We start off with our XHTML front-end.

 <div id="container">  <div id="heading"> <!-- the heading --> <h1>A cool jQuery gallery</h1> </div> <div id="gallery"> <!-- this is the containing div for the images -->  < ?php //our php code goes here ?>  <div class="clear"></div> <!-- using clearfix --> </div>  <div id="footer"> <!-- some tutorial info --> </div>  </div> <!-- closing the container div --> 

And that is basically all there is to it. Note the highlighted area – this is where we put our PHP code, that will generate the gallery images. Now lets go through how this is done.

The PHP

The idea is simple – our PHP back-end is going to scan a folder that we've set up with our gallery images, and turn it into a fancy CSS & jQuery gallery. The great thing about this strategy is that it is incredibly easy to set up a gallery, and adding images to an existing one is a charm – just dump them in the gallery's directory via FTP and it is ready to go.

 $directory = 'gallery';	//where the gallery images are located  $allowed_types=array('jpg','jpeg','gif','png');	//allowed image types  $file_parts=array(); $ext=''; $title=''; $i=0;  //try to open the directory $dir_handle = @opendir($directory) or die("There is an error with your image directory!");  while ($file = readdir($dir_handle))	//traverse through the files { 	if($file=='.' || $file == '..') continue;	//skip links to the current and parent directories  	$file_parts = explode('.',$file);	//split the file name and put each part in an array 	$ext = strtolower(array_pop($file_parts));	//the last element is the extension  	$title = implode('.',$file_parts);	//once the extension has been popped out, all that is left is the file name 	$title = htmlspecialchars($title);	//make the filename html-safe to prevent potential security issues  	$nomargin=''; 	if(in_array($ext,$allowed_types))	//if the extension is an allowable type 	{ 		if(($i+1)%4==0) $nomargin='nomargin';	//the last image on the row is assigned the CSS class "nomargin" 		echo ' 		<div class="pic '.$nomargin.'" style="background:url('.$directory.'/'.$file.') no-repeat 50% 50%;"> 		<a href="'.$directory.'/'.$file.'" title="'.$title.'" target="_blank">'.$title.'</a> 		</div>';  		$i++;	//increment the image counter 	} }  closedir($dir_handle);	//close the directory 

By traversing through the files in the directory and skipping the non-image files, we output some XHTML code for every image . This code (lines 28-39) consists of a div container, with a CSS class pic (and in some cases a nomargin, more on that later), and we set its background to the image file via the style attribute. We position the image in the center of the background by specifying its position to be 50% 50%. This centers it both horizontally and vertically and thus shows only the middle part, that fits into the div container's size. This creates a nice thumbnail, with no need of actually resizing the image.

This works best with images with smaller resolutions, so you should consider resizing those 10 megapixel photos before uploading them.

The div contains a hyperlink which is linked to the image and has a title of the image filename. Both these attributes are used by the lightBox plugin to generate the lightbox gallery. So by renaming the file, you can change the caption that shows under it.

You may wonder what is the point of that nomargin class? Every image in the gallery has a right and a bottom margin. But this means that it is not possible the last element of each row to align with the right part of the heading div and it looks amateurish. So we assign this special class, which clears the right margin for the last element on each row and gives us a proper alignment.

Gallery

The CSS

Everything is set up, but we still have to give it that cool look.

 /* first reset some of the elements for browser compatibility */ body,h1,h2,h3,p,td,quote,small,form,input,ul,li,ol,label{ 	margin:0px; 	padding:0px; 	font-family:Arial, Helvetica, sans-serif; }  body{	/* style the body */ 	margin-top:20px; 	color:white; 	font-size:13px; 	background-color:#222222; }  .clear{	/* the clearfix class */ 	clear:both; }  a, a:visited {	/* a:visited is needed so it works properly in IE6 */ 	color:#00BBFF; 	text-decoration:none; 	outline:none; }  a:hover{	/* the hover effect */ 	text-decoration:underline; }  #container{	/* the main container div */ 	width:890px; 	margin:20px auto; }  #heading,#footer{	/* the header and the footer share some of their style rules */ 	background-color:#2A2A2A; 	border:1px solid #444444; 	height:20px; 	padding:6px 0 25px 15px; 	margin-bottom:30px; 	overflow:hidden; }  #footer{	/* ..but not all */ 	height:10px; 	margin:20px 0 20px 0; 	padding:6px 0 11px 15px; }  div.nomargin{	/* our special nomargin class */ 	margin-right:0px; }  .pic{	/* divs that hold all the pictures in the gallery */ 	float:left; 	margin:0 15px 15px 0; 	border:5px solid white; 	width:200px; 	height:250px; }  .pic a{	/* in every .pic container there is a hyperlink exactly the size of the container */ 	width:200px; 	height:250px; 	text-indent:-99999px; 	display:block;	/* don't forget that widths and heights of hyperlinks are useless without display:block */ }  h1{	/* style the heading */ 	font-size:28px; 	font-weight:bold; 	font-family:"Trebuchet MS",Arial, Helvetica, sans-serif; }  h2{	/* the footer text */ 	font-weight:normal; 	font-size:14px; 	color:white; } 

The jQuery

To make it all tick, we need to include the jQuery java script library in our page, and add the lightBox plugin. The following code was taken from the head section of demo.php:

 <link rel="stylesheet" type="text/css" href="lightbox/css/jquery.lightbox-0.5.css"> <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="lightbox/js/jquery.lightbox-0.5.pack.js"></script> <script type="text/javascript" src="script.js"></script> 

On line 1 we include the lightbox plugin's CSS file, which styles the lightbox that displays the images. On line 2 we include our own CSS file.

Line 4 is where we include the jQuery library from Google's CDN. Later come the lightbox plugin itself and our own script.js file.

Now we are ready to put the finishing touch.

 // after the page has finished loading $(document).ready(function(){  	$('.pic a').lightBox({ 	// we call the lightbox method, and convert all the hyperlinks in the .pic container into a lightbox gallery  		imageLoading: 'lightbox/images/loading.gif', 		imageBtnClose: 'lightbox/images/close.gif', 		imageBtnPrev: 'lightbox/images/prev.gif', 		imageBtnNext: 'lightbox/images/next.gif'  	});  }); 

The lighbox() method takes an object as an optional parameter. The only reason we provide any parameters is that I changed the default location of the plugin, putting it in a subfolder /lightbox which aids for a cleaner file structure. Unfortunately the images that the plug-in uses become inaccessible and have to be provided manually.

With this our gallery is complete.

Conclusion
In this tutorial you learned how to create a stylish image gallery with the help of the jQuery lightBox plug-in. You can use the example code into your projects and you are free to modify it in whatever manner you find appropriate. You can as well use it as is and add a gallery to your site with minimum modifications needed.






Demo: http://demo.tutorialzine.com/2009/09/cool-jquery-gallery/demo.php
Download: http://demo.tutorialzine.com/2009/09/cool-jquery-gallery/demo.zip
Source: http://tutorialzine.com/2009/09/cool-jquery-gallery/

Related Listings:

  1. EO Gallery-Jquery EOGallery is a web animated slideshow gallery maid with jQuery....
  2. jQuery Lightbox Plugin jQuery lightBox plugin is simple, elegant, unobtrusive, no need extra...
  3. Gallery Script with XML Parser The original gallery has been taken from http://www.aaronbirchphotography.com and updated...

An AJAX Based Shopping Cart with PHP, CSS and jQuery

Posted: 06 Oct 2009 12:03 PM PDT

Introduction
In this tutorial we are going to create an AJAX-driven shopping cart. All the products are going to be stored in a MySQL database, with PHP showing and processing the data.

jQuery will drive the AJAX-es on the page, and with the help of the simpletip plugin will add to an interactive check out process.
So go ahead, download the demo files and start reading.

Step 1 – The MySQL Database
If you want to set up a working demo, you'll need to execute the following SQL code in your database manager (e.g. phpMyAdmin). It will set up the table and insert a few products. The code is also available in table.sql in the demo files.

 CREATE TABLE IF NOT EXISTS `internet_shop` (   `id` int(6) NOT NULL auto_increment,   `img` varchar(32) collate utf8_unicode_ci NOT NULL default '',   `name` varchar(64) collate utf8_unicode_ci NOT NULL default '',   `description` text collate utf8_unicode_ci NOT NULL,   `price` double NOT NULL default '0',   PRIMARY KEY  (`id`),   UNIQUE KEY `img` (`img`) ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=7 ;  INSERT INTO `internet_shop` VALUES(1, 'iPod.png', 'iPod', 'The original and popular iPod.', 200); INSERT INTO `internet_shop` VALUES(2, 'iMac.png', 'iMac', 'The iMac computer.', 1200); INSERT INTO `internet_shop` VALUES(3, 'iPhone.png', 'iPhone', 'This is the new iPhone.', 400); INSERT INTO `internet_shop` VALUES(4, 'iPod-Shuffle.png', 'iPod Shuffle', 'The new iPod shuffle.', 49); INSERT INTO `internet_shop` VALUES(5, 'iPod-Nano.png', 'iPod Nano', 'The new iPod Nano.', 99); INSERT INTO `internet_shop` VALUES(6, 'Apple-TV.png', 'Apple TV', 'The new Apple TV. Buy it now!', 300); 

Step 2 – the XHTML

First we start off with our main markup.

 <div id="main-container"> <!-- the main container element -->  <div class="tutorialzine">	<!-- some headings --> <h1>Shopping cart</h1> <h3>The best products at the best prices</h3> </div>  <div class="container">	<!-- the first section - products -->  <span class="top-label"> <span class="label-txt">Products</span>	<!-- section label --> </span>  <div class="content-area"> <div class="content drag-desired">	<!-- assigning a common content class and an individually targeted drag-desired class -->  < ?php // php code that generates the products ?>  <div class="clear"></div>	<!-- clearing the floats --> </div> </div>  <div class="bottom-container-border">	<!-- bottom part of the section --> </div>  </div>	<!-- closing the products section -->  <div class="container">	<!-- the second section - shopping cart -->  <span class="top-label"> <span class="label-txt">Shopping Cart</span>	<!-- label for the section --> </span>  <div class="content-area"> <div class="content drop-here">	<!-- content class, shared with the product section above, and the targeted drop-here class --> <div id="cart-icon"> <img src="img/Shoppingcart_128x128.png" alt="shopping cart" class="pngfix" width="128" height="128" />	<!-- using the pngfix class --> <img src="img/ajax_load_2.gif" alt="loading.." id="ajax-loader" width="16" height="16" />	<!-- the rotating gif - hidden by default and shown during ajax interactions --> </div>  <form name="checkoutForm" method="post" action="order.php">	<!-- the form --> <div id="item-list">	<!-- in this div we insert all the products in the shopping cart -->  </div> </form>	<!-- closing the form -->  <div class="clear"></div>	<!-- clearing -->  <div id="total"></div>	<!-- the total price goes here --> <div class="clear"></div>	<!-- clearing the floats -->  <a href="" onclick="document.forms.checkoutForm.submit(); return false;" class="button">Checkout</a>	<!-- the submit button, hidden by default, notice the onclick attribute -->  </div> </div>  <div class="bottom-container-border">	<!-- bottom part of the section --> </div>  </div><!-- closing the main container --> </div> 

As you can see, we've organized our content into two main sections, which are almost identical in the XHTML markup they use – the first one, where all the products are displayed, and second one, acting as a shopping card.

Below you can see a detailed explanation of the structure of the product section.

The products are generated by our PHP code, as you can see on line 18. We are digging deeper into this in a few minutes. Now lets take a look at how we turned the XHTML layout into a finished design.

Step 3 – the CSS

 body,h1,h2,h3,p,td,quote,small,form,input,ul,li,ol,label{ /* resetting some of the styles for browser compatibility */ 	margin:0px; 	padding:0px; 	font-family:Arial, Helvetica, sans-serif; }  body{ 	color:#555555; 	font-size:13px; 	background-color:#282828; }  .clear{	/* implementing the clear-fix hack for fixing floated layouts */ 	clear:both; }  #main-container{	/* this is the main container, holding the two sections */ 	width:700px; 	margin:20px auto; }  .container{	/* the main container of our content sections - the products and the shopping cart */ 	margin-bottom:40px; }  .top-label{	/* the outer span comprising the label */ 	background:url(img/label_bg.png) no-repeat;	/* showing the left part of label_bg.png - a wide round-cornered image */ 	display:inline-block; 	margin-left:20px; 	position:relative; 	margin-bottom:-15px;	/* the whole label is lowered on the product section */ }  .label-txt{	/* the inner span - red border in the illustration above */ 	background:url(img/label_bg.png) no-repeat top right;	/* shows the right part of the wider label_bg.png */ 	display:inline-block; 	font-size:10px; 	height:36px; 	margin-left:10px;	/* leaves space on the left, so that the outer span can show its background */ 	padding:12px 15px 0 5px; 	text-transform:uppercase; }  .content-area{	/* The top part of the rounded container image, see the illustration above */ 	background:url(img/container_top.png) no-repeat #fcfcfc; 	padding:15px 20px 0 20px; }  .content{	/* shared by the two sections */ 	padding:10px; }  .drag-desired{	/* individually targeted properties */ 	background:url(img/drag_desired_label.png) no-repeat top right; 	padding:30px; }  .drop-here{	/* not shared with the other sections */ 	background:url(img/drop_here_label.png) no-repeat top right; }  .bottom-container-border{	/* the bottom rounded graphic, that completes the section */ 	background:url(img/container_bottom.png) no-repeat; 	height:14px; }  .product{	/* styling the products */ 	border:2px solid #F5F5F5; 	float:left; 	margin:15px; 	padding:10px; }  .product img{ 	cursor:move; }  p.descr{ 	padding:5px 0; }  small{ 	display:block; 	margin-top:4px; }  .tooltip{	/* the tooltips, this div is created by the simpletip plugin */ 	position: absolute; 	top: 0; 	left: 0; 	z-index: 3; 	display: none;  	background-color:#666666; 	border:1px solid #666666; 	color:#fcfcfc;  	padding:10px;  	-moz-border-radius:12px;	/* rounded corners */ 	-khtml-border-radius: 12px; 	-webkit-border-radius: 12px; 	border-radius:12px; } 

Notice the tooltip class. It is created automatically by the simpletip plugin, but it has no styles applied by default. That is why we style it here. I've used the border-radius property, which is not yet supported by all browsers, but will degrade gracefully for those that don't.

Now lets take a look at the styles that target the shopping cart section.

 #cart-icon{	/* the div that contains the shopping cart icon */ 	width:128px; 	float:left; 	position:relative;	/* changing the position to relative so that ajax-loader is positioned relative to it */ }  #ajax-loader{ 	position:absolute;	/* absolute positioning makes an element relative to its parent if the latter has positioning different from the default  */ 	top:0px; 	left:0px; 	visibility:hidden; }  #item-list{	/* the contents of the shopping cart goes into this div */ 	float:left; 	width:490px; 	margin-left:20px; 	padding-top:15px; }  a.remove,a.remove:visited{	/* the REMOVE link */ 	color:red; 	font-size:10px; 	text-transform:uppercase; }  #total{	/* the total cost div */ 	clear:both; 	float:right; 	font-size:10px; 	font-weight:bold; 	padding:10px 12px; 	text-transform:uppercase; }  #item-list table{	/* every product in the shopping cart is positioned inside the item-list div */ 	background-color:#F7F7F7; 	border:1px solid #EFEFEF; 	margin-top:5px; 	padding:4px; }  a.button,a.button:visited{	/* the CHECKOUT button */ 	display:none;  	height:29px; 	width:136px;  	padding-top:15px; 	margin:0 auto; 	overflow:hidden;  	color:white; 	font-size:12px; 	font-weight:bold; 	text-align:center; 	text-transform:uppercase;  	background:url(img/button.png) no-repeat center top;	/* showing only the top part of the background image */ }  a.button:hover{ 	background-position:bottom;	/* on hover we show the bottom part of the image */ 	text-decoration:none; }  /* Some less interesting classes */  a, a:visited { 	color:#00BBFF; 	text-decoration:none; 	outline:none; }  a:hover{ 	text-decoration:underline; }  h1{ 	font-size:28px; 	font-weight:bold; 	font-family:"Trebuchet MS",Arial, Helvetica, sans-serif; }  h2{ 	font-weight:normal; 	font-size:20px;  	color:#666666; 	text-indent:30px; 	margin:20px 0; }  .tutorialzine h1{ 	color:white; 	margin-bottom:10px; 	font-size:48px; }  .tutorialzine h3{ 	color:#F5F5F5; 	font-size:10px; 	font-weight:bold; 	margin-bottom:30px; 	text-transform:uppercase; }  .tutorial-info{ 	color:white; 	text-align:center; 	padding:10px; 	margin-top:-20px; } 

As any front-end developer will tell you, we have something missing here. You guessed it – special treatment for IE6.

I personally plan to stop supporting IE6 soon in my projects altogether – if it wasn't for it, the above code would have been at least a quarter shorter, and it would have taken a lot less time to debug.

But anyway, here is how we target IE6 specifically:

demo.php

 <!--[if lt IE 7]> <style type="text/css"> 	.pngfix { behavior: url(pngfix/iepngfix.htc);}	/* this is a special htc file that fixes the IE6 transparency issues */ 	.tooltip{width:200px;};	/* provide a default width for the tooltips */ </style> < ![endif]--> 

Step 4 – PHP

We use PHP in a number of ways and places. First lets look at how the product list is generated on the main page.

 $result = mysql_query("SELECT * FROM internet_shop");	// selecting all the products while($row=mysql_fetch_assoc($result)) { 	echo '<div class="product"><img src="img/products/'.$row['img'].'" alt="'.htmlspecialchars($row['name']).'" width="128" height="128" class="pngfix" /></div>'; } 

Another place where we use PHP is in tips.php, which takes an image file name as a parameter, checks which product is associated with that image, and outputs the tool tip data as html. This is later used by the simpletip plugin.

ajax/tips.php

 define('INCLUDE_CHECK',1); require "../connect.php";  if(!$_POST['img']) die("There is no such product!");  $img=mysql_real_escape_string(end(explode('/',$_POST['img'])));  $row=mysql_fetch_assoc(mysql_query("SELECT * FROM internet_shop WHERE img='".$img."'"));  if(!$row) die("There is no such product!");  echo '<strong>'.$row['name'].'</strong> <p class="descr">'.$row['description'].'</p> <strong>price: $'.$row['price'].'</strong> <small>Drag it to your shopping cart to purchase it</small>'; 

We also use PHP to return the necessary data for the addition of products in the shopping cart. The difference is that this time we return the data as JSON (a javascript object).

ajax/addtocart.php

 define('INCLUDE_CHECK',1); require "../connect.php";  if(!$_POST['img']) die("There is no such product!");  $img=mysql_real_escape_string(end(explode('/',$_POST['img']))); $row=mysql_fetch_assoc(mysql_query("SELECT * FROM internet_shop WHERE img='".$img."'"));  echo '{status:1,id:'.$row['id'].',price:'.$row['price'].',txt:\'\ \ <table width="100%" id="table_'.$row['id'].'">\ <tr>\ <td width="60%">'.$row['name'].'</td>\ <td width="10%">$'.$row['price'].'</td>\ <td width="15%"><select name="'.$row['id'].'_cnt" id="'.$row['id'].'_cnt" onchange="change('.$row['id'].');">\ <option value="1">1</option>\ <option value="2">2</option>\ <option value="3">3</option>\ \ </select></td>\ <td width="15%"><a href="#" onclick="remove('.$row['id'].');return false;" class="remove">remove</a></td>\ </tr>\ </table>\'}'; 

The outputted object has status, id, price and txt properties. These are used by our AJAX functions as you'll see in a moment.

Notice how I've escaped each line of the string with a backslash. This is done because javascript does not support multiline strings.

The last place where we use PHP is in order.php, which is used to process the orders. Currently, it just outputs your order. You could modify it to include an email form, paypal functionality, or anything that will make it into a functional online shop.

order.php

 < ?php  define('INCLUDE_CHECK',1); require "connect.php";  if(!$_POST)	// if there is no data submitted to the form { 	if($_SERVER['HTTP_REFERER'])	// redirect 	header('Location : '.$_SERVER['HTTP_REFERER']); 	exit;	// and exit }  ?>  <!-- XHTML code.. -->  < ?php  $cnt = array(); $products = array();  foreach($_POST as $key=>$value) { 	$key=(int)str_replace('_cnt','',$key); 	$products[]=$key;	// store the product ids in an array 	$cnt[$key]=$value;	// create a key / value pair where for each product id there is a corresponding value being the number of products  purchased}  $result = mysql_query("SELECT * FROM internet_shop WHERE id IN(".join($products,',').")");	// selecting all the products with the IN() function  if(!mysql_num_rows($result))	// no products found { 	echo '<h1>There was an error with your order!</h1>'; } else { 	echo '<h1>You ordered:</h1>'; 	while($row=mysql_fetch_assoc($result)) 	{ 		echo '<h2>'.$cnt[$row['id']].' x '.$row['name'].'</h2>'; 		$total+=$cnt[$row['id']]*$row['price']; 	}  	echo '<h1>Total: $'.$total.'</h1>'; }  ?> 

This concludes the PHP section. The only thing that is left is some jQuery magic.

Step 5 – jQuery

We will utilize jQuery to the fullest, so we will need to include the additional jQuery UI library as well as the basic library.

 <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="simpletip/jquery.simpletip-1.3.1.pack.js"></script> <!-- the jQuery simpletip plugin --> <script type="text/javascript" src="script.js"></script> <!-- our script.js file --> 

Now we can continue with our script.

script.js

 var purchased=new Array();	//an array containing all the products we've purchased so far var totalprice=0;	//the total price  $(document).ready(function(){  	$('.product').simpletip({	//using the simpletip plugin  		offset:[40,0], 		content:'<img style="margin:10px;" src="img/ajax_load.gif" alt="loading" />',	// default content 		onShow: function(){  			var param = this.getParent().find('img').attr('src'); 			// fix for IE6 			if($.browser.msie &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; $.browser.version=='6.0') 			{ 				param = this.getParent().find('img').attr('style').match(/src=\"([^\"]+)\"/); 				param = param[1]; 			}  			// after the tooltip is shown, load the tips.php file and pass the image name as a parameter 			this.load('ajax/tips.php',{img:param}); 		}   	});  	$(".product img").draggable({	// enable all product images to be dragged  	containment: 'document', 	opacity: 0.6, 	revert: 'invalid', 	helper: 'clone', 	zIndex: 100  	});  	$("div.content.drop-here").droppable({	// convert the shopping cart to a droppable  			drop: 				function(e, ui) 				{ 					var param = $(ui.draggable).attr('src'); 					// IE6 fix 					if($.browser.msie &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; $.browser.version=='6.0') 					{ 						param = $(ui.draggable).attr('style').match(/src=\"([^\"]+)\"/); 						param = param[1]; 					}  					addlist(param);	// the special addlist function - see below 				}  	});  }); 

The main idea here is that we use an image's src attribute as an unique key that is sent to the PHP back-end. Every product in the DB has a file name filed, which enables us to find the product by it's product image.

This whole block of code is executed after the page has finished loading, so we are sure that all the elements on the page are initialized.

Below is the second part of script.js.

 function addlist(param) { 	// the addlist function ads a product to the shopping cart  	$.ajax({	// sending an ajax request to addtocart.php 	type: "POST", 	url: "ajax/addtocart.php", 	data: 'img='+encodeURIComponent(param),	// the product image as a parameter 	dataType: 'json',	// expecting json 	beforeSend: function(x){$('#ajax-loader').css('visibility','visible');},	// showing the loading gif 	success: function(msg){  		$('#ajax-loader').css('visibility','hidden');	// hiding the loading gif animation 		if(parseInt(msg.status)!=1) 		{ 			return false;	// if there has been an error, return false 		} 		else 		{ 			var check=false; 			var cnt = false;  			for(var i=0; i<purchased .length;i++) 			{ 				if(purchased[i].id==msg.id)	// find if we have already bought this prduct 				{ 					check=true; 					cnt=purchased[i].cnt;  					break; 				} 			}  			if(!cnt)	// if we haven't bought it yet, or we have removed it from the purchases, we insert it in the shopping cart 				$('#item-list').append(msg.txt);  			if(!check)	// if we haven't bought it yet, insert it in the purchased array 			{ 				purchased.push({id:msg.id,cnt:1,price:msg.price}); 			}  			else	// else if we've bought it 			{ 				if(cnt>=3) return false;	// 3 products of type max  				purchased[i].cnt++; 				$('#'+msg.id+'_cnt').val(purchased[i].cnt);	// update the select box 			}  			totalprice+=msg.price;	// recalculate the price 			update_total();	// update the total div  		}  		$('.tooltip').hide();	// hiding the tooltip (sometimes it stays on screen after the drag)  	} 	}); }  function findpos(id)	// a helper function that finds the position at which the product is inserted in the array, returns the position { 	for(var i=0; i</purchased><purchased .length;i++) 	{ 		if(purchased[i].id==id) 			return i; 	}  	return false; }  function remove(id)	// remove a product from the shopping cart { 	var i=findpos(id);	// find its position in the array  	totalprice-=purchased[i].price*purchased[i].cnt;	// recalculate the price 	purchased[i].cnt = 0;	// reset the counter  	$('#table_'+id).remove();	// remove it from the cart 	update_total();	// update the total price counter on the page }  function change(id)	// evoked when we change the number of products via the select area { 	var i=findpos(id);  	totalprice+=(parseInt($('#'+id+'_cnt').val())-purchased[i].cnt)*purchased[i].price;  	purchased[i].cnt=parseInt($('#'+id+'_cnt').val()); 	update_total(); }  function update_total()	// function that updates the total price div on the page { 	if(totalprice) 	{ 		$('#total').html('total: $'+totalprice);	// if we've bought somehitng, show the total price div and the purchase button 		$('a.button').css('display','block'); 	} 	else	// hide them 	{ 		$('#total').html(''); 		$('a.button').hide(); 	} } 

Conclusion

Today we made a functional AJAX driven shopping cart. You are free to download the code and modify it any way you wish. You can build upon it and even turn it into a full fledged online shop.



Demo : http://demo.tutorialzine.com/2009/09/shopping-cart-php-jquery/demo.php

Download : http://demo.tutorialzine.com/2009/09/shopping-cart-php-jquery/demo.zip

Source : http://tutorialzine.com/2009/09/shopping-cart-php-jquery/

Related Listings:

  1. jCart – free jQuery/PHP web cart Based on jQuery and PHP, jCart handles visitor input without...
  2. Ajax Based Tab Script When user clicks a tab the Ajax will communicate with...
  3. Ajax im – Ajax based Instant Messenger ajax im (”asynchronous javascript and xml instant messenger”) is a...

jQuery Browser Plugin

Posted: 06 Oct 2009 11:17 AM PDT

The jQuery Browser Plugin is an addon for jQuery that makes it easy to uniquely identify your visitors’ browsers.

It gives you an object in javascript that contains all of the information about the browser being used. It also adds CSS browser selectors, which means you can style elements or write functions for specific browsers, browser versions, layouts, layout versions, and even operating systems. Image of the jQuery Browser Plugin in action.

First, it quickly and carefully collects all of the information about the browser. Then, it takes all of that information and places it into intuitively named objects inside jQuery.browser, jQuery.layout, and jQuery.os. making browser information as easily accessible as jQuery already makes writing javascript.

jQuery is a small but power-packed bundle of javascript functions that make writing javascript quick and simple. Selecting elements on your page is like using CSS, learning and using functions requires minimal fuss, and the learning curve is sometimes described as “zero”.

Features

The jQuery Browser Plugin strives to make accessing your visitors’ browser information simple and intuitive. It can literally be this simple:

* browser.name: The name of the browser being used.

alert($.browser.name); // this will alert ‘firefox’
* browser.version: The version of the browser (note, as a string).

alert($.browser.version); // this will alert ‘3.5.3′
* browser.versionNumber: The version of the browser (note, as an integer).

alert($.browser.versionNumber); // this will alert ‘3.5′ alert($.browser.versionNumber + 1); // this will alert ‘4.5′
* browser.versionX: The release of the browser (think 2x, 3x, etc).

alert($.browser.versionX); // this will alert ‘3′
* browser.className: The browser name and browser version as a class name.

alert($.browser.className); // this will alert ‘firefox3′
* layout.name: The name of the layout engine being used.

alert($.layout.name); // this will alert ‘gecko’
* layout.version: The version of the layout engine (note, as a string).

alert($.layout.version); // this will alert ‘1.9.1.3′
* layout.versionNumber: The version of the layout engine (note, as an integer).

alert($.layout.versionNumber); // this will alert ‘1.9′ alert($.layout.versionNumber + 1); // this will alert ‘2.9′
* browser.versionX: The release of the layout engine (think 2x, 3x, etc).

alert($.layout.versionX); // this will alert ‘1′
* layout.className: The browser name and browser version as a class name.

alert($.layout.className); // this will alert ‘gecko1′
* os.name: The operating system being used.

alert($.os.name); // this will alert ‘win’

Other values that may appears (this is actually based off the browser you’re currently viewing this page with).





Demo: http://jquery.thewikies.com/browser/test.html
Download: http://jquery.thewikies.com/browser/jquery.browser.min.js
Source: http://jquery.thewikies.com/browser/

Related Listings:

  1. jQuery Calculate Plugin The Calculation plug-in is designed to give easy-to-use jQuery...
  2. EasyDrag Box jQuery Plugin Handler feature added! Finally I decided to add a...
  3. imgAreaSelect with jQuery Plugin imgAreaSelect is a jQuery plugin for selecting a rectangular area...

Jquery Gadget Plugin

Posted: 06 Oct 2009 09:15 AM PDT

The jquery.gadget plugin provides a way of combining javascript with a html resource and css, providing a simple, scoped lifecycle and a standardised approach to writing modular, self contained ajax gadgets. It's an intentionally simple approach to a problem that sits somewhere between basic jquery ajax such as $.get("/url.html") and the more complicated mvc style approach of frameworks like sproutcore, javascriptMVC etc.

Typically a gadget will be comprised of three parts:

1. A javascript file – typically gadgets exist in their own file and are named in relation to their file location and url of the html resource. This helps to keep things clear within the project. As the number of gadgets in your project increases you'll want to start combining gadget js files into a single minified resource. Packtag is a good solution to this problem in the java world. There are other tools for this in other languages.
2. A html resource – this is the server generated html referenced and loaded by the gadget.
3. A css file – css used to style the gadget. The same naming and organization rules apply as for the gadget js.

While the css is an important part of the picture, there is no specific functionality provided for it within the gadget framework. There are however a series of 'best practices' that describe simple ways of scoping your css to your gadgets so that they are isolated from the rest of your page and will not cause problems when combined with other elements on the page. These are provided later in the document.
Registering a gadget

Before a gadget can be used, it must be registered with the page. This is a little like writing a class and it's the way you define the behaviour of the gadget common to all instances.

A gadget should be registered in such a way that it's both correctly scoped and evaluated immediately on load as opposed to on dom-ready. This ensures that the gadget is added to the gadget registry so it can be instantiated within the page. The recommended way of registering a gadget is as follows:

 (function() {      $.gadget.register("my_gadget", {           baseUrl : my_gadget.html",           initialize : function() {                var gadget = this;                 // do things with the gadget here           }      }); })();

The three key pieces here are:

1. The gadget name – this must be unique within the page, most commonly this really means within the application. If a page contains more than one gadget registered under the same name, an error will be raised in the console.
2. The baseUrl – this is the base url of the html for the gadget. Don't put query string params here. They are passed separately and generally when creating instances of the gadget rather than during registration as these vary between instances.
3. initialize – this is called once the gadget's html has been inserted into the dom. This is where you define any common behaviour such as binding events to elements within the gadget.

Typically when a gadget is initialised, you will want to act on elements within the gadget html. In fact, as a general rule, you should only ever act on dom elements that are known to the gadget in order to keep coupling as low as possible. Cross gadget communication will be covered later on when we discuss events.

Once initialised, every gadget will have a reference to the dom element that wraps the gadget html. This property is exposed directly from the gadget instance and is called 'element' – it is also important to note that this is a jquery object wrapper of the dom element. So for example, if you wanted to find all button elements within the gadget onload and bind to their onclick event you could do something like this:

 var gadget = this; gadget.find("button").click(function() {      console.log("Click!"); });

Note the shortcut to the jquery find method. You could also write this as jquery.element.find() but it's used so often this will save quite a few bytes!

Ok, so we've registered a gadget, how do we actually use it ?
Using a gadget

The gadget api is a jquery plugin so it behaves like any other jquery plugin in that it acts on an element or set of elements selected using a jquery dom query. The one difference difference here is that where a regular jquery plugin will return the jquery object it was applied to, the gadget plugin returns the gadget element instead. The reason for this is due to the different ways you can create a gadget in relation to the original element. Also in the context it's used, it's unlikely you'd want to be doing any serious chaning.

Say you wanted to insert an instance of the "my_gadget" gadget into the div with id "gadget_container". In this example you would do this:

 $("#gadget_container").gadget("my_gadget");

The result of this would be call the url specified in the registration of the "my_gadget" gadget, insert it into the div with id "gadget_container", then call the initialize function on the gadget.

There are several options that can be passed to the gadget when creating an instance which are listed below. It is important to note that all of these can be supplied upon registration of the gadget as well. In many cases that is the preferred place as the only configuration that should be supplied upon gadget creation is the config that varies on a per instance basis:

* cache [true / false] – defaults to false – this provides a local cache of the html after the first time it's called. This is handy when you have some static html that should only ever be loaded once within a page or if you're loading a html template that you're going to merge with data upon load.
* method – ["html", "after", "before", "append", "prepend"] – defaults to "html" – determines where the element is inserted in relation to the element that gadget was called upon. Based on the standard jquery dom manipulation methods.
* baseUrl – if you want to override on a per instance basis.
* urlParams – an object literal representing the parameters to be passed with the baseUrl – Eg.

* dataany data you want to pass to the gadget for use in setting up the instance of the gadget etc. Can be retrieved directly from the gadget in the initialise method via this.data.
* postInitialize – provides a place to call specific logic after the main initialisation has occured.
* dialog – a config object or function returning a config object for loading the gadget inside a jquery-ui dialog. This requires jquery-ui to be included on the page or it won't work.
* cssClass – an optional class name(s) that will be added to the gadget wrapper div.

The structure of a gadget

The basic structure of gadget html is extremely simple. When a gadget is created a wrapper div is created that the gadget html is inserted into. An empty gadget called "contact_list" would look like the following:

<div class="gadget gadget_contact_list"></div>

It might be worth noting here that this root gadget element also has a reference to the gadget object stored using the jquery data construct. You could for instance get a handle to the gadget object in the following way via the root gadget element:

 $(".gadget_contact_list").data("gadget");

Gadget CSS

As mentioned earlier there is no specific provision for css in the gadget framework. Following this simple set of rules should help you to write gadgets with properly scoped css.

* Use a single css file for each gadget. If you are doing this, we highly recommend combining all your css into a single file as part of your build process. Better still, use a framework like packtag (for java) or one of the solutions for other back-ends to do this at runtime. This will make for a much more pleasant development experience, I promise!!
* A gadget automatically gets the following classes applied to it's wrapper div – "gadget" and "gadget_name_gadget". Use these classes to correctly scope each gadget css to the gadget. For example:

       .user_list_gadget h2 { font-size: 1.2em;};

* This would apply to the following gadget html wrapper element:

       <div class="gadget user_list_gadget">//your gadget in here...</div>

It is also possible to pass other css classes via the config option 'cssClass' when both registering or creating a gadget. This could be useful if you want to define a class that is shared across multiple gadgets.
Events and inter-gadget-communication

In order for gadgets to stay decoupled from one another each gadget should be able to exist without the requirement that another gadget exist. Sometimes gadgets do however have behaviour that depends on other gadgets so the key in this situation is to limit the communication channel between each gadget to an events based system. One gadget can publish and event that other gadgets can listen for – the end result being that the only coupling between the gadgets is an event name.

This is probably best illustrated with a scenario:

Say you have a typical master-detail view which is comprised of two gadgets, one is used to represent the a list of contacts and the other a specific contact. When the user clicks on a contact from the list, the contact should be opened in the detail view.

The wrong way:

On click of the contact in the list, the html for the contact is fetched, a dom query is made from the list gadget that finds the container for the detail view container and the html is inserted directly into this container.

The problem with this approach is that the list view requires that the detail view exist on the page to work. They are coupled together. It would be difficult or impossible to test these two gadgets in isolation.

A better way:

On click of the contact in the list, the "contact_loaded" event is fired with the id of the contact to open. The detail view gadget is listening for this event so when it receives notification, it takes the id for the contact, loads the contact, and then populates it's content with the contact details. Of course there are a few ways you could achieve this depending on the context but this example serves mainly to illustrate the use of events for the communication between the gadgets than the implementation of this specific scenario.
Binding and triggering events

The gadget framework makes use of jquery custom events. This essentially boils down to binding functions to named events at a global level. The trick with gadgets or in fact any heavy ajax based page is that you don't want event bindings to hang around longer than the gadget that they are owned by, or just as importantly, to element that the listeners refer to.

Custom jquery events can be bound directly to jquery objects at any level of the dom. Unlike regular dom events however, custom events do not bubble, so you need to trigger an event on the same element that the listener is bound to. Binding events in this way somewhat defeats the purpose though because it means event publishers need to know what objects are listening to them and trigger each one explicitly. One way around this, and the one that gadgets use is to bind and trigger all events against $(document). This effectively provides a global event hub that all custom events pass through.

For this to work correctly, you need to be sure to namespace your events correctly so you don't have collisions. Using some basic conventions this can be pretty straight forward. I've found that prefixing each event with the gadget name is a good start but any convention is fine.

To extend our previous example, if upon initialising itself, our contact gadget binds itself to any events called "contact_loaded", there is now a function bound to the gadget registry. If we were to then do something with the page that caused the dom element representing the gadget to be removed from the dom the binding for the "contact_loaded" event will still be in the event registry. Now we come back to the contacts view and another instance of the same event function gets added to the registry. Now when we go to open a contact, the event is picked up by two identical functions which are both executed. Worse still, the first instance of the function is refering to a dom element that no longer exists. This is obviously not something that we want.

The way to avoid this in the gadget world is to use the gadget itself to bind and (less importantly) trigger events. This way the gadget knows of all it's bindings and if used correctly can clean up after itself. For this to work effectively two things must be done:

1. All bindings to external events from a gadget should be done in the following manner:

gadget.bind(”event_name”, function(event, data){});

2. Whenever updating content within a page, use a gadget to do it unless you are absolutely sure that their are no child nodes within that content that contain other gadgets. The reason for this is that when a gadget inserts it's html content into the dom, it checks for any existing gadgets that it might be overwriting. If there are any, it unbinds all event bindings and detroys the gadget. This ensures that there's no rogue events hanging around outside of the life of the gadget.
Global Gadget Events

There are a couple of global events at this stage. Global events differ from instance events in that they are triggered for any gadget instance.

* preLoad [gadget_pre_load]
* postLoad [gadget_post_load]

These events are published as global jquery events under the keys shown above in brackets. These events could be used as a gadget focused way of displaying a loading indicator for instance. Both events pass a reference to the gadget. For example:

 $(document).bind("gadget_pre_load", function(event, gadget) {     showLoadingIndicator(gadget.element); });

Where to from here ?

There are lots of places you can take something like this, however, much further and you're approaching functionality that is much better supported by 'real' frameworks. Some simple things that could be added and probably will before too long are:

* Support for templating so that instead of returning populated html, a html template is returned and a seperate json request returns the data that can be merged with the html template. This way the html can be cached and a smaller request for data can result in a snappier application.

Feel free to do whatever you like with this code. Use it as-is or pull it apart. Internally there are things i'll probably change before too long as it was originally written a while back and i've learned a thing or two about javascript that i'd do differently. I will probably write a version of this that is based on jquery-ui widgets at some stage as they enforce a nicer set of conventions that this could benefit from.





Download: http://www.redredred.com.au/wp-content/uploads/2009/05/jquerygadget.js
Source: http://www.redredred.com.au/projects/jquery-gadget-plugin/

Related Listings:

  1. EasyDrag Box jQuery Plugin Handler feature added! Finally I decided to add a...
  2. KeyTable – jQuery Table Plugin KeyTable is a Javascript library which provides keyboard navigation and...
  3. QuickFlip 2: The jQuery Flipping Plugin Made Faster and Simpler QuickFlip 2, a major reworking of the jQuery plugin that...

markItUp beta Universal Markup Editor

Posted: 06 Oct 2009 09:03 AM PDT

markItUp! is not meant to be a "Full-Features-Out-of-the-Box"-editor. Instead it is a very lightweight, customizable and flexible engine made to meet the developer’s needs in their CMSes, blogs, forums or websites. markItUp! is not a WYSIWYG editor, and it never will be.

* Author: Jay Salvat
* Licence: MIT/GPL
* File: Packed naked engine is about 6.5Kb.
* Required: jQuery 1.2.3 Javascript library
* Info: markItUp! is based on former jTagEditor
* Supported: IE7, Safari 3.1, Firefox 2, Firefox 3. IE6 and Opera 9+ as-is.

Licensing

markItUp! is released under both the MIT and GPL Open Source licenses.
In short, this means that markItUp! is totally Free, and you can do whatever you want with it. You are only obligated to keep the credits in place, but a link to this website in your application’s credits is highly appreciated.
If you use markItUp! and like it, please consider making a donation.





Demo: http://markitup.jaysalvat.com/downloads/demo.php?id=releases/latest
Download: http://markitup.jaysalvat.com/downloads/download.php?id=releases/latest
Source: http://markitup.jaysalvat.com/home/

Related Listings:

  1. NicEdit Inline Content Editor NicEdit is a WYSIWYG editor for websites. Its goal is...
  2. Simple WYSIWYG Editor The Simple WySiWyG Editor for your small light and simple...
  3. Ajax Script – Free Rich Text Editor Free Rich Text Editor is same like a WYSIWYG editor...

0 comments:

Post a Comment

Note: Only a member of this blog may post a comment.