Tạo menu trượt với jQuery

Đăng bởi Neo trong mục Hướng dẫn vào 15 tháng 6, 2010 | Comments

Bài hướng dẫn tạo menu trượt với jQuery. Menu sẽ xuất hiện khi có một nút checkbox bất kỳ được chọn. Bạn có thể kéo menu tới bất kỳ vị trí nào bạn muốn

Bài hướng dẫn lấy ý tưởng từ phiên bản cho mobile của Gmail. Bạn có thể thấy menu này nếu mở gmail bằng Safari ở iPhone hoặc iPod Touch (mình chưa thử trên iPad).

Mã HTML

Trước tiên là một table đơn giản gồm có id và một vài checkboxes

<table id="mytable">
  <tr>
    <td class="check">
    	<input id="check_1" name="check_1" type="checkbox" value="1" />
    </td>
    <td>Some Content</td>
  </tr>
  <tr>
    <td class="check">
    	<input id="check_2" name="check_2" type="checkbox" value="2" />
    </td>
    <td>Some Content</td>
  </tr>
</table>

Và mã HTML sử dụng cho menu trượt:

<div id="actionsBox" class="actionsBox">
  <div id="actionsBoxMenu" class="menu">
    <span id="cntBoxMenu"></span>
    <a class="button box_action">Archive</a>
    <a class="button box_action">Delete</a>
    <a id="toggleBoxMenu" class="open"></a>
    <a id="closeBoxMenu" class="button">X</a>
  </div>
  <div class="submenu" style="display:none;">
    <a class="first box_action">Move...</a>
    <a class="box_action">Mark as read</a>
    <a class="box_action">Mark as unread</a>
    <a class="last box_action">Spam</a>
  </div>
</div>

Thẻ div với class submenu sẽ xuất hiện khi bạn click vào thẻ a nằm trong div#actionsBoxMenu

CSS

Tiếp theo sẽ là các style cho menu trượt. Hướng dẫn dưới đây sử dụng nhiều thuộc tính của CSS3, do vậy nếu muốn menu chạy trên nhiều trình duyệt bạn phải thay đổi lại các thuộc tính CSS và sử dụng ảnh nền

Ban đầu menu sẽ bị ẩn đi, vì thế div#actionBox sẽ có style như sau:

.actionsBox{
    font-size:13px;
    font-family: Arial,Verdana;
    font-style:normal;
    left:50%;
    position:absolute;
    top:-50px;
    opacity:0;
    cursor:move;
}

Style cho phần menu chính

.actionsBox .menu{
    color:#47708F;
    width:240px;
    line-height:30px;
    text-shadow:1px 1px 0px #fff;
    padding:7px;
    -moz-border-radius:5px;
    -webkit-border-radius:5px;
    border-radius:5px;
    font-weight:bold;
    border:1px solid #D9EAF2;
    background:#e8f4fa;
    background:
        -webkit-gradient(
        linear,
        left bottom,
        left top,
        color-stop(0.58, rgb(217,234,242)),
        color-stop(0.93, rgb(232,244,250))
        );
    background:
        -moz-linear-gradient(
        center bottom,
        rgb(217,234,242) 58%,
        rgb(232,244,250) 93%
        );
    -moz-box-shadow:1px 1px 3px #999;
    -webkit-box-shadow:1px 1px 3px #999;
    box-shadow:1px 1px 3px #999;
}

Phần dưới đây sử dụng nhiều thuộc tính của CSS3 như gradient, bo tròn, đổ bóng chữ...

.actionsBox .menu .button{
    padding:4px 7px;
    border:1px solid #D9EAF2;
    cursor:pointer;
    background:#e8f4fa;
    background:
        -webkit-gradient(
        linear,
        left bottom,
        left top,
        color-stop(0.38, rgb(230,243,249)),
        color-stop(0.88, rgb(245,249,250))
        );
    background:
        -moz-linear-gradient(
        center bottom,
        rgb(230,243,249) 38%,
        rgb(245,249,250) 88%
        );
    -moz-border-radius:5px;
    -webkit-border-radius:5px;
    border-radius:5px;
    -moz-box-shadow:0px 1px 0px #f9f9f9;
    -webkit-box-shadow:0px 1px 0px #f9f9f9;
    box-shadow:0px 1px 0px #f9f9f9;
}

Khi di chuột qua, chuyển nền thành màu trắng:

.actionsBox .menu .button:hover{
    background:#fff;
}

Thẻ span hiển thị số checkbox được chọn:

.actionsBox .menu span{
    padding:0px 10px;
}

Mặc định thì các menu con sẽ chỉ hiển thị khi click vào menu cha.

.actionsBox .submenu{
    display:none;
    width:120px;
    margin-left:100px;
    top:46px;
    right:10px;
    background:#fff;
    border:1px solid #D9EAF2;
    border-top:none;
    -moz-border-radius:0px 0px 10px 10px;
    -webkit-border-bottom-left-radius:10px;
    -webkit-border-bottom-right-radius:10px;
    border-bottom-left-radius:10px;
    border-bottom-right-radius:10px;
    -moz-box-shadow:0px 1px 4px #ddd;
    -webkit-box-shadow:0px 1px 4px #ddd;
    box-shadow:0px 1px 4px #ddd;
}
.actionsBox .submenu a{
    display:block;
    cursor:pointer;
    padding:10px 15px;
    border-top:1px solid #D9EAF2;
}

Thẻ a cuối cùng ở menu con có hiệu ứng bo tròn ở dưới:

.actionsBox .submenu a.last{
    -moz-border-radius:0px 0px 10px 10px;
    -webkit-border-bottom-left-radius:10px;
    -webkit-border-bottom-right-radius:10px;
    border-bottom-left-radius:10px;
    border-bottom-right-radius:10px;
}

Và thẻ a đầu tiên không có bo tròn trên đầu

.actionsBox .submenu a.first{
    border-top:none;
}
.actionsBox .submenu a:hover{
    background-color:#f9f9f9;
}

Style cho nút đóng/ mở

.actionsBox .menu a.open,
.actionsBox .menu a.closed{
    border:1px solid #D9EAF2;
    padding:4px 17px;
    -moz-border-radius:5px;
    -webkit-border-radius:5px;
    border-radius:5px;
    -moz-box-shadow:0px 1px 0px #f9f9f9;
    -webkit-box-shadow:0px 1px 0px #f9f9f9;
    box-shadow:0px 1px 0px #f9f9f9;
    cursor:pointer;
    opacity:0.6;
    margin-right:5px;
}
.actionsBox .menu a.open{
    background:#fff url(../open.png) no-repeat center center;
}
.actionsBox .menu a.closed{
    background:#fff url(../closed.png) no-repeat center center;
}
.actionsBox .menu a.open:hover,
.actionsBox .menu a.closed:hover{
    opacity:1.0;
}

Mã javascript

Sau khi xong HTML & CSS chúng ta sẽ sử dụng jQuery để tạo hiệu ứng và hoạt động cho menu

Trước tiên bạn cần thêm jQuery (1.4.2) và jQuery UI (1.7.2) vào trang HTML (Cần có jQuery UI vì chúng ta sẽ làm cho menu có thể kéo tới bất kỳ vị trí nào)

Thêm đoạn mã sau:

