jQueryでタブ切り替え。バグるコードとバグらないコードを比較してみた。

タブ切り替え的なUIを作った。
バグるコードとバグらないコードをメモしておく。

バグるコード。
chrome33で、
素早くタブ切り替えをするとバグる。
フラグで切り替えたりしてても時々バグる。
処理中に別の処理が並行して走るからバグってしまうみたい。
比較的処理がゆっくりなIE8とかだとバグらない。
具体的にどこでエラーを起こしてるのかはよくわからなかった。

$(function(){
	//画像の先読み
	jQuery.preloadImages = function(){
		for(var i = 0; i<arguments.length; i++){
			jQuery('<img>').attr('src', arguments[i]);
		}
	};
	$.preloadImages('/img/btn01_on.png','/img/btn02_on.png','/img/btn03_on.png','/img/btn04_on.png','/img/btn05_on.png','/img/btn01_selected.png','/img/btn02_selected.png','/img/btn03_selected.png','/img/btn04_selected.png','/img/btn05_selected.png','/img/tab02.jpg','/img/tab03.jpg','/img/tab04.jpg','/img/tab05.jpg');
	
	
	$(window).load(function(){
		var onName = '_on';
		var offName = '_off';
		var selectedName = '_selected';	
		var imgBefore = '/img/btn_';
		var imgAfteron = '_on.png';
		var imgAfteroff = '_off.png';
		var imgAfterselected = '_selected.png';
		
		//サムネイルクリック時の挙動
		
		var changeflag = true;
		
		function changeImg() {
			$('#packageWrap li img').each(function(){
				var	thisattr = $(this).attr('src').replace(selectedName, offName).replace(onName, offName);
				$(this).attr('src',thisattr);
			});
		};
		
		$('#packageWrap li img').on({
			'click':function(){
				if(changeflag = true){
					changeflag = false;
					$('#packageWrap li img').removeClass('selected');
					$(this).addClass('selected');
					changeImg();
					$('#detailBox>div').hide();
					openDiv = '#' + $(this).attr('src').replace(imgBefore, '').replace(imgAfteroff, '').replace(imgAfteron, '').replace(imgAfterselected, '');
					$(openDiv).show();
					this.setAttribute('src', this.getAttribute('src').replace(offName, selectedName).replace(onName, selectedName));
					changeflag = true;
				}else{
					return false;
				};
			},
			'mouseenter':function(){
				if($(this).attr('class') == 'selected'){
					return false;
				}else{
					this.setAttribute('src', this.getAttribute('src').replace(offName, onName));
				}
			},
			'mouseleave':function(){
				if($(this).attr('class') == 'selected'){
					return false;
				}else{
					this.setAttribute('src', this.getAttribute("src").replace(onName, offName));				
				}
			}
		});
	});
});

バグらないコード。
ひとつひとつif文で分岐しているからバグらない。
手抜きしないで丁寧に分岐させてあげるのが大事みたい。

$(function(){
	//画像の先読み
	jQuery.preloadImages = function(){
		for(var i = 0; i<arguments.length; i++){
			jQuery('<img>').attr('src', arguments[i]);
		}
	};
	$.preloadImages('/img/btn01_on.png','/img/btn02_on.png','/img/btn03_on.png','/img/btn04_on.png','/img/btn05_on.png','/img/btn01_selected.png','/img/btn02_selected.png','/img/btn03_selected.png','/img/btn04_selected.png','/img/btn05_selected.png','/img/tab02.jpg','/img/tab03.jpg','/img/tab04.jpg','/img/tab05.jpg');
	
	
	$(window).load(function(){
		pageTab();
	});
	
	function pageTab() {
		var imgBefore = '/img/btn_';
		var imgAfteron = '_on.png';
		var imgAfteroff = '_off.png';
		var imgAfterselected = '_selected.png';
		
		//クリックの処理
		$('#packageWrap li img').click(function(){
			$('#packageWrap li img').each(function(){
			if(String($(this).attr('src')).match(/_selected\.(.*)$/)){
				$(this).attr('src',$(this).attr('src').replace('_selected','_off'));
			}
			});

			if(String($(this).attr('src')).match(/_off\.(.*)$/)){
				$(this).attr('src',$(this).attr('src').replace('_off','_selected'));
			}else
	
			if(String($(this).attr('src')).match(/_on\.(.*)$/)){
				$(this).attr('src',$(this).attr('src').replace('_on','_selected'));
			}
			
			$('#detailBox>div').hide();
			openDiv = '#' + $(this).attr('src').replace(imgBefore, '').replace(imgAfteroff, '').replace(imgAfteron, '').replace(imgAfterselected, '');
			$(openDiv).show();
		});
	
	
		//ボタンのロールオーバー
		$('#packageWrap li img').hover(function(){
			$(this).attr('src',$(this).attr('src').replace('_off','_on'));
		},function(){
			$(this).attr('src',$(this).attr('src').replace('_on','_off'));
		});
	};
});

投稿者:

ayako0802

フロントエンドエンジニア