Friday, July 6, 2007

Drag and Drop -Ajax Page Elements

Ever wondered how Google creates personalized home
page with drag and drop effects.

Yes you can also create similar drag and drop page elements in your own web page by using Ajax Javascript libraries like Scriptaculous and Prototype.js in conjunction with StyleSheets.

Here is the code snippet to do that.
Step 1: Ajax JavaScript library
Download the latest scriptaculous js library from the site
http://script.aculo.us/downloads
To create the drag and drop elements in your page you will need the following js file from the scriptaculous library. You can remove all other js files from the library.
1. Dragdrop
2. Effects
3. Prototype
4. Scriptaculous

Step 2: JavaScript to produce draggable elements

Create a JavaScript file portal.js.
Include the following code to this file. The functions added here are used to create draggable page elements.
var Portal = Class.create();
Portal.prototype = {
initialize: function (options) {
this.setOptions(options);
var sortables = document.getElementsByClassName(
this.options.column, this.options.portal
);
sortables.each(function (sortable) {
Sortable.create(sortable, {
containment: sortables,
constraint: false,
tag: 'div',
only: this.options.block,
dropOnEmpty: true,
handle: this.options.handle,
hoverclass: this.options.hoverclass,
onUpdate: function (container) {
if (!this.options.saveurl) {
return;
}
if (container.id == this.options.blocklist) {
return;
}
var url = this.options.saveurl;
var postBody = container.id + ':';
var blocks = document.getElementsByClassName(
this.options.block, container
);
postBody += blocks.pluck('id').join(',');
postBody = 'value=' + escape(postBody);

new Ajax.Request(url, {
method: 'post',
postBody: postBody
}
);
}.bind(this)
});
}.bind(this));

var blocks = document.getElementsByClassName(
this.options.block, this.options.portal
);
blocks.each(
function (block) {
var content = Element.childrenWithClassName(
block, this.options.content, true
);

var toggle = Element.childrenWithClassName(
block, this.options.toggle, true
);
Event.observe(
toggle, 'click',
function (e) { Effect.toggle(content, 'Slide'); },
false
);

}.bind(this)
);

Event.observe(
this.options.blocklistlink, 'click',
this.displayBlockList.bindAsEventListener(this),
false
);

new Draggable(this.options.blocklist, {
handle: this.options.blocklisthandle
}
);

},

displayBlockList: function (e) {
Effect.toggle(this.options.blocklist);
Event.stop(e);
},

setOptions: function (options) {
this.options = {
portal: 'portal',
column: 'portal-column',
block: 'block',
content: 'content',
handle: 'handle',
hoverclass: 'block-hover',
toggle: 'block-toggle',
blocklist: 'portal-column-block-list',
blocklistlink: 'portal-block-list-link',
blocklisthandle: 'block-list-handle',
saveurl: ''
}
Object.extend(this.options, options || {});
},

applySettings: function (settings) {
for (var container in settings) {
settings[container].each(function (block) {
$(container).appendChild($(block));
});
}
}
}

Step 3: CSS file
Create a CSS file portal.css. This CSS file is needed to produce the drag and drop effect in your page.
Copy the following contents into the file
#portal .portal-column {
float: left;
width: 30%;
margin: 5px;
padding: 5px;

}
#portal .portal-column h2 {
color: #bbb;
text-align: center;
}

#portal #portal-column-block-list {
position: absolute;
width: 200px;
top: 140px;
left: 0;
z-index: 10;
background-color: #FFEAB1;
}
#portal #portal-column-block-list .block {
margin: 2px;
}
#portal #portal-column-block-list .block .content {
display: none;
}

#portal .block {
margin: 15px;
padding: 5px;
border: 1px solid #0F3974;
}
#portal .block h3 {
margin: 0;
padding: 5px;
font-size: 14px;
color: #fff;
background-color: #2153AA;
}
#portal .block .content {
padding: 5px;
}
#portal .block .block-toggle {
background-image: url(block-slide.png);
display: block;
float: right;
width: 7px;
height: 7px;
background-repeat: no-repeat;
background-position: center;
cursor: pointer;
}
#portal .block .block-toggle span {
display: none;
}

#portal .block-hover {
border: 1px dashed #f00;
}

#portal .block-list-handle, #portal .handle {
cursor: move;
}
* html body #portal .handle {
width: 100%;
}
#portal #portal-column-block-list .block .block-toggle {
display: none;
}

Step 4: HTML Page

In your html page include the following javascript libraries and css files
1. Prototype.js
2. Scriptaculous.js
3. Portal.js
4. Portal.css
The Scriptaculous.js and Prototype.js internally uses DragDrop and Effect js.
Make sure these files are included in your lib folder.
To make a page element draggable enclose the element within the following div tags

<div class="portal-column" id="portal-column-0">
<div class="block block-archive" id="Div1">
[Draggable page element]
</div>
</div>

To create a droppable column in your page add the following div tags

<div class="portal-column" id="portal-column-block-list">
[Page column – Page elements can be dragged to this column]
</div>

Sample html code:

Here is the entire code sample which can be used to test the drag and drop effect.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Ajax Drag and Drop</title>
<script type="text/javascript" src="lib/prototype.js">
</script>
<script type="text/javascript" src="lib/scriptaculous.js">
</script>
<script type="text/javascript" src="lib/portal.js">

</script>
<script type="text/javascript">
//<!--
var settings = {};
var portal;
function init() {
portal = new Portal();
portal.applySettings(settings);
}
Event.observe(window, 'load', init, false);
//-->
</script>
<style type="text/css" media="all"> @import "css/portal.css";
</style>
</head>
<body>
<div id="portal">
<div class="portal-column" id="portal-column-0">
<div class="block block-archive" id="Div1">
Draggable item 1
</div>
</div>
<div class="portal-column" id="portal-column-block-list">
<div class="block block-archive" id="block-archive-0">
Draggable item 2
</div>
<div class="block block-archive" id="block-archive-1">
Draggable item 3
</div>
</div>
</div>
</body>
</html>

Now you can drag any page element included within the “block block-archive column” to the column marked by the “portal-column block-list” in the page.

In the above sample you will be able to drag the text marked “Drag1” to the column created by “portal-column-block-list” id.

No comments: