JavaScript拖拽给网页布局效果,酷

2008-12-31 15:39:26 | 【

非常优秀的拖拽效果,支持各种浏览器,网页上的任何模块都可以随意拖动来对网页进行布局,媲美iGoogle的主页效果

查看演示页面 View Demo 查看全部代码 View Code

在网页<head>区添加以下代码

	<style type="text/css">
	/* CSS NEEDED ONLY IN THE DEMO */
	html{
		width:100%;
		overflow-x:hidden;
	}
	body{
		font-family: Trebuchet MS, Lucida Sans Unicode, Arial, sans-serif;
		width:100%;
		margin:0px;
		padding:0px;
		text-align:center;
		background-color:#E2EBED;	
		font-size:0.7em;	
		overflow-x:hidden;
	}
		
	#mainContainer{
		width:600px;
		margin:0 auto;
		text-align:left;
		background-color:#FFF;
	}
	h4{
		margin:0px;
	}
	p{
		margin-top:5px;
	}
	
	
	
	/* This is the box that is parent to the dragable items */
	#dragableElementsParentBox{
		padding:10px;	/* Air */
	}
	
	.smallArticle,.bigArticle{
		float:left;
		border:1px solid #000;
		background-color:#DDD;
		padding:2px;
		margin-right:10px;
		margin-bottom:5px;
	}
	.smallArticle img,.bigArticle img{
		float:left;
		padding:5px;
	}
	.smallArticle .rightImage,.bigArticle .rightImage{
		float:right;
	}
	.smallArticle{
		width:274px;		
	}
	.bigArticle{
		width:564px;
	}
	.clear{
		clear:both;
	}
	
	/* END DEMO CSS */
	
	/* REQUIRED CSS */
	
	#rectangle{
		float:left;
		border:1px dotted #F00;	/* Red border */
		background-color:#FFF;
	}
	#insertionMarker{	/* Don't change the rules for the insertionMarker */
		width:6px;
		position:absolute;
		display:none;
	}
	#insertionMarker img{	/* Don't change the rules for the insertionMarker */
		float:left;
	}		
	#dragDropMoveLayer{	/* Dragable layer - Not need if you're using 'rectangle' mode */
		position:absolute;
		display:none;
		border:1px solid #000;
		filter:alpha(opacity=50);	/* 50% opacity , i.e. transparency */
		opacity:0.5;	/* 50% opacity , i.e. transparency */

	}
	
	/* END REQUIRED CSS */
	</style>
	
	<script type="text/javascript">
                 
        /*****************************************************
         *  Share JavaScript (http://www.ShareJS.com)
         * 使用此脚本程序,请保留此声明
         * 获取此脚本以及更多的JavaScript程序,请访问 http://www.ShareJS.com
         ******************************************************/
    
	/************************************************************************************************************
	(C) www.dhtmlgoodies.com, January 2006
	
	This is a script from www.dhtmlgoodies.com. You will find this and a lot of other scripts at our website.	
	
	Terms of use:
	You are free to use this script as long as the copyright message is kept intact. However, you may not
	redistribute, sell or repost it without our permission.
	
	Thank you!
	
	www.dhtmlgoodies.com
	Alf Magne Kalleland
	
	************************************************************************************************************/	

	
	var rectangleBorderWidth = 2;	// Used to set correct size of the rectangle with red dashed border
	var useRectangle = false;	
	var autoScrollSpeed = 4;	// Autoscroll speed	- Higher = faster
	
	/* The saveData function creates a string containing the ids of your dragable elements. 
	
	The format of this string is as follow
	
	id of item 1;id of item 2;id of item 3
	
	i.e. a semi colon separated list. The id is something you put in as "id" attribute of your dragable elements.
	
	*/
	
	function saveData()
	{
		var saveString = "";
		for(var no=0;no<dragableObjectArray.length;no++){
			if(saveString.length>0)saveString = saveString + ';';
			ref = dragableObjectArray[no];
			saveString = saveString + ref['obj'].id;
		}	
		
		alert(saveString);	// For demo only
		
		/* 	Put this item into a hidden form field and then submit the form 
		
		example:
		
		document.forms[0].itemOrder.value = saveString;
		document.forms[0].submit;
		
		On the server explode the values by use of server side script. Then update your database with the new item order
		
		*/
	}

	
	/* Don't change anything below here */
	
	
	var dragableElementsParentBox;
	var opera = navigator.appVersion.indexOf('Opera')>=0?true:false;
		
	var rectangleDiv = false;
	var insertionMarkerDiv = false;
	var mouse_x;
	var mouse_y;
	
	var el_x;
	var el_y;
		
	var dragDropTimer = -1;	// -1 = no drag, 0-9 = initialization in progress, 10 = dragging
	var dragObject = false;
	var dragObjectNextObj = false;
	var dragableObjectArray = new Array();
	var destinationObj = false;	
	var currentDest = false;
	var allowRectangleMove = true;
	var insertionMarkerLine;
	var dragDropMoveLayer;
	var autoScrollActive = false;
	var documentHeight = false;
	var documentScrollHeight = false;
	var dragableAreaWidth = false;
	
	function getTopPos(inputObj)
	{		
	  var returnValue = inputObj.offsetTop;
	  while((inputObj = inputObj.offsetParent) != null){
	  	if(inputObj.tagName!='HTML')returnValue += inputObj.offsetTop;
	  }
	  return returnValue;
	}
	
	function getLeftPos(inputObj)
	{
	  var returnValue = inputObj.offsetLeft;
	  while((inputObj = inputObj.offsetParent) != null){
	  	if(inputObj.tagName!='HTML')returnValue += inputObj.offsetLeft;
	  }
	  return returnValue;
	}
		
	function cancelSelectionEvent()
	{
		if(dragDropTimer>=0)return false;
		return true;
	}
	
	function getObjectFromPosition(x,y)
	{
		var height = dragObject.offsetHeight;
		var width = dragObject.offsetWidth;
		var indexCurrentDragObject=-5;
		for(var no=0;no<dragableObjectArray.length;no++){			
			ref = dragableObjectArray[no];			
			if(ref['obj']==dragObject)indexCurrentDragObject=no;
			if(no<dragableObjectArray.length-1 && dragableObjectArray[no+1]['obj']==dragObject)indexCurrentDragObject=no+1;
			if(ref['obj']==dragObject && useRectangle)continue;	
			if(x > ref['left'] && y>ref['top'] && x<(ref['left'] + (ref['width']/2)) && y<(ref['top'] + ref['height'])){
				if(!useRectangle && dragableObjectArray[no]['obj']==dragObject)return 'self';
				if(indexCurrentDragObject==(no-1))return 'self';
				return Array(dragableObjectArray[no],no);
			}
			
			if(x > (ref['left'] + (ref['width']/2)) && y>ref['top'] && x<(ref['left'] + ref['width']) && y<(ref['top'] + ref['height'])){
				if(no<dragableObjectArray.length-1){
					if(no==indexCurrentDragObject || (no==indexCurrentDragObject-1)){
						return 'self';
					}
					if(dragableObjectArray[no]['obj']!=dragObject){
						return Array(dragableObjectArray[no+1],no+1);
					}else{
						if(!useRectangle)return 'self';
						if(no<dragableObjectArray.length-2)return Array(dragableObjectArray[no+2],no+2);
					}
				}else{
					if(dragableObjectArray[dragableObjectArray.length-1]['obj']!=dragObject)return 'append';	
					
				}
			}
			if(no<dragableObjectArray.length-1){
				if(x > (ref['left'] + ref['width']) && y>ref['top'] && y<(ref['top'] + ref['height']) && y<dragableObjectArray[no+1]['top']){
					return Array(dragableObjectArray[no+1],no+1);
				}
			}
		}	
		if(x>ref['left'] && y>(ref['top'] + ref['height']))return 'append';				
		return false;	
	}
		
	function initDrag(e)
	{
		if(document.all)e = event;
		mouse_x = e.clientX;
		mouse_y = e.clientY;
		if(!documentScrollHeight)documentScrollHeight = document.documentElement.scrollHeight + 100;
		el_x = getLeftPos(this)/1;
		el_y = getTopPos(this)/1;
		dragObject = this;
		if(useRectangle){
			rectangleDiv.style.width = this.clientWidth - (rectangleBorderWidth*2) +'px';
			rectangleDiv.style.height = this.clientHeight - (rectangleBorderWidth*2) +'px';
			rectangleDiv.className = this.className;
		}else{
			insertionMarkerLine.style.width = '6px';
		}
		dragDropTimer = 0;
		dragObjectNextObj = false;
		if(this.nextSibling){
			dragObjectNextObj = this.nextSibling;
			if(!dragObjectNextObj.tagName)dragObjectNextObj = dragObjectNextObj.nextSibling;
		}
		initDragTimer();
		return false;
	}
	
	function initDragTimer()
	{
		if(dragDropTimer>=0 && dragDropTimer<10){
			dragDropTimer++;
			setTimeout('initDragTimer()',5);
			return;
		}
		if(dragDropTimer==10){
			
			if(useRectangle){
				dragObject.style.opacity = 0.5;
				dragObject.style.filter = 'alpha(opacity=50)';
				dragObject.style.cursor = 'default';
			}else{
				var newObject = dragObject.cloneNode(true);
				dragDropMoveLayer.appendChild(newObject);
			}
		}
	}
	
	
	function autoScroll(direction,yPos)
	{
		if(document.documentElement.scrollHeight>documentScrollHeight && direction>0)return;
		
		window.scrollBy(0,direction);
		
		if(direction<0){
			if(document.documentElement.scrollTop>0){
				mouse_y = mouse_y - direction;
				if(useRectangle){
					dragObject.style.top = (el_y - mouse_y + yPos) + 'px';
				}else{
					dragDropMoveLayer.style.top = (el_y - mouse_y + yPos) + 'px';
				}			
			}else{
				autoScrollActive = false;
			}
		}else{
			if(yPos>(documentHeight-50)){		

				mouse_y = mouse_y - direction;
				if(useRectangle){
					dragObject.style.top = (el_y - mouse_y + yPos) + 'px';
				}else{
					dragDropMoveLayer.style.top = (el_y - mouse_y + yPos) + 'px';
				}				
			}else{
				autoScrollActive = false;
			}
		}
		if(autoScrollActive)setTimeout('autoScroll('+direction+',' + yPos + ')',5);
	}
	
	function moveDragableElement(e)
	{
		if(document.all)e = event;

		if(dragDropTimer<10)return;
		if(!allowRectangleMove)return false;
		
		
		if(e.clientY<50 || e.clientY>(documentHeight-50)){
			if(e.clientY<50 && !autoScrollActive){
				autoScrollActive = true;
				autoScroll((autoScrollSpeed*-1),e.clientY);
			}
			
			if(e.clientY>(documentHeight-50) && document.documentElement.scrollHeight<=documentScrollHeight && !autoScrollActive){
				autoScrollActive = true;
				autoScroll(autoScrollSpeed,e.clientY);
			}
		}else{
			autoScrollActive = false;
		}
		if(useRectangle){			
			if(dragObject.style.position!='absolute'){
				dragObject.style.position = 'absolute';
				setTimeout('repositionDragObjectArray()',50);
			}
		}		
	
		if(useRectangle){
			rectangleDiv.style.display='block';
		}else{
			insertionMarkerDiv.style.display='block';	
			dragDropMoveLayer.style.display='block';	
		}
		
		if(useRectangle){
			dragObject.style.left = (el_x - mouse_x + e.clientX + Math.max(document.body.scrollLeft,document.documentElement.scrollLeft)) + 'px';
			dragObject.style.top = (el_y - mouse_y + e.clientY) + 'px';
		}else{
			dragDropMoveLayer.style.left = (el_x - mouse_x + e.clientX + Math.max(document.body.scrollLeft,document.documentElement.scrollLeft)) + 'px';
			dragDropMoveLayer.style.top = (el_y - mouse_y + e.clientY) + 'px';
		}
		dest = getObjectFromPosition(e.clientX+Math.max(document.body.scrollLeft,document.documentElement.scrollLeft),e.clientY+Math.max(document.body.scrollTop,document.documentElement.scrollTop));
		
		if(dest!==false && dest!='append' && dest!='self'){
			destinationObj = dest[0]; 
			
			if(currentDest!==destinationObj){
				currentDest = destinationObj;
				if(useRectangle){
					destinationObj['obj'].parentNode.insertBefore(rectangleDiv,destinationObj['obj']);
					repositionDragObjectArray();
				}else{
					if(dest[1]>0 && (dragableObjectArray[dest[1]-1]['obj'].offsetLeft + dragableObjectArray[dest[1]-1]['width'] + dragObject.offsetWidth) < dragableAreaWidth){
						insertionMarkerDiv.style.left = (getLeftPos(dragableObjectArray[dest[1]-1]['obj']) + dragableObjectArray[dest[1]-1]['width'] + 2) + 'px';
						insertionMarkerDiv.style.top = (getTopPos(dragableObjectArray[dest[1]-1]['obj']) - 2) + 'px';
						insertionMarkerLine.style.height = dragableObjectArray[dest[1]-1]['height'] + 'px';
					}else{					
						insertionMarkerDiv.style.left = (getLeftPos(destinationObj['obj']) - 8) + 'px';
						insertionMarkerDiv.style.top = (getTopPos(destinationObj['obj']) - 2) + 'px';
						insertionMarkerLine.style.height = destinationObj['height'] + 'px';
					}
					
					
				}
			}
		}
		
		if(dest=='self' || !dest){
			insertionMarkerDiv.style.display='none';
			destinationObj = dest;	
		}
		
		if(dest=='append'){
			if(useRectangle){
				dragableElementsParentBox.appendChild(rectangleDiv);
				dragableElementsParentBox.appendChild(document.getElementById('clear'));
			}else{
				var tmpRef = dragableObjectArray[dragableObjectArray.length-1];
				insertionMarkerDiv.style.left = (getLeftPos(tmpRef['obj']) + 2) + tmpRef['width'] + 'px';
				insertionMarkerDiv.style.top = (getTopPos(tmpRef['obj']) - 2) + 'px';
				insertionMarkerLine.style.height = tmpRef['height'] + 'px';	
			}
			destinationObj = dest;
			repositionDragObjectArray();
		}	
		
		if(useRectangle && !dest){
			destinationObj = currentDest;
		}
		
		allowRectangleMove = false;
		setTimeout('allowRectangleMove=true',50);
	}
	
	function stop_dragDropElement()
	{
		dragDropTimer = -1;
		
		if(destinationObj && destinationObj!='append' && destinationObj!='self'){
			destinationObj['obj'].parentNode.insertBefore(dragObject,destinationObj['obj']);
		}
		if(destinationObj=='append'){
			dragableElementsParentBox.appendChild(dragObject);
			dragableElementsParentBox.appendChild(document.getElementById('clear'));
		}
		
		if(dragObject && useRectangle){
			dragObject.style.opacity = 1;
			dragObject.style.filter = 'alpha(opacity=100)';
			dragObject.style.cursor = 'move';
			dragObject.style.position='static';
		}
		rectangleDiv.style.display='none';
		insertionMarkerDiv.style.display='none';
		dragObject = false;
		currentDest = false;
		resetObjectArray();
		destinationObj = false;
		if(dragDropMoveLayer){
			dragDropMoveLayer.style.display='none';
			dragDropMoveLayer.innerHTML='';
		}
		autoScrollActive = false;
		documentScrollHeight = document.documentElement.scrollHeight + 100;
	}
	
	function cancelEvent()
	{
		return false;
	}
	
	function repositionDragObjectArray()
	{
		for(var no=0;no<dragableObjectArray.length;no++){
			ref = dragableObjectArray[no];
			ref['left'] = getLeftPos(ref['obj']);
			ref['top'] = getTopPos(ref['obj']);			
		}	
		documentScrollHeight = document.documentElement.scrollHeight + 100;
		documentHeight = document.documentElement.clientHeight;
	}
	
	function resetObjectArray()
	{
		dragableObjectArray.length=0;
		var subDivs = dragableElementsParentBox.getElementsByTagName('*');
		var countEl = 0;

		for(var no=0;no<subDivs.length;no++){
			var attr = subDivs[no].getAttribute('dragableBox');
			if(opera)attr = subDivs[no].dragableBox;
			if(attr=='true'){
				var index = dragableObjectArray.length;
				dragableObjectArray[index] = new Array();
				ref = dragableObjectArray[index];
				ref['obj'] = subDivs[no];
				ref['width'] = subDivs[no].offsetWidth;
				ref['height'] = subDivs[no].offsetHeight;
				ref['left'] = getLeftPos(subDivs[no]);
				ref['top'] = getTopPos(subDivs[no]);
				ref['index'] = countEl;
				countEl++;
			}
		}	
	}
	

	
	function initdragableElements()
	{
		dragableElementsParentBox = document.getElementById('dragableElementsParentBox');
		insertionMarkerDiv = document.getElementById('insertionMarker');
		insertionMarkerLine = document.getElementById('insertionMarkerLine');
		dragableAreaWidth = dragableElementsParentBox.offsetWidth;
		
		if(!useRectangle){
			dragDropMoveLayer = document.createElement('DIV');
			dragDropMoveLayer.id = 'dragDropMoveLayer';		
			document.body.appendChild(dragDropMoveLayer);	
		}
		
		var subDivs = dragableElementsParentBox.getElementsByTagName('*');
		var countEl = 0;
		for(var no=0;no<subDivs.length;no++){
			var attr = subDivs[no].getAttribute('dragableBox');
			if(opera)attr = subDivs[no].dragableBox;
			if(attr=='true'){
				subDivs[no].style.cursor='move';	
				subDivs[no].onmousedown = initDrag;
				
				var index = dragableObjectArray.length;
				dragableObjectArray[index] = new Array();
				ref = dragableObjectArray[index];
				ref['obj'] = subDivs[no];
				ref['width'] = subDivs[no].offsetWidth;
				ref['height'] = subDivs[no].offsetHeight;
				ref['left'] = getLeftPos(subDivs[no]);
				ref['top'] = getTopPos(subDivs[no]);
				ref['index'] = countEl;
				countEl++;
			}
		}
		
		/* Creating rectangel indicating where item will be dropped */
		rectangleDiv = document.createElement('DIV');
		rectangleDiv.id='rectangle';
		rectangleDiv.style.display='none';
		dragableElementsParentBox.appendChild(rectangleDiv);
		
		
		document.body.onmousemove = moveDragableElement;
		document.body.onmouseup = stop_dragDropElement;
		document.body.onselectstart = cancelSelectionEvent;
		document.body.ondragstart = cancelEvent;
		window.onresize = repositionDragObjectArray; 
		
		documentHeight = document.documentElement.clientHeight;
	}
	
	window.onload = initdragableElements;
	
	</script>



在网页<body>区添加以下代码
<div id="mainContainer">
	<!-- START DRAGABLE CONTENT -->
	<div id="dragableElementsParentBox">
		<div class="bigArticle" dragableBox="true" id="article1">
			<h4>Heading 1</h4>
			<p>Splendida porro oculi fugitant vitantque tueri. sol etiam caecat, contra si tendere pergas,propterea quia vis magnast ipsius et altea�ra per purum simulacra ferunturet feriunt oculos turbantia composituras.</p>
		</div>
		<div class="smallArticle" dragableBox="true" id="article2">
			<h4>Heading 2</h4>
			<p>Splendida porro oculi fugitant vitantque tueri. sol etiam caecat, contra si tendere pergas,propterea quia vis magnast.</p>
		</div>
		<div class="smallArticle" dragableBox="true" id="article3">
			<h4>Heading 3</h4>
			<p>Splendida porro oculi fugitant vitantque tueri. sol etiam caecat, contra si tendere pergas,propterea quia vis magnast.</p>
		</div>
		<div class="bigArticle" dragableBox="true" id="article4">
			<h4>Heading 4</h4>
			<p>Splendida porro oculi fugitant vitantque tueri. sol etiam caecat, contra si tendere pergas,propterea quia vis magnast ipsius et altea�ra per purum simulacra ferunturet feriunt oculos turbantia composituras.</p>
		</div>		
		<div class="smallArticle" dragableBox="true" id="article5">
			<h4>Heading 5</h4>
			<p>Splendida porro oculi fugitant vitantque tueri. sol etiam caecat, contra si tendere pergas,propterea quia vis magnast.</p>
		</div>
		<div class="smallArticle" dragableBox="true" id="article6">
			<h4>Heading 6</h4>
			<p>Splendida porro oculi fugitant vitantque tueri. sol etiam caecat, contra si tendere pergas,propterea quia vis magnast.</p>
		</div>
		<div class="bigArticle" dragableBox="true" id="article7">
			<h4>Heading 7</h4>
			<p>Splendida porro oculi fugitant vitantque tueri. sol etiam caecat, contra si tendere pergas,propterea quia vis magnast ipsius et altea�ra per purum simulacra ferunturet feriunt oculos turbantia composituras.</p>
		</div>	
		<div class="bigArticle" dragableBox="true" id="article8">

			<h4>Heading 8</h4>
			<p>Splendida porro oculi fugitant vitantque tueri. sol etiam caecat, contra si tendere pergas,propterea quia vis magnast ipsius et altea�ra per purum simulacra ferunturet feriunt oculos turbantia composituras.</p>
		</div>	
		<div class="bigArticle" dragableBox="true" id="article9">
			<h4>Heading 9</h4>
			<p>Splendida porro oculi fugitant vitantque tueri. sol etiam caecat, contra si tendere pergas,propterea quia vis magnast ipsius et altea�ra per purum simulacra ferunturet feriunt oculos turbantia composituras.</p>
		</div>					
		<div class="clear" id="clear"></div>		
	</div>
	<!-- END DRAGABLE CONTENT -->
	<input type="button" value="Save" onclick="saveData()">
</div>
<!-- REQUIRED DIVS -->
<div id="insertionMarker">
	<img src="images/marker_top.gif">
	<img src="images/marker_middle.gif" id="insertionMarkerLine">
	<img src="images/marker_bottom.gif">
</div>
<!-- END REQUIRED DIVS -->



下载图片
网页中用到三个图片,点击这里下载. 把图片放到images文件夹,并在网页里调用如下:

<div id="insertionMarker">
  <img src="images/marker_top.gif">
  <img src="images/marker_middle.gif" id="insertionMarkerLine">
  <img src="images/marker_bottom.gif">
</div>



程序配置
指定拖动内容
所有的可拖动框都使用纯HTML代码定义. Example:

<div id="dragableElementsParentBox">
  <div class="bigArticle" dragableBox="true" id="article1">
    <h4>Heading 1</h4>
    <p>Splendida porro oculi fugitant vitantque tueri</p>
  </div>
  <div class="smallArticle" dragableBox="true" id="article2">
    <h4>Heading 2</h4>
    <p>Splendida porro oculi fugitant vitantque tueri</p>
  </div>
  <div class="smallArticle" dragableBox="true" id="article3">
    <h4>Heading 3</h4>
    <p>Splendida porro oculi fugitant vitantque tueri</p>
  </div>
  <div class="clear" id="clear"></div>    
