Converting standard show/hide jQuery code to plain JS

hi,

I have to do in plain JavaScript something that I’m much more used to doing in jQuery… this is for a standard tabbed-content show/hide div switcheroo… here’s the jQuery code:

$('.tabs a').click(function(e) {
	e.preventDefault();
	$('.tab_content_wrapper').hide();
	$('.tab_content_wrapper').eq( $(this).index('.tabs a') ).show();
	$('.tabs a').removeClass('tab_on').addClass('tab_off');
	$(this).addClass('tab_on').removeClass('tab_off');
});

the main difficulty in doing this in plain JS is in grabbing which anchor was clicked…

this did not do the trick…

[INDENT]if ( document.addEventListener ) {
tabs.childNodes[i].addEventListener(“click”, function(){ this.style.border = ‘1px solid red’; }, false);
} else if ( document.attachEvent ) {
tabs.childNodes[i].attachEvent (“click”, function(){ this.style.border = ‘1px solid red’; });
}[/INDENT]

‘this’ evidently does not refer to the element that was clicked on…

also, can you refer to elements by their class name?

also, is it possible to do event-binding in plain JavaScript w/o using individual id’s for the clicked-on elements? like I did, (thanks to help from people at the jQuery forums) in the code I posted above? if not I don’t mind using element id’s, but still, if possible would like something like if second tabbed was clicked show 2nd div…

would appreciate some help & suggestions as to how to convert this jQuery functionality to plain JS…

thank you…

(PS: can’t use

 tags..  they mess things up.. hide part of the post..  (I guess new interface still a bit buggy...;-) )

the main difficulty in doing this in plain JS is in grabbing which anchor was clicked…

this did not do the trick…

if ( document.addEventListener ) {
tabs.childNodes[i].addEventListener("click", function(){ this.style.border = '1px solid red'; }, false);
} else if ( document.attachEvent ) {
tabs.childNodes[i].attachEvent ("click", function(){ this.style.border = '1px solid red'; });
}

‘this’ evidently does not refer to the element that was clicked on…

This is a guess:


// Source: Sitepoint book, Simply Javascript
document.getElementsByClass = function(theClass) {
	var elementArray = [];
	if (typeof document.all != "undefined") {
  		elementArray = document.all;
	} else {
  		elementArray = document.getElementsByTagName("*");
	}
	var matchedArray = [];
	var pattern = new RegExp("(^| )" + theClass + "( |$)");
	for (var i = 0; i < elementArray.length; i++) {
  		if (pattern.test(elementArray[i].className)) {
      		matchedArray[matchedArray.length] = elementArray[i];
		}
  	}
  	return matchedArray;
};

// From http://ejohn.org/projects/flexible-javascript-events/
function addEvent( obj, type, fn ) {
	if ( obj.attachEvent ) {
		obj['e' + type + fn] = fn;
		obj[type + fn] = function(){
			obj['e' + type + fn]( window.event );
		}
		obj.attachEvent( 'on' + type, obj[type+fn] );
	} else {
		obj.addEventListener( type, fn, false );
	}
}	

var tabs = document.getElementsByClass('.tabs')
	tabsA = tabs.getElementsByTagName('a');
for( var i=0; i<tabsA.length; i++ ) {
	addEvent(tabsA[i], 'click', function(){
		// your code here
	});
}

also, can you refer to elements by their class name?

also, is it possible to do event-binding in plain JavaScript w/o using individual id’s for the clicked-on elements?

See the code above.

this is for a standard tabbed-content show/hide div switcheroo…

Like this? (tested in FF/Chrome only - addEventlistener & forEach)

<!DOCTYPE html>
<html>
	<head>
		<style>
			li { display: inline; }
			#tabs > div { display: none; } 
			#tabs > div.current { display: block; }  		
		</style>	
	</head>
	<body>
		<ul>
			<li><a href="#test-1">Test 1</a></li>
			<li><a href="#test-2">Test 2</a></li>
			<li><a href="#test-3">Test 3</a></li>
		</ul>
		<div id="tabs">
			<div id="test-1" class="current">Test 1 Div</div>
			<div id="test-2">Test 2 Div</div>
			<div id="test-3">Test 3 Div</div>
		</div>
		<script>
			// Source: Sitepoint book, Simply Javascript
			document.getElementsByClass = function(theClass) {
				var elementArray = [];
				if (typeof document.all != "undefined") {
			  		elementArray = document.all;
				} else {
			  		elementArray = document.getElementsByTagName("*");
				}
				var matchedArray = [];
				var pattern = new RegExp("(^| )" + theClass + "( |$)");
				for (var i = 0; i < elementArray.length; i++) {
			  		if (pattern.test(elementArray[i].className)) {
			      		matchedArray[matchedArray.length] = elementArray[i];
					}
			  	}
			  	return matchedArray;
			};
					
			window.onload = function() {		
				window.addEventListener(
					'hashchange', 
					function() {	
						var currentDivs = document.getElementsByClass('current'),
							currPageEl 	= document.getElementById(location.hash.substring(1));
							
							currentDivs.forEach(function(el,i) {
								currentDivs[i].removeAttribute('class');
							});
							currPageEl.setAttribute('class','current');
					},
					false
				);
			};							
		</script>
	</body>
