Scriptaculous is a library that makes use of Prototype to deliver a rich set of high-level functionality that the developer can put to work directly in creating polished interactive user interfaces. On its own, Prototype smoothes out many of the wrinkles of Ajax development. When used with Scriptaculous, it transforms the way in which we approach the web user interface, by making features such as animation and dragging and dropping as simple as a few lines of code.
Usage
1. Download
Go to the script.aculo.us downloads page to grab yourself the latest version in a convenient package. Follow the instructions there, then return here.
2. Install
Put prototype.js, scriptaculous.js, builder.js, effects.js, dragdrop.js, slider.js and controls.js in a directory of your website, e.g. /javascripts.
3. Link to script.aculo.us
Link to the scripts in the head of your document:
|
By default, scriptaculous.js loads all of the other javascript files necessary for effects, drag-and-drop, sliders, and all of the other script.aculo.us features. If you don’t need all of the features, you can limit the additional scripts that get loaded by specifying them in a comma-separated list, e.g.:
|
The scripts that can be specified are:
- builder
- effects
- dragdrop
- controls
- slider
Note that some of the scripts require that others be loaded in order to function properly.
Creating Sortable Lists With PHP And Ajax
Introduction
You might have been in a situation before where you had a list of items in your database that needed to be output in a specific order. These items could be anything: perhaps a listing of your favourite movies or your favourite books. For whatever reason, you want them ordered in a custom way that can’t be determined automatically (such as alphabetical).
This article covers the implementation of a system that lets you easily define the order of such a list.
Traditionally, implementations of such functionality involve you clicking a “move up”, “move down”, “move to top”, or “move to bottom” button that switches the order the items (one item at a time). Or perhaps each item has a text box with a number in it, that by changing the numbers you can change the order of the list.
In any case, these methods are much more difficult to use than they should be. In this article, we’ll create a drag drop system using JavaScript that will let you drag an item to its new position, and then save the new order as soon as you drop the item.
To achieve the Ajax effects (that is, the drag/drop effect, and the seamless saving of ordering data), we will be using the Prototype and Scriptaculous libraries.
Firstly, we will create a database table (compatible with MySQL and PostgreSQL) and populate it with data. Then we will output our list and apply the drag and drop effects to it. Finally, we will deal with the saving of the new ordering data.
For our example, we will use a list of “favourite movies”, and implement functionality to change the order of our movies.
Creating Our Database And Populating It
We will now create the database table we need in order to create this example. We won’t be writing all the code for inserting, editing and deleting of data, as it is beyond the scope of this example. As such, we will simply provide insert statements to create a static list of data.
The examples below are for PostgreSQL and MySQL.
Create your database
First up, you need to create a database for this article. This may be in either PostgreSQL or MySQL. Additionally, you may need to setup a username and password to access the database, depending on your system setup.
MySQL database schema
Listing 1 listing-1.sql
create table movies (
movie_id int not null auto_increment,
title varchar(25) not null,
ranking int,
primary key (movie_id)
);
insert into movies (title) values ('American Pie');
insert into movies (title) values ('Die Hard');
insert into movies (title) values ('Clerks');
insert into movies (title) values ('Air Force');
insert into movies (title) values ('Titanic');
insert into movies (title) values ('Shawshank');
insert into movies (title) values ('Gone In 60');
Code:
<html>
<head>
<title>aseef</title>
<script src=”prototype.js” type=”text/javascript”></script>
<script src=”scriptaculous.js” type=”text/javascript”></script>
<style>
li.green {
background-color: #ECF3E1;
border:1px solid #C5DEA1;
cursor: move;
}
li.orange {
border:1px solid #E8A400;
background-color: #FFF4D8;
}
span.handle {
background-color: #E8A400;
color:white;
cursor: move;
}
</style>
</head>
<body>
<?php
$connect = mysql_connect(’localhost’,'user_name’,'password’) ;
mysql_select_db(’test’) ;
$query = “select * from movies order by ranking”;
$result = mysql_query($query,$connect) ;
?>
<div style=”height:200px;”>
<div style=”float:left;”>
<h3>This is the first list</h3>
<ul class=”sortabledemo” id=”movie_list” style=”height:150px;width:200px;”>
<?php
while($row = mysql_fetch_array($result))
{
extract($row);
echo “<li class=’green’ id=’movie_$movie_id’>”.$title.”</li>”;
}
?>
</ul>
</div>
<div id=”user_list”>
</div>
<script type=”text/javascript”>
function updateOrder()
{
var option = {
method: ‘post’,
parameters: Sortable.serialize(’movie_list’),
onComplete: showStatus
};
new Ajax.Request(’process.php’,option);
}
function showStatus(returnData)
{
var info = returnData.responseText;
document.getElementById(’user_list’).innerHTML=info;
}
Sortable.create(’movie_list’, { onUpdate : updateOrder });
</script>
Shopping Cart using Script.aculo.us
This workshop we will be building a shopping cart that’s Ajax powered. This will be a drag and drop shopping cart using the Script.aculo.us JavaScript library. We will also be using PHP on the back end to store the user’s shopping cart in sessions.
We will start this workshop off with the XHTML and CSS for the shopping cart and its products. Let’s take a look at the XHTML.
<div id="products">
<div style="float:left; font-weight:bold">Products</div>
<div id="clearCart" onclick="clearCart();">Clear Cart</div>
<div id="loading">Loading...</div>
<br style="clear:both" />
<div class="box" id="product_1">1</div>
<div class="box" id="product_2">2</div>
<div class="box" id="product_3">3</div>
<div class="box" id="product_4">4</div>
<div class="box" id="product_5">5</div>
<div class="box" id="product_6">6</div>
</div>
<div id="cart">
<div style="float:left; font-weight:bold">Shopping Cart</div>
</div>
We start out with a product div; this div will hold all of our products. Inside the product div we have a new div for the product box label “Products”, a div to hold the clear cart button (which we attached an event to that will be discusses further in the workshop) and the loading status image. After we have a break tag with a clear:both this is needed because we floated the previous divs.
We then have the products with their class “box” and a unique id. The ID is what we will be passing to the server side to add the product to our shopping cart.
We then have the cart div. This is the actual shopping cart when you drag your products into to be saved server side.
Let’s take a look at the CSS now:
#cart {
background-color:#FFFF66;
border:dashed gray 1px;
height:100px;
width:500px;
padding:5px;
margin-top:10px;
overflow: auto;
}
#products {
background-color:#FFF;
border:dashed gray 1px;
height:100px;
width:500px;
padding:5px;
}
.box {
background-color:#CCFF33;
border:solid gray 1px;
margin:10px;
padding:4px;
width:50px;
height:50px;
float:left;
cursor:pointer;
}
#loading {
display:none;
float:right;
}
#clearCart {
text-decoration:underline;
cursor:pointer;
float:right
}
#clearCart:hover {
background-color:#CCFFCC;
color:#000099;
}
Nothing spectacular going on here for the most part, we are giving all of our divs some style, setting the height and width colors etc. Some things to point out are in the box class we are floating left so that the divs are horizontally aligned also we are setting display of the loading ID to none so that it’s not shown unless we are communicating with the server.
You should now have something that looks like this:

We now need to add the code for Script.aculo.us to create the drag and drop functionality. Add this code right before the closing of your body tag.
<script type="text/javascript">
var products = document.getElementsByClassName('box');
for (var i = 0; i < products.length; i++) {
new Draggable(products[i].id, {ghosting:true, revert:true})
}
Droppables.add('cart', {onDrop:addProduct})
</script>
The first thing we are doing is getting each product as an object so we can add the drag ability from Script.aculo.us. We do this by getting all elements with the class name of “box” in an array then looping through and creating a new Draggable with the ID of the element. There are also two parameters: ghosting:true and revert:true. Ghosting makes the element transparent while dragging and revert sends the element back to it’s starting position on mouse out.
We then make the cart div a droppable. What this does is allow us to catch the ID of which element was dropped and call a function. We set the onDrop parameter to onDrop:addProduct which means that when a draggable (product) is dropped on the droppable (cart) we call the function addProduct.
Let’s take a look at the JavaScript now that contains all of our functions.
function addProduct(element, dropon, event) {
sendData(element.id);
}
function sendData (prod) {
var url = 'cart.php';
var rand = Math.random(9999);
var pars = 'product_id=' + prod + '&rand=' + rand;
var myAjax = new Ajax.Request( url,
{method: 'get',
parameters: pars,
onLoading: showLoad,
onComplete: showResponse} )
}
function clearCart () {
var url = 'cart.php';
var rand = Math.random(9999);
var pars = 'clear=true&rand=' + rand;
var myAjax = new Ajax.Request( url,
{method: 'get',
parameters: pars,
onLoading: showLoad,
onComplete: showResponse} )
}
function clearProduct (id) {
var url = 'cart.php';
var rand = Math.random(9999);
var pars = 'clearProduct=true&id=' + id + '&rand=' + rand;
var myAjax = new Ajax.Request( url,
{method: 'get',
parameters: pars,
onLoading: showLoad,
onComplete: showResponse} );
}
function showResponse (originalRequest) {
$('loading').style.display = "none";
$('clearCart').style.display = "block";
$('cart').innerHTML = originalRequest.responseText;
}
function showLoad () {
$('clearCart').style.display = "none";
$('loading').style.display = "block";
}
The first function we created addProduct is what is called when a product is added to the shopping cart. We then call another function sendData and pass the ID of the product that was dropped in the cart.
The next function sendData we send the product ID to the server to store in a SESSION. For more information using this function visit the previous workshops where we went into greater detail.
The clearCart and clearProduct functions are almost identical to the sendData function, but instead we are clearing the cart and clearing the product respectively in the server side SESSION.
The showResponse function is updating the shopping cart with products in the server side SESSION as well as hiding the loading div and showing the clear cart button.
The showLoad function hides the clear cart button and shows the loading status div.
Time for the server side Cart.php.
<?php
session_start();
function stringForJavascript($in_string) {
$str = ereg_replace("[rn]", " \n\n", $in_string);
$str = ereg_replace('"', '\"', $str);
Return $str;
}
if (isset($_GET['clearProduct'])) {
$_SESSION['cart'][$_GET['id']]--;
if ($_SESSION['cart'][$_GET['id']] == 0) {
unset($_SESSION['cart'][$_GET['id']]);
}
foreach ($_SESSION['cart'] as $key => $value) {
print "$key = $value <span style="color:blue;
text-decoration:underline;
cursor:pointer"
onclick="clearProduct('$key');">DELETE</span><br>";
}
sleep(1);
die;
}
if (isset($_GET['clear'])) {
unset($_SESSION['cart']);
sleep(1);
die;
}
$prodid = $_GET['product_id'];
$_SESSION['cart'][$prodid] = 1 + $_SESSION['cart'][$prodid];
foreach ($_SESSION['cart'] as $key => $value) {
print "$key = $value <span style="color:blue;
text-decoration:underline;
cursor:pointer"
onclick="clearProduct('$key');">DELETE</span><br>";
}
sleep(1);
?>
We start off by calling the session_start() function which allow us to access and modify the SESSION global variable. We then have created a function for returning a string that JavaScript can read.
Next we are using a conditional statement to check whether we are adding a product, clearing the cart or removing a product. Depending on what action is called we manipulate the SESSION global variable and send back the contents of the shopping cart.
Visual Effects
All the combination effects are based on the five Core Effects(Effect.Opacity, Effect.Scale, Effect.Morph, Effect.Move, Effect.Highlight, Effect.Parallel) and are thought of as examples to allow you to write your own effects.
- Effect.Appear, Effect.Fade
- Effect.Puff
- Effect.DropOut
- Effect.Shake
- Effect.Highlight
- Effect.SwitchOff
- Effect.BlindDown, Effect.BlindUp
- Effect.SlideDown, Effect.SlideUp
- Effect.Pulsate
- Effect.Squish
- Effect.Fold
- Effect.Grow
- Effect.Shrink
Additionally, there’s the Effect.toggle utility method for elements you want to show temporarily with a Appear/Fade, Slide or Blind animation
Effect.toggle uses any of the following pairs:
|
Toggle Parameter |
Appears With |
Disappears With |
|
Appear |
||
|
Slide |
||
|
Blind |
A demo is given on the following site:
http://wiki.script.aculo.us/scriptaculous/show/CombinationEffectsDemo