1. 程式人生 > >利用jQuery UI為CMS網站實現拖拽佈局效果,秒殺table佈局

利用jQuery UI為CMS網站實現拖拽佈局效果,秒殺table佈局

實現效果

    對於使用過CMS系統製作網站的人應該都清楚,製作網站過程有一個重要的步驟就是製作頁面佈局。目前,實現頁面佈局有兩種方式:tablediv。這兩種方式各有其優劣之處。

    Table

    優勢:使用簡單,使用表格進行佈局順理成章,概念和效果圖理解起來很簡單,製作也方便。

    劣勢:表格佈局比較固定,佈局效果控制的比較死,一些較為特殊的效果、層疊效果等比較難以實現。

    Div

    優勢:佈局效果靈活,div能輕易的控制佈局位置,浮動效果等。

    劣勢:操作較為複雜,需要前端佈局設計人員對div的特性、層疊樣式等都較為熟悉。

    可以看出,其實table

div這兩種佈局方式是互為優劣的。但是目前來說div越來越成為一種主流設計方式,其佈局效果靈活、樣式新穎的特點也越來越受到青睞。而且這裡我們所講的,如果你想使用拖拽的方式輕鬆實現頁面佈局,那非div不可。如圖:


    如下圖,可以將佈局div拖入佈局區,使用滑鼠拖拽隨意移動其位置,同時可以將其選中,使用鍵盤進行各個方向的位置移動,還可以delete鍵將其刪除。另外,還可以使用滑鼠拖拽其右下角改變div的大小。


    雙擊某個div後,會彈出屬性對話方塊。可以輸入div的寬度,高度,還可以在文字區中加入div中的內容。


使用工具

    整個工具使用jQueryUI來製作。製作過程用到了

jQueryUI的包含的以下成員:

    1) Accordion

    用於實現左側楓葉選單,div來源基於此處。

    2) Draggable

    拖拽項即使用Draggable來實現。

    3) Droppable

    Droppable用來實現佈局釋放區。

    4) Resizable

    Resizable用來實現對div大小的拖拽設定效果。

    5) Dialog

    Dialog用來製作雙擊div時彈出的屬性對話方塊。 

實現過程

3.1 增加左側摺疊導航

    增加左側摺疊導航,用到了jQueryUI中的Accordion,效果如圖:


    程式碼:

        //增加摺疊效果
	$("#catalog").accordion( {
		heightStyle : "fill"
	});
	//使<li>標籤中的元素可拖拽
	$("#catalog li").draggable( {
		appendTo : "body",//用來指定控制元件在拖拽過程中ui.helper的容器, 預設情況下, ui.helper使用和初始定義的draggable相同的容器, 也就是其父元素.預設值  "parent"
		helper : "clone" //拖拽元素時的顯示方式。(如果是函式,必須返回值是一個DOM元素)可選值:"original", "clone", Function預設值  "original"
	});

3.2 設定佈局畫布

    列表項已經可以拖拽了,現在還需要有地方可以接收這些元素。我們要實現的效果是,從左側列表拖出,放入右面的佈局畫布區域,因此要將佈局畫布區域設定為接收區,jQueryUI提供了Droppable來實現這個效果:

var bordNum = 0;

	$("#pageAreaWrapper div")
			.droppable(
					{
						activeClass : "ui-state-default",
						hoverClass : "ui-state-hover",
						accept : ".item",
						drop : function(event, ui) {
							//$(this).find(".placeholder").remove();
						var divContent = "";
						
						//生成佈局介面的div
						var ss = $("<div id=\"border_"
								+ ++bordNum
								+ "\" class=\"item-accepted componentWrapper\" style=\"position: absolute; z-index: 101;\">"
									+ "<div class=\"shield\" style=\"position:absolute\">"
									+ "</div>"
									+ "<div class=\"wrapperBorder\" style=\"background-color: transparent; border: 0px solid transparent; opacity: 1;\">"
										+ "<div class=\"wrapperPadding\">"
											+ "<div class=\"wrapperContent\" style=\"width: 320px; height:240px; word-break:break-all\">"
											+ divContent
											+ "</div>"
										+ "</div>" 
									+ "</div>" 
								+ "</div>");

						//ss.text(ui.draggable.text()).appendTo(this);
						ss.appendTo(this);

						//獲取拖入位置
						var px = ui.position.left;
						var py = ui.position.top;

						//獲取佈局畫布pageArea的在整個頁面的絕對偏移量
						var pageArea_px = $("#pageArea")[0].offsetLeft;
						//此處加上73是因為外層的table的top位置為73
						var pageArea_py = $("#pageArea")[0].offsetTop + 73;
						
						//alert("cart2_px=" + cart2_px + ", cart2_py=" + cart2_py);
						
						//獲取滾動條滾動距離
						var scrollpx = $("#bodyOfPage").scrollLeft();
						var scrollpy = $("#bodyOfPage").scrollTop();

						//剛拖入時的位置,要考慮到滾動條的因素
						setPosition(ss, px - pageArea_px + scrollpx, py - pageArea_py + scrollpy);

						ss.draggable( {
							containment : "#pageAreaWrapper",
							scroll : false,
							stop : function(event, ui) {
			
							}
						});
						
						//雙擊div,編輯div內部內容
						ss.dblclick(function() {
										
										var dialog;
										
										dialog = $( "#dialog-form" ).dialog({
											autoOpen: false,
											height: 400,
											width: 450,
											modal: true,
											buttons: {
											OK: function() {
													var valid = true;
							
													if ( valid ) {
														var content = dialog.find("#content");	
														var divWidth = dialog.find("#divWidth");
														var divHeight = dialog.find("#divHeight");
														//alert(divWidth.val() + " " + divHeight.val());
														
														ss.css('width', divWidth.val());
														ss.find(".wrapperContent").css('width', divWidth.val());
														ss.css('height', divHeight.val());
														ss.find(".wrapperContent").css('height', divHeight.val());
														
														ss.find(".wrapperContent").html(content.val());
														dialog.dialog( "close" );
													}
													return valid;
												},
											Cancel: function() {
														dialog.dialog( "close" );
													}
											},
											close: function() {
												//form[ 0 ].reset();
												//allFields.removeClass( "ui-state-error" );
											},
											open: function(event, ui) {
												//dialogSource = 
											}
										});
										
										//設定textarea的值需要用val()函式,html()函式設定不成功
										dialog.find("#content").val(ss.find(".wrapperContent").html());
										dialog.find("#divWidth").val(ss.css("width"));
										dialog.find("#divHeight").val(ss.css("height"));
										
										dialog.dialog( "open" );
									}		
						);

						//定義點選選中事件
						$("*")
								.click(function(event, ui) {//alert(event.currentTarget.id);
										//每次點選都是先取消選中,然後再讓相應元素被選中
										$(".selected").removeClass("selected");
										if (event.currentTarget
												.getAttribute("class") == "shield") {//alert(1);

											$(this).parent().find(
													".wrapperBorder").addClass(
													"selected");
											return false;
										} 
									/*	else if ($(this).hasClass(
												"componentWrapper")) {//alert(2);

											$(this).find(".wrapperBorder")
													.addClass("selected");

										}*/
										//else {
										//	$(".wrapperBorder").removeClass("selected");	
										//}

										//只啟用第一次點選,之後停止起泡
										//return false;

									});

						//調整大小時同時將內層div大小調整
						$(".componentWrapper").resizable(
								{
									autoHide : true,
									resize : function(event, ui) {
										//alert($(this).width());
										$(this).find(".wrapperContent").css(
												"width", $(this).width());
										$(this).find(".wrapperContent").css(
												"height", $(this).height());
									}
								});

					}
					});

    這裡需要說明:

    1. 為了使每個被拖出來的divid都不一樣,設定了一個變數“bordNum”來標識。

    2. 每個被拖出來的div,也就是ss,需要再次設定為Droppable,才能使其在畫布中也能夠被拖動。

    3. 為了可以使用滑鼠選中某個div,需要為div動態增加樣式,而且要注意獲取物件並動態增加了樣式之後就要通過“return false”來阻止事件冒泡

    4. 剛拖入時,放入位置還要考慮到滾動條的因素

    5. 通過設定divResizable使其可以被拖拽調整大小

3.3 鍵盤動作

    鍵盤動作主要有選中後:

    向上移動一個畫素;

    向下移動一個畫素;

    向左移動一個畫素;

    向右移動一個畫素;

    刪除。

    程式碼:

$(document).ready(function() {
	divFullScreen();//頁面載入時全屏
		$(window).bind('resize', function() {
			divFullScreen();//最大化,還原視窗大小時DIV尺寸跟著變化,不過最好在CSS裡給這個DIV加個min-width等於html,body的最小寬度。
			});

		//定義鍵盤移動div位置事件
		$(document).keydown(function(event) {

			var x = $(".selected").parent().position().top;//水平方向位移
				var y = $(".selected").parent().position().left;//垂直方向位移

				switch (event.which) {
				//case 37: y = y - 10; $("border_1").css("left", y + "px"); break;
				case 37:
					if (y >= 1) {
						//alert(y);
						y = y - 1;
						//alert(y);
						$(".selected").parent().css("left", y + "px");
					} else {
						y = 0;
					}
					break;

				case 38:
					if (x > 1) {
						x = x - 1;
						$(".selected").parent().css("top", x + "px");
					} else {
						x = 0;
					}

					break;

				case 39:
					if (y < $("#pageAreaWrapper").width()
							- $(".selected").width()) {
						y = y + 1;
						$(".selected").parent().css("left", y + "px");
					} else {
						y = $("#pageAreaWrapper").width();
					}

					break;

				case 40:
					x = x + 1;
					$(".selected").parent().css("top", x + "px");
					break;
				
				case 46:
					$(".selected").parent().remove();
					break;

				default:
					break;
				}
				//返回false是為了停止冒泡,以便點選鍵盤向下鍵時頁面不隨著移動
				return false;
			});

	});