</html>

thank you very very much for posting all that code…

as expected (and as you hinted) of course it doesn’t work in IE…:wink:

you say "add addEventlistener " you meant add attachEvent, right? addEventListener is there already… (and of course it does work in all browsers except IE…) so I did:

if (document.all) {
		
		window.onload = function() {		
			window.attachEvent(
				'hashchange', 
				function() {	
					var currentDivs = document.getElementsByClass('current'),
						currPageEl 	= document.getElementById(location.hash.substring(1));
						
						currentDivs.forEach(function(el,i) {
							currentDivs[i].removeAttribute('class');
						});
						currPageEl.setAttribute('class','current');
				}
			);
		};		
		
	
	}  else {	// yr code AddEventListener code...  

but this is not working in IE (took out that third param for AttachEvent, since it only takes two params (judging by examples I have seen…)

I also have questions: what is ‘hashchange’??? and how is event-binding done for ‘click’ event here? I don’t see ‘onclick’ anywhere here…

thank you very much…

The first code example has the click event. The second was an alternative.

Sent from my ADR6300 using Tapatalk

As stated the click example was shown above but I will show a basic example here using click and hashchange.

Using this HTML and JS lib:


<ul>
	<li><a href="#test-1" class="tabLink">Test 1</a></li>
	<li><a href="#test-2" class="tabLink">Test 2</a></li>
	<li><a href="#test-3" class="tabLink">Test 3</a></li>
</ul>
<div id="tabs">
	<div id="test-1" class="current">Test 1 Div</div>
	<div id="test-2">Test 2 Div</div>
	<div id="test-3">Test 3 Div</div>
</div>
<script>
// Source: Sitepoint book, Simply Javascript
document.getElementsByClass = function(theClass) {
	var elementArray = [];
	if (typeof document.all != "undefined") {
  		elementArray = document.all;
	} else {
  		elementArray = document.getElementsByTagName("*");
	}
	var matchedArray = [];
	var pattern = new RegExp("(^| )" + theClass + "( |$)");
	for (var i = 0; i < elementArray.length; i++) {
  		if (pattern.test(elementArray[i].className)) {
	  		matchedArray[matchedArray.length] = elementArray[i];
		}
  	}
  	return matchedArray;
};

// From http://ejohn.org/projects/flexible-javascript-events/
function addEvent( obj, type, fn ) {
	if ( obj.attachEvent ) {
		obj['e' + type + fn] = fn;
		obj[type + fn] = function(){
			obj['e' + type + fn]( window.event );
		}
		obj.attachEvent( 'on' + type, obj[type+fn] );
	} else {
		obj.addEventListener( type, fn, false );
	}
}	
</script>

Click just listens for the click event and the href is disregarded ie preventDefault():


window.onload = function() {
	var tabLinks = document.getElementsByClass('tabLink'),
		i;
	for(i = 0; i < tabLinks.length; i++) {
		addEvent(
			tabLinks[i], 
			'click', 
			function(e) { 
				var currDiv  = document.getElementsByClass('current'),
					newDiv = document.getElementById(this.href.split('#')[1]),
					j;
				e.preventDefault();
				for(j = 0; j < currDiv.length; j++) {
					currDiv[j].removeAttribute('class');
				}
				newDiv.setAttribute('class','current');	
			}
		);	
	}
};

Hashchange listens to the URL#hash and reacts to that listener if changed:


window.onload = function() {		
	addEvent(
		window, 
		'hashchange', 
		function() {	
			var currentDivs = document.getElementsByClass('current'),
				currPageEl 	= document.getElementById(location.hash.substring(1)),
				i;
			
			for(i = 0; i < currentDivs.length; i++) {	
				currentDivs[i].removeAttribute('class');
			}
			currPageEl.setAttribute('class','current');
		}
	);
};	

You see preventDefault isn’t present because we want the A tag to do its thing so we can capture the URL#hash in location.hash