</div> 


首先我们定义了 <div id="dragableElementsParentBox"> 为所有可拖动元素的根结点. 内该节点内部定义可拖动的box,所有的可拖动的box都必须拥有dragablebox属性,dragableBox="true".

记住,每一个可拖动的box都必须有一个唯一的ID ,这些ID在保存数据时需要用到.

Javascript变量设置
在 <SCRIPT> 区域的最上面,有三个JavaScript变量,我么可以自定义其值:

var rectangleBorderWidth = 2;
var useRectangle = false;
var autoScrollSpeed = 4;


rectangleBorderWidth = 拖动框的虚线宽度.
useRectangle = 定义是否使用虚线框作为放置模块的区域. 如果要使用虚线框设置为True,如果要使用黑色线条设置为false.
autoScrollSpeed = 当你把模块拖动到浏览器的最上方或者最下方时,滚动条会相应的滚动. 这个变量用于定义滚动的速度,值越大滚动得越快

保存布局数据
在完成框架拖动后,你可以通过 saveData() 函数来保存数据. 这个函数会生成一个用分号分隔的字符串,分割的内容就是各个模块的编号. 如: 'item 1;item 2;item 3;item 5;item 4';. 你需要创建一个form,在form内放一个隐藏于,然后把值放在这个隐藏域内,这个操作代码要放在saveData() 函数的最后. 如:

document.forms[0].itemOrder.value = saveString;
document.forms[0].submit; 


当然你可以创建一个服务器端文件,把最后的布局保存到数据库中

下载"JavaScript拖拽给网页布局效果,酷"

  • 本地下载
  • 本地下载2

相关资源