$(function() {
	/* Khai báo cho phép kéo menu hay không */
	var dragged = false;

	/* Thời gian menu trượt sau khi scroll trang web */
	var moveBoxTimeout;

	/* Đoạn mã cho phép kéo thả menu */
	$('#actionsBox').draggable({
		start: function(event, ui) {
			dragged = true;
		},
		stop: function(event, ui) {
			var $actionsBox = $('#actionsBox');
			/*
			Tính toán khoảng cách của menu so với cửa sổ trình duyệt
      sẽ sử dụng khi scroll chuột (menu trượt theo)
			 */
			$actionsBox.data('distanceTop',parseFloat($actionsBox.css('top'),10) - $(document).scrollTop());
		}
	});

	/*
	Khi click vào checkbox: 
  Thay đổi class của tr và hiển thị menu
	 */
	$('#mytable input[type="checkbox"]').bind('click',function(e) {
		var $this = $(this);
		if($this.is(':checked'))
			$this.parents('tr:first').addClass('selected');
		else
			$this.parents('tr:first').removeClass('selected');
		showActionsBox();
	});

	function showActionsBox(){
		/* Số lượng checkbox được chọn */
		var BoxesChecked = $('#mytable input:checked').length;
		/* Cập nhật số checkbox được chọn */
		$('#cntBoxMenu').html(BoxesChecked);
		/*
		Nếu không còn checkbox nào chọn, ẩn menu đi
		 */
		var $actionsBox = $('#actionsBox');
		if(BoxesChecked > 0){
			/*
			Nếu không kéo đi chỗ khác, menu vẫn ở nguyên vị trí cũ;
			 */
			if(!dragged)
				$actionsBox.stop(true).animate({
					'top': parseInt(15 + $(document).scrollTop()) + 'px',
					'opacity':'1'
				},500);
			else
				$actionsBox.stop(true).animate({
					'top': parseInt($(document).scrollTop() + $actionsBox.data('distanceTop')) + 'px',
					'opacity':'1'
				},500);
		}
		else{
			$actionsBox.stop(true).animate({
				'top': parseInt($(document).scrollTop() - 50) + 'px',
				'opacity':'0'
			},500,function(){
				$(this).css('left','50%');
				dragged = false;
				/* Nếu menu con vẫn mở thì ẩn đi */
				var $toggleBoxMenu = $('#toggleBoxMenu');
				if($toggleBoxMenu.hasClass('closed')){
					$toggleBoxMenu.click();
				}
			});
		}
	}

	/*
	Khi scroll trang, đoạn mã sau sẽ cho menu scroll theo
	 */
	$(window).scroll(function(){
		clearTimeout(moveBoxTimeout);
		moveBoxTimeout = setTimeout(showActionsBox,500);
	});

	/* Mở menu con */
	$('#toggleBoxMenu').toggle(
	function(e){
		$(this).addClass('closed').removeClass('open');
		$('#actionsBox .submenu').stop(true,true).slideDown();
	},
	function(e){
		$(this).addClass('open').removeClass('closed');
		$('#actionsBox .submenu').stop(true,true).slideUp();
	}
);

	/*
	Đóng menu con
	 */
	$('#closeBoxMenu').bind('click',function(e){
		$('#actionsBox').animate({
			'top':'-50px',
			'opacity':'0'
		},1000,function(){
			$(this).remove();
		});
	});

	/*
	Ví dụ nếu bạn click vào nút nào đó
	sẽ thông báo giá trị các checkbox
	 */
	$('#actionsBox .box_action').bind('click',function(e){
		var ids = '';
		$('#mytable input:checked').each(function(e,i){
			var $this = $(this);
			ids += 'id : ' + $this.attr('id') + ' , value : ' + $this.val() + '\n';
		});
		alert('checked inputs:\n'+ids);
	});
});

Nút đóng sẽ làm cho menu mất hoàn toàn. Bạn có thể thay đổi hàm để khi tiếp tục click vào checkbox menu sẽ xuất hiện

Hàm ví dụ cuối cùng là sự kiện khi bạn click nút nào đó ở menu. Tất nhiên bạn sẽ phải thay đổi hàm này khi áp dụng vào thực tế.

Và cuối cùng, đây là bài Neo dịch lại từ tympanus.net nên nếu xem tiếng Việt ko hiểu, bạn có thể xem bản gốc tại đây

Bạn có thích bài viết này?

Neo's picture

Neo

Nhìn mặt trời từ năm 1984 nhưng tới tận 2002 mới được thấy cái máy tính đầu tiên của mình. Đầu năm 2007 thì quyết định theo cái nghề cao quý là thiết kế web Big Grin. Hiện mình đang sống tại Hà Nội. Sở thích: làm website và giúp đỡ mọi người phát triển website theo chiều hướng tốt đẹp hơn.

Trang chủ - Twitter