Design Lunatic » jQuery https://www.designlunatic.com Just another WordPress site Tue, 12 Nov 2013 17:22:29 +0000 en-US hourly 1 http://wordpress.org/?v=3.6.1 Isotope infinite scroll https://www.designlunatic.com/2012/12/isotope-infinite-scroll/ https://www.designlunatic.com/2012/12/isotope-infinite-scroll/#comments Tue, 25 Dec 2012 07:02:39 +0000 Design Lunatic http://www.designlunatic.com/?p=1303 The faster something loads, the happier the user is. This is something it is important to understand when creating websites. Today, I’ll show how to use jQuery’s AJAX capabilities in conjunction with isotope.js to dynamically load content in once the user reaches the bottom of the page, which makes everything seem faster and improves the user experience.

Before you begin this tutorial, make sure you have a local web server set up, because jQuery’s AJAX functions don’t work when the file is just opened locally.

HTML

The HTML remains the same as it was in the original isotope tutorial. However, you must create some more pages. Create a duplicate of the index.html file from the original isotope tutorial and call it page2.html. Do the same thing again, and call it page3.html. Put the pages you created in a directory called “pages”. Feel free to change the content of the boxes inside each page – that will just make it easier to distinguish which box came from what page.

CSS

The CSS remains unchanged from the original isotope tutorial.

jQuery

First, include the jquery that initializes isotope.

$(document).ready(function(){
	var $container = $('#content');
	$container.isotope({
		filter: '*',
		animationOptions: {
			duration: 750,
			easing: 'linear',
			queue: false,
		}
	});

	$('#nav a').click(function(){
		var selector = $(this).attr('data-filter');
		$container.isotope({ 
			filter: selector,
			animationOptions: {
				duration: 750,
				easing: 'linear',
				queue: false,
			}
		});
		
		return false;
	});
});

Now, can start on the AJAX functionality. First, we need a variable to store what page is currently being displayed on the page.

var page = 1;

This will go up by one every time another page is loaded in.

Next, we’ll create the window.scroll function that all of our code today will go into.

var page = 1;
$(window).scroll(function(){

});

This is where all the magic will happen. Since the whole purpose of the script is to detect when a user has scrolled down to the bottom of the page and load content in when that happens, we need a window.scroll function. Every time the user scrolls, the code inside this function is executed.

Now, we’ll create some variables.

var scrollTop = $(window).scrollTop();
var windowHeight = $(window).height();
var docuHeight = $(document).height();

We’ll use these three variables to determine whether or not the user has scrolled down to the bottom of the page yet.

if(scrollTop + windowHeight == docuHeight){

}

This statement is true if the user has scrolled to the bottom of the page.

Once the user has scrolled to the bottom of the page, a temporary div called “temp-load” will be created.

if(scrollTop + windowHeight == docuHeight){
	$('body').append('<div id="temp-load"</div>');
}

Next, we’ll use jQuery’s load function to get the boxes from the next page and put them into this temp-load div.

if(scrollTop + windowHeight == docuHeight){
	$('body').append('<div id="temp-load"</div>');

	page += 1;

	$('#temp-load').load('pages/page' + page + '.html #content');
}

The parameter inside the load function is what jquery is retrieving. In this case, it is a page inside the “pages” directory, and the page is whatever the next page is – that’s why page is being incremented by one. The second part of the parameter is “#content”, which means jquery is only retrieving the #content div from the next page, since we don’t need anything else. The HTML jquery retrieves is placed inside the “#temp-load” div.

Jquery .load can take another parameter, which is the callback.

$('#temp-load').load('pages/page' + page + '.html #content', function(){
	
});

The code inside the callback gets executed once the load function successfully completes, which means everything was retrieved and has been placed into the “#temp-load” div.

$('#temp-load').load('pages/page' + page + '.html #content', function(){
	$('#temp-load > #content').children().css({ 
		 opacity: 0 
	});	

	var toAdd = $('#temp-load > #content').html();
	
});

This code makes the elements inside the “temp-load” div have an opacity of 0, so that they can later on be nicely animated in. The “toAdd” variable contains the HTML for all the elements that were just loaded in with jquery. We’ll insert the content of this variable into the main container. To do this, we’ll use isotope’s insert function.

var toAdd = $('#temp-load > #content').html();

$container.isotope('insert', $(toAdd), function(){
	$container.children().css({
		opacity: 1
	});	
					
	$('#temp-load').remove();
					
});
				

Here’s what happens: isotope takes the value of “toAdd” and appends it to the inside of the $container. It then triggers a reLayout, which means everything inside is re-filtered. This way, all the items are now isotoped. Once the items have been added, the callback function fires. Inside that, we make all of $container’s children have an opacity of 1. Since the elements we just added all have an opacity of 0, they need to become visible. Modifying their styles to make their opacity 1 animates them to become visible. Lastly, the temporary div is removed since we no longer need it.

The final code looks like this:

$(document).ready(function(){
	var $container = $('#content');
	$container.isotope({
		filter: '*',
		animationOptions: {
			duration: 750,
			easing: 'linear',
			queue: false,
		}
	});

	$('#nav a').click(function(){
		var selector = $(this).attr('data-filter');
		$container.isotope({ 
			filter: selector,
			animationOptions: {
				duration: 750,
				easing: 'linear',
				queue: false,
			}
		});
		
		return false;
	});

	var page = 1;

	$(window).scroll(function(){

		var scrollTop = $(window).scrollTop();
		var windowHeight = $(window).height();
		var docuHeight = $(document).height();

		if(scrollTop + windowHeight == docuHeight){
				
			$('body').append('<div id="temp-load"</div>');

			page += 1;
			
			$('#temp-load').load('pages/page' + page + '.html #content', function(){
				
				$('#temp-load > #content').children().css({
					opacity: 0
				});	
			
				var toAdd = $('#temp-load > #content').html();

				$container.isotope('insert', $(toAdd), function(){
					
					$container.children().css({
					opacity: 1
					});	
					
					$('#temp-load').remove();
					
				});
		
			});
			
		}

	});

});

That’s the end of this tutorial; I hope you enjoyed it. If you have any questions or comments, feel free to leave them in the comments section below.

]]>
https://www.designlunatic.com/2012/12/isotope-infinite-scroll/feed/ 8
Custom Scrollbars with jQuery https://www.designlunatic.com/2012/11/custom-scrollbars-with-jquery/ https://www.designlunatic.com/2012/11/custom-scrollbars-with-jquery/#comments Thu, 22 Nov 2012 21:13:01 +0000 Design Lunatic http://www.designlunatic.com/?p=1281 Sometimes, as web designers, we create a perfect design. Everything is exactly the way it should be, every pixel in the right spot, every color the right tinge. However, there is one thing that we often leave unchanged, and that is the scrollbar. Today, I’ll show how to create custom scrollbars using jQuery.

HTML

The HTML is extremely basic – it’s just a “section” with some paragraphs inside. The javascript we’re about to write inserts all the HTML the custom scrollbar needs, so you can place whatever you want into the HTML.

<section id="main">
<p>
Lorem ipsum dolor sit amet, christus eum ego. Rhenum ibat est amet consensit cellula filia in lucem. Maria non dum est Apollonius eius sed quod una litus ostendam Apollonio dares. Actum in rei civibus nescis admonente iustum ait in deinde duas particularis ad quia ad per dicis. Stans sed quod una Christi iube es est cum, athenagorae principio intus huius domus ad quia quod tamen adnuente rediens eam ad per. Quos essem rogo cum suam non ait mea in rei sensibilium acciperem. Corripit ars tolle Adfertur guttae sapientiae decubuerat. Inquisivi ecce habitu rubor virginitatem sunt antecedente tuus desiderio sic ut libertatem adhuc. Inter autem nobiscum paulo aureos fecit per accipere, dicis Deducitur potest flens praemio litore iunctionem quae. Domini in lucem genero in rei finibus veteres hoc! Equidem deceptum in deinde cepit roseo ruens sed eu fugiens laudo in.
</p>
<p>
Lugens quia iuvenis eum istam provoces Athenagora eius sed dominum oculos ne a civitas iter. Patriam Dianae non solutionem inveni quem suis alteri formam speciosam at at eius ad quia illum decidat quam cara patrem! Habes prima inrumpit dic hoc ambulare dolor invenerit, mytilenam Descendi eam in rei finibus veteres hoc. Inquisivi ecce prima substantiae Apollonius in deinde duas formis ei quoque non solutionem innocentem vis! Ait mea ego dum miror diligere quem est se in modo genito in. Adiuro me naufragus qui enim, unam emanabat cum obiectum ait. Miscetur vulnus fertur ardeat in modo genito in fuerat est se ad per animum est amet amet Cur meae. Antiochia videns de tuae illa caelum ad suis. Peregrini in lucem concitaverunt in rei finibus veteres hoc contra serpentibus isto. Post petiit materia amicis filia dedit beneficio ad quia ei. Accedens est cum obiectum est in fuerat se est cum suam vidit Dionysiadi me in. Eum est amet constanter approximavit te in lucem exitum vivit. Se vero non solutionem ascendens sed eu fugiens laudo misera haec vidit ad quia. Impietatem die audi discipuli Tyrius tu mihi Tyrum reverteretur ad nomine.
</p>
<p>
Laetare quod non solutionem invenerunt ita in. Abstulit meis dolor ad per sanctus ait. Probo artium studiose rosa ad per animum pares terris restituit. Meam ad quia iuvenis omnia bono quomodo possum es. Modum cura supponere ipsa Invitamus me! Erige me in deinde vero quo sanctis oravit. Antioche in fuerat eum ego dum miror puella est se ad nomine Maria non ait mea ego esse haec. Atqui plurium venenosamque serpentium ne civitatis civium currebant in, nescimus de me in deinde cupis hominem. Rogo ultimum favente his domino ab ornabo in modo invenit quasi plena violatam. Mutilenae ratio omnes deo adiuves finem. Credo puella mihi quidditas tuo dolor virgo permitte a civitas ad nomine Maria non ait est amet amet amet consensit cellula rei exultant deo. Maria cum unde non dum est amet consensit cellula filia puella. Ascendi in lucem exitum atque bona dei fundamus magister. Thebaeorum in fuerat eum est amet amet constanter determinatio debitis torporis quin.
</p>
<p>
Dicite enim formam se est in! Ardalio nos filiae gloriam virginis provolutus volo lacrimis colligantes amarissimo formas. Secundis est in modo ad suis alteri si non solutionem invenisti naufragus ferro conparuit de. Ni fluctus evasit dic ego illum Apollonii appropinquat tation ulterius a his e contrarius haec vidit Dionysiadi me in. Videns sed quod eam sed quod una Christi in lucem in fuerat accidens suos exteriores. Tantus puella sed haec aliquam habet comam apodixin mei in fuerat est se sed dominum sit in. Ephesum iube creasti hoc ait Cumque materia amicis in modo cavendum es ego dum est Apollonius ut a. Accede meae ad quia ad per te in rei completo litus vita Apolloni figitur acquievit. Etiam corpusculum subito animal irruit in, primam qui enim est in deinde plectrum anni ipsa Invitamus me.
</p>
<p>
Puto suam in lucem genero in fuerat accidens suos exteriores iuvenis eum in fuerat eum ego Pentapolim Cyrenaeorum. Nescimus de me naufragus habuisti sit in! Pater ostendit qui non ait Cumque materia eam eos. Litus sua Cumque persequatur sic vero cum suam ad per dicis filiam in lucem in. Horreo Athenagora eius non solutionem invenisti naufragus ait mea, unam emanabat cum autem illud huius domus respexit est amet coram regis fine omnino vero cum. Habet vero quo accumsan in rei finibus veteres hoc contra me. Permansit in lucem in deinde cupis ei Taliarchum. Ite in modo ad suis alteri si. Ecce codicellis desinit sestertia habeatis Apollonio sed dominum depressit filia navem causa alia qui auri. Sed eu fides se est amet coram regis suam! Quantum ait regem consolatus dum est se sed dominum depressit filia puella ut diem finito convocatis ad per. Ubi diceret modiorum fudit animo resignasset iubet contremuit in, spongia non solutionem inveni in rei sensibilium iussit divisit calvus dolor invenerit. Thebaeorum in rei completo litus sua in fuerat est in. Mutilenae ea communia ei quoque sed quod eam in, fige omnium ad quia ei sed eu fides Concordi fabricata ait. Iacentem substantiales statim iuxta quia iuvenis ut libertatem petitiones, adfertur guttae sapientiae ducitur multa confert eam sed.
</p>
</section>

CSS

The CSS is mostly just styling, but there are a couple of things it is important to have.

html {
overflow-y: hidden;
}

This causes the default scrollbar to disappear, which allows us to create a replacement.

Next, we have the scrollbar track. This is the vertical line on which the scrollbar goes up and down.

#scrollbar-track {
width: 10px;
position: fixed;
right: 0px;
height: 100%;
background: #ddd;
}

We’re giving it a width, fixing it to the viewport so that it stays in the same spot no matter where the user scrolls, we attach it to the right of the screen, and we give it a height of “100%”, which makes it the same height as the viewport. The last thing is just a light grey background.

Next, the scrollbar.

#scrollbar {
width: 10px;
position: fixed;
right: 0px;
background: #666;
-webkit-border-radius: 5px;
border-radius: 5px;
}

The CSS is almost the same as that of the scrollbar track’s, but here there is no “height: 100%”, since the height will vary depending on how much content there is on the page. The scrollbar also has a width of 10px, is attached to the right side of the viewport, and is given some mild styling.

Keep in mind that you won’t be able to see these styles yet, as the elements haven’t actually been created by the javascript yet.

jQuery

The first thing we need is to include a couple of scripts. Download the files for this tutorial. Inside, you’ll find “jquery-ui-draggable.js” and “jquery.mousewheel.js”. The “draggable” script is just a custom build of jQuery UI that only contains the code for “draggable”, and “mousewheel” gives us some handy functions based on the user’s mousewheel or trackpad. Place them in the directory in which you’re following this tutorial.

Now, include them in the “head” of the HTML document.

<script src="jquery.mousewheel.js"></script>
<script src="jquery-ui-draggable.js"></script>

Don’t forget to include a copy of jQuery as well.

Now, we’ll create the scrollbar and the track.

$(document).ready(function(){

	$('body').prepend('<div id="scrollbar-track"><div id="scrollbar"></div></div>');

});

This code adds the two “div” elements we need to the very beginning of the page, just inside the “body”.

Next, we’ll create the function that does all the work.

function scrollBar(){

	var viewportHeight = $(window).height();
	var docuHeight = $(document).height();

	var trackHeight = $('#scrollbar-track').height();

	var scrollbarHeight = (viewportHeight/docuHeight)*trackHeight;

	$('#scrollbar').height(scrollbarHeight);
}

There’s now a function called “scrollBar”, which has some variables inside it. The first one, “viewportHeight” is the height of the browser viewport. The next, “docuHeight”, is the height of the whole HTML page. “trackHeight” is the height of the scrollbar track, which is the same as “viewportHeight”. I just like to keep the two separate to make it clearer what the code actually does. Next, the “scrollbarHeight” variable. This variable is created by taking the ratio of the viewport height to the document height, which is usually between 0 to 1. If the ratio is higher, that means that the viewport is bigger than the whole HTML document, in which case the scrollbar doesn’t do anything. We take the ratio and multiply it by the “trackHeight”. This gives us the height of the scrollbar. Let’s imagine that the whole document is exactly twice as big as the viewport. For example, the height of the viewport is 500px and the height of the document is 1000px. 500/1000 is “0.5″, so the ratio is “0.5″. We then multiply “0.5″ by the trackHeight, which gives us a value exactly half the size of the track height. This is how the height of the scrollbar is determined.

Now, we’ll make the scrollbar draggable.

$('#scrollbar').draggable({
	axis: 'y',
	containment: 'parent',
	drag: function() {
		var scrollbarTop = parseInt($(this).css('top'));

		var scrollTopNew = (scrollbarTop/(trackHeight))*docuHeight;

		$(window).scrollTop(scrollTopNew);

	}
});

This is where the “draggable” script comes in. We use the “draggable” function to make the scroll bar draggable. The “axis” parameter is set to “y”, which means that it can only be dragged up or down. The “containment” parameter is set to “parent”, which means it can’t be dragged out of the boundaries of the parent, which in this case, is the “track”. The last thing is the “drag” paramater, which accepts a function as a value. Basically, whenever the scrollbar is being dragged, this function fires. Inside the function, the first thing we do is create a variable called “scrollbarTop”, which takes the CSS “top” value of the scrollbar (how far away it is from the top of the track) and converts it into an integer. This allows us to use it in mathematical equations such as the one that determines the value of the next variable, “scrollTopNew”. “scrollTopNew” is the new value of where the window should scroll to. In order to do this, we take the ratio of the scrollbar’s “top” value and the “trackHeight”. We then take this ratio and multiply it by the “docuHeight”, which gives us a value to which the window should scroll. The last line actually scrolls the window to this value.

Here’s what everything looks like so far:

$(document).ready(function(){

	$('body').prepend('<div id="scrollbar-track"><div id="scrollbar"></div></div>');

	function scrollBar(){

		var viewportHeight = $(window).height();
		var docuHeight = $(document).height();

		var trackHeight = $('#scrollbar-track').height();

		var scrollbarHeight = (viewportHeight/docuHeight)*trackHeight;

		$('#scrollbar').height(scrollbarHeight);

		$('#scrollbar').draggable({
			axis: 'y',
			containment: 'parent',
			drag: function() {
				var scrollbarTop = parseInt($(this).css('top'));

				var scrollTopNew = (scrollbarTop/(trackHeight))*docuHeight;

				$(window).scrollTop(scrollTopNew);

			}
		});
	}
});

Now, we can initialize the function so that the code actually happens.

function scrollBar(){
//Code in here...
}

scrollBar();

At this point, dragging the scroll bar should result in the page scrolling around. The last thing we need to do is make the mousewheel/touchpad work. We’ll do this by using the “mousewheel” script.

$("body").bind("mousewheel", function (event, delta) {

	var scrollTop = $(window).scrollTop();
	var scrollTopNew = scrollTop - (delta * 40);

	$(window).scrollTop(scrollTopNew);

	var scrollbarTop = ($(window).scrollTop()/docuHeight)*trackHeight;

	$('#scrollbar').css({
		top: scrollbarTop
	});
});

This code is just after the “draggable” scrollbar code. Here, we bind a “mousewheel” event to the body, so whenver the mousewheel is moved, the code inside is executed.

The first variable, “scrollTop”, is how far the window has already scrolled. The next one, “scrollTopNew”, is where the window should now scroll to. It is determined by taking the current “scrollTop”, and using teh “delta” variable. The “delta” variable is a number, “1″ or “-1″. It is “-1″ if the user just scrolled down, and “+1″ if the user scrolled up. This number is multiplied by “30″, so when the user moves their mouse wheel down once, the page scrolls down by 30 pixels. This new value is then applied to the window’s “scrollTop” by using the “scrollTop” function. “scrollbarTop” is where the scrollbar should be as a result of the user’s mouse wheel or touchpad scrolling. It takes the current scrollTop divides it by the document height to get the ratio, and multiplies the ratio by the trackHeight so that the scrollbar is in the right position. The scrollbar is then given a top of “scrollbarTop”.

This code should work well, but it doesn’t work when the user resizes their browser window. We can fix this by using the following code:

$(window).resize(function(){
	scrollBar();
});

This way, the function is re-executed whenever the window is resized.

Here’s what all the javascript should look like:

$(document).ready(function(){

	$('body').prepend('<div id="scrollbar-track"><div id="scrollbar"></div></div>');

	function scrollBar(){

		var viewportHeight = $(window).height();
		var docuHeight = $(document).height();

		var trackHeight = $('#scrollbar-track').height();

		var scrollbarHeight = (viewportHeight/docuHeight)*trackHeight;

		$('#scrollbar').height(scrollbarHeight);

		$('#scrollbar').draggable({
			axis: 'y',
			containment: 'parent',
			drag: function() {
				var scrollbarTop = parseInt($(this).css('top'));

				var scrollTopNew = (scrollbarTop/(trackHeight))*docuHeight;

				$(window).scrollTop(scrollTopNew);

			}
		});

		$("body").bind("mousewheel", function (event, delta) {

			var scrollTop = $(window).scrollTop();
			var scrollTopNew = scrollTop - (delta * 40);

			$(window).scrollTop(scrollTopNew);

			var scrollbarTop = ($(window).scrollTop()/docuHeight)*trackHeight;

			$('#scrollbar').css({
				top: scrollbarTop
			});
		});

	}

	scrollBar();

	$(window).resize(function(){
		scrollBar();
	});

});

That’s it for this tutorial – I hope you enjoyed it and learned something new. If you have any questions or comments, post them below and I’ll do my best to answer.

]]>
https://www.designlunatic.com/2012/11/custom-scrollbars-with-jquery/feed/ 14
Awesome jQuery Tooltips https://www.designlunatic.com/2012/11/awesome-jquery-tooltips/ https://www.designlunatic.com/2012/11/awesome-jquery-tooltips/#comments Sun, 04 Nov 2012 17:58:06 +0000 Design Lunatic http://www.designlunatic.com/?p=1250 Tooltips are a great way to display some information about an element on the page. Normally, these are used on links. In this post, I’ll explain how to create a jQuery script that allows for easy tooltips on a page.

HTML

All that’s on the page is just some Lorem Ipsum text and a couple of links.

<section id="container">

<p>
Lorem ipsum dolor sit amet, video cum autem quod non dum, audite deo adoptavit cum magna amici invocat manibusque removit benedictus. Ad per dicis Deducitur potest contremiscunt <a href="#" data-tooltip="A tooltip!">pater unica</a> suae ad nomine sed haec aliquam laetandum prudentia litteris erutis invenies eum. Euro in fuerat se est amet consensit cellula rei finibus veteres hoc contra piissimi sibi adsedit in deinde cepit roseo. <a href="#" data-tooltip="This is a tooltip">Vini in deinde</a> cepit roseo ruens sed dominum sit audivit illius actio viro prudentius ei. Erras nisi auri est in lucem, venis potest in modo compungi mulierem.
</p>

</section>

The important part is the “data-tooltip” attributes on the links. These are so the jQuery script we’ll write knows what to display in the tooltip.

CSS

First off, get a good CSS reset, as these are invaluable in getting rid of weird browser-related issues. Now, let’s just style the main container to make it look nice.

body {
background: #eee;
}

#container {
font-family: arial;
font-size: 15px;
line-height: 25px;
color: #515151;
width: 600px;
height: 2000px;
padding: 20px;
border-left: 1px solid #dedede;
border-right: 1px solid #dedede;
border-bottom: 1px solid #dedede;
background: #fff;
margin: 0 auto;
-webkit-border-radius: 0px 0px 5px 5px;
border-radius: 0px 0px 5px 5px;
}

The text inside the container will be 15px Arial with a line-height of 25px, and will be a dark grey color. The container will be 600px wide with some padding, and will have borders that are slightly rounded.

Next up, some link styling.

#container a {
color: #888;
text-decoration: none;
border-bottom: 1px dotted #888;
position:relative;
}

This is just for visual purposes, but notice the “position: relative”. This will be important in positioning the tooltip properly.

Now, we can style the tooltip. This will just be a simple rectanble, but it will have a triable facing downwards to indicate where the tooltip is coming from.

.tooltip {
width: 100px;
margin-left: -60px;
left: 50%;
line-height: 20px;
padding: 10px;
font-family: Arial;
font-size: 14px;
color: #777;
text-align: center;
border: 2px solid #bbb;
background: #fff;
text-indent: 0px;
position: absolute;
pointer-events: none;
opacity: 0;
box-shadow: 1px 1px 2px rgba(0,0,0,0.1);
-webkit-border-radius: 5px;
border-radius: 5px;
}

All of this is just for visual purposes. We’re giving it a width of 100px, some padding, styling the text inside – basically, we’re just making it pretty. Notice the “left: 50%” and “margin-left: -60px”. This positions the left edge of the tooltip to be halfway in the link, but that’s not what we want; we want it to be perfectly centered. The “margin-left: -60px” makes it perfectly centered by shifting it a value to the left equal to half of the width of the tooltip (since with the padding, the tooltip actually has a total width of 120px). Another important property is the “pointer-events: none” property – this makes the user unable to interact with the tooltip, so that it doesn’t get in the way when it isn’t visible.

With this code, the tooltip already looks pretty – but it doesn’t have a triangle pointing down to indicate where it originated from. Let’s fix that.

.tooltip::after {
content: '';
position: absolute;
left: 50%;
margin-left: -10px;
bottom: -10px;
width: 0;
height: 0;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 8px solid #bbb;
}

Instead of creating a separate element just for the triangle, we’re using the CSS3 “after” pseudo element. The “content” property is so that the pseudo element actually contains something; without this, nothing will show up. Now, the next two lines are centering the triangle. The “left: 50%” will make the left edge of the triangle be halfway, but by giving it a negative margin equal to half of its width, the triangle is now perfectly centered. However, the triangle is not where we want it to be. The “bottom: -10px” makes it be right below the tooltip. The next lines are what make it a triangle. By giving it a width and height of 0, all that’s left is the borders. Each border behaves like a triangle, where four triangles create a square. By making the left and right borders transparent, the top border is all that remains. The top border has the same color as the border of the tooltip, so it fits in nicely.

Jquery

Before we begin writing code, here’s how everything will work:

  1. The script iterates over each link, or “a” element on the page.
  2. For each link, a “div” with a class of “tooltip” is added.
  3. Each tooltip div contains the text from the “data-tooltip” attribute inside its corresponding link.
  4. When a link is hovered over, its corresponding tooltip is animated slightly upwards and the opacity is increased.

Let’s get to work:

$(document).ready(function(){
	
	$('a[data-tooltip]').each(function(){
		
	});

});

This is just the typical jquery document ready function, which waits until the page is loaded to execute the code inside it. The “each” function repeats itself for each element selected; in this case, the code inside it is executed for each link with a “data-tooltip” attribute on the page.

Now, we’ll create the tooltip.

$('a[data-tooltip]').each(function(){
	var tooltipText = $(this).attr('data-tooltip');
	$(this).append('<div class="tooltip">'+tooltipText+'</div>');
});

The variable “tooltipText” is simply the value of the “data-tooltip” attribute of the link. The next line of code appends a div with a class of “tooltip” and with the value of “tooltipText” inside it.

Next, we’ll position the tooltip properly.

$('a[data-tooltip]').each(function(){
	var tooltipText = $(this).attr('data-tooltip');
	$(this).append('<div class="tooltip">'+tooltipText+'</div>');
	
	var tooltipHeight = $(this).find('.tooltip').outerHeight();	

	$(this).find('.tooltip').css({
		top: -tooltipHeight,
	});
});

The variable “tooltipHeight” is the height of the tooltip using the “outerHeight” function, which is just the “height” function but it includes padding and borders – this allows for a more accurate height. “$(this).find” finds a particular element inside the current element. In this case, we’re just finding the tooltip that is inside the link the script is currently on. We then give the tooltip a “top” equal to the negative of its height, which puts it right above the link.

The last thing that must be done is making the tooltip actually appear when a link is hovered over.

$('a[data-tooltip]').each(function(){
//Your code here...
});

$('a[data-tooltip]').hover(function(){
		
	$(this).find('.tooltip').animate({
		opacity: 1,
		marginTop: -7
	},200);
		
});

When a link with a “data-tooltip” attribute is hovered over, the tooltip inside it is animated to “opacity: 1″, and is shifted up 7 pixels. When the tooltip shifts up like that, it not only looks nice, but also shows where the tooltip is actually coming from. These two animations are done during 200 milliseconds. At this point, we’re almost done, but notice what happens when you move the mouse cursor away from a link – nothing. The tooltip stays where it is.

Fortunately, this can easily be fixed.

$('a[data-tooltip]').hover(function(){
	
	$(this).find('.tooltip').animate({
		opacity: 1,
		marginTop: -7
	},200);
	
}, function(){
	$(this).find('.tooltip').animate({
		opacity: 0,
		marginTop: 0
	},200);
});

Here, we’ve used a callback to the “hover” function; the code inside the “hover” callback executes when the cursor is no longer hovering over the link. In this callback, we simply move the tooltip back down and reduce its opacity.

Here’s all the jQuery in one place.

$(document).ready(function(){
	
	$('a[data-tooltip]').each(function(){
	
		var tooltipText = $(this).attr('data-tooltip');
		$(this).append('<div class="tooltip">'+tooltipText+'</div>');
		
		var linkWidth = $(this).width();
		var tooltipWidth = $(this).find('.tooltip').outerWidth();
		
		var tooltipHeight = $(this).find('.tooltip').outerHeight();	

		
		$(this).find('.tooltip').css({
			top: -tooltipHeight,
		});
		
		
	});
	
	$('a[data-tooltip]').hover(function(){
		
		$(this).find('.tooltip').animate({
			opacity: 1,
			marginTop: -7
		},200);
		
	}, function(){
		$(this).find('.tooltip').animate({
			opacity: 0,
			marginTop: 0
		},200);
	});
	
});

That’s the end of this tutorial. I hope you found it useful and enjoyable, and if you have any questions or comments, feel free to comment below – I’d be happy to answer.

]]>
https://www.designlunatic.com/2012/11/awesome-jquery-tooltips/feed/ 0
Rearrange content when it’s too wide with jquery https://www.designlunatic.com/2012/09/rearrange-content-when-too-wide-with-jquery/ https://www.designlunatic.com/2012/09/rearrange-content-when-too-wide-with-jquery/#comments Tue, 18 Sep 2012 02:53:48 +0000 Design Lunatic http://www.designlunatic.com/?p=1222 Media queries have proven to be extremely useful in responsive layouts. However, they do have a drawback: they can’t analyze the content on the page before deciding when to kick in. For example, if you have a fluid layout, CSS doesn’t know exactly what width the container has when the browser has a width of, for example, 742px. Javascript does. In this post, I’ll show how javascript can be used to make layouts even smarter and more adaptable.

HTML

The example we’ll be creating today is just the top of a web page – it will contain the title of the site and the navigation menu. That means the HTML is fairly straightforward.

<header>

<h1>The title of the site</h1>

<nav>
	<ul>
		<li><a href="#">Home</a></li>
		<li><a href="#">Portfolio</a></li>
		<li><a href="#">About</a></li>
		<li><a href="#">Contact</a></li>
	</ul>
</nav>

</header>

Header just contains everything, the “h1″ is the title of the site, and the “nav” contains the navigation menu. Feel free to add whatever you want to the HTML – the beauty of this script is that it will work no matter what you have in there.

CSS

In the CSS, we’ll first style the elements to look a certain way, and then we’ll add classes that will be applied to the elements when there isn’t enough space.

We’ll start off with some basic styling.

body {
font-family: Arial;
font-size: 15px;
line-height: 25px;
color: #595959;
background: #f8f8f8;
}

Now, the header. We’ll give this a percentage width of 60% to demonstrate the capabilites of the javascript we’ll write in a moment. You can set this to whatever you want, but I would suggest sticking with 60%.

header {
width: 60%;
min-width: 260px;
height: 50px;
margin: 0 auto;
margin-top: 30px;
background: #fff;
-webkit-box-shadow: 0px 0px 5px #888888;
box-shadow: 0px 0px 5px #888888;
-webkit-border-radius: 5px;
border-radius: 5px;
padding: 15px;
}

The “header” has a width of 60%, and it doesn’t get any smaller than 260px, because anything less than that is just unreasonably small. The height is 50px, and we’re setting it because the elements inside are floated. It’s centered using “margin: 0 auto”, and is 30px from the top of the page, and after that are just some styles to make it look nice.

Next up, we’re going to style the “h1″ title inside the header.

h1 {
font-size: 32px;
line-height: 50px;
float: left;
}

The font-size is 32px because that’s a reasonable size for the title of a website, and its line height is 50px so that it’s centered in the header. Since the header has a height of 50px, anything inside with a line-height of 50px will be vertically centered, and that’s what’s happening with the title and the navigation.

Now, we just need the “nav” to float to the right.

nav {
float: right;
}

However, the content inside the nav still looks ugly. Let’s fix this.

nav ul li {
display: inline;
padding-left: 10px;
line-height: 50px;
}

Each “li” is displayed inline so that they can all be on one line, they’re all 10 pixels from each other, and the line-height is 50px so that they’re vertically centered.

Unfortunately, the links inside still look pretty bad.

nav ul li a {
color: #515151;
text-decoration: none;
}

There. That nasty blue color is gone, and so is the underline. Much better.

At this point, everything is completely styled – but one thing is missing: the styles for the smaller, alternate versions of the header, the title, and the navigation.

Let’s make an alternate version of the header

.smallHeader {
height: 100px;
}

The height is now twice as tall as it was before, so that all the content inside still fits perfectly. Since the title and the navigation both have a line-height of 50px, and they’re on separate lines now, two rows of 50px is 100px.

Now, let’s make the title and the navigation both 100%, so they make the best use of the space availabe.

.smallTitle {
width: 100%;
text-align: center;
}

.smallNav {
width: 100%;
text-align: center;
}

They’re both as wide as possible, and have their text-align set to center so that the text inside is… centered.

jQuery

Make sure you have a copy of jQuery before starting this part.

Here’s how the javascript will work: at the beginning, we’ll declare 3 variables – the width of the title, the width of the navigation, and the width of both of them added together.

$(document).ready(function(){
			
	var origTitleWidth = $('h1').width();
	var origNavWidth = $('nav').width();
	var origSpaceTaken = origTitleWidth+origNavWidth;
	
});

These 3 variables are declared before any changes happen to the three elements, so we have their original widths, and not the altered ones.

Next, we declare the “rearrange” function.

function rearrange(){	

}

Now, we need to find out the width of the header to know whether or not to apply the modified styles to the title and the navigation.

function rearrange(){
	var headerWidth = $('header').width();
}

Once we have the header width, we need to set up two “if” statements.

function rearrange(){
	if(origSpaceTaken>headerWidth){

	}
	
	if(origSpaceTaken<headerWidth){

	}
}

This handles both possibilites: either the space taken is larger than the space available, or it is smaller.

If the space taken up by the elements inside is too large for the space available, we need those elements to receive their alternate styling.

function rearrange(){
	if(origSpaceTaken>headerWidth){
		$('header').addClass('smallHeader');
		$('h1').addClass('smallTitle');
		$('nav').addClass('smallNav');
	}
	
	if(origSpaceTaken<headerWidth){

	}
}

There. Now, if the header is too small, the elements inside are optimized for it. The other possibility is that they fit, so we don’t want the “small” classes.

function rearrange(){
	if(origSpaceTaken>headerWidth){
		$('header').addClass('smallHeader');
		$('h1').addClass('smallTitle');
		$('nav').addClass('smallNav');
	}
	
	if(origSpaceTaken<headerWidth){
		$('header').removeClass('smallHeader');
		$('h1').removeClass('smallTitle');
		$('nav').removeClass('smallNav');
	}
}

That makes sure that they have the proper styling when necessary.

Also, the function needs to be called to work.

rearrange();

Lastly, we need to set up a window resize function so that the script can change the elements without reloading the page.

$(window).resize(function(){
	rearrange();
});

Now, as soon as the window is resized, the script can check to see if the elements inside fit or not, and can apply the right styles when necessary.

Here’s the completed code:

$(document).ready(function(){
		
	var origTitleWidth = $('h1').width();
	var origNavWidth = $('nav').width();
	var origSpaceTaken = origTitleWidth+origNavWidth;
	
	function rearrange(){
	
		var headerWidth = $('header').width();
		
		if(origSpaceTaken>headerWidth){
			
			$('header').addClass('smallHeader');
			$('h1').addClass('smallTitle');
			$('nav').addClass('smallNav');
		}
		
		if(origSpaceTaken<headerWidth){
			
			$('header').removeClass('smallHeader');
			$('h1').removeClass('smallTitle');
			$('nav').removeClass('smallNav');
		}
		
	}
	
	rearrange();
	
	$(window).resize(function(){
		rearrange();
	});
	
});

I can see this as being especially useful for themes and templates, where you don’t know what the buyer will have as their site title or their navigation. This way, the styles will be applied at the perfect moment. That’s the end of this tutorial – if you have any questions or comments, feel free to post them below and I’ll do my best to help you out.

]]>
https://www.designlunatic.com/2012/09/rearrange-content-when-too-wide-with-jquery/feed/ 0
A Continuation of the Isotope Tutorial: Hash History with Isotope https://www.designlunatic.com/2012/08/a-continuation-of-the-isotope-tutorial-hash-history-with-isotope/ https://www.designlunatic.com/2012/08/a-continuation-of-the-isotope-tutorial-hash-history-with-isotope/#comments Sun, 19 Aug 2012 01:38:17 +0000 Design Lunatic http://www.designlunatic.com/?p=1200 jQuery hashchange event.]]> I’ve written several tutorials on how to use isotope effectively and maximize its potential, and today’s post will be part of that series. What exactly does isotope do? It reorders the content on a page to only display what is necessary. The user can usually control this by clicking on links that change what the content is filtered by. But what if the user refreshes the page? Or decides that what the content was previously filtered by worked better, and presses the back button? Then, problems begin. The user has to reorder the content again to get back to where they were. Today’s post aims to solve that problem by using a plugin called jQuery hashchange event. This plugin works with the hash, the part after the url of the page that begins with “#”. It adds back button support to cycle through the hashes, and adds a handy “hashchange” jquery event.

As usual, before we begin on this post, grab a copy of the original isotope tutorial.

HTML

There are no changes from the HTML of the original isotope tutorial.

CSS

Nope, no changes here either. Keep reading.

Jquery

Here’s where the fun starts. We’ll rewrite the jquery from scratch, as there are several changes and optimizations to be made. Before you start writing the code, download the hashchange plugin. Once you’ve included the plugin, start off with jquery’s essential document.ready function.

$(document).ready(function(){

	var $container = $('#content');

});

There’s also a “$container” variable defined, which is just what we’re filtering.

Now, we need to create the code that will deal with appending values to the URL when a link is clicked.

$('#nav a').click(function(){
	var selector = $(this).attr('data-filter');

	location.hash = selector;

	return false;
});

The above code takes the “data-filter” attribute of the link that was just clicked, and appends it the url via the “location.hash” method. Then, there’s a return false, so the link isn’t followed. The above code works fine, but personally, I don’t like what is appended to the url. I think the dot before the category is extra – so let’s get rid of it.

$('#nav a').click(function(){
	var selector = $(this).attr('data-filter');

	var prettyselector = selector.substr(1);
  
	location.hash = prettyselector;

	return false;
});

With this addition, the URL looks cleaner and is nicer to look at. The above code now does exactly what we want it to do.

At this point, we’ll start using the capabilities of the “hashchange” plugin we’ve included.

$(window).hashchange( function(){

});

This is a “hashchange” function. When the hash of the URL is modified, the function fires. We can use this to filter the content as soon as a “hashchange” is detected.

$(window).hashchange( function(){
	var hashfilter = "." + location.hash.substr(1);
	
	$container.isotope({
		filter: hashfilter,
		animationOptions: {
			duration: 750,
			easing: 'linear',
			queue: false,
		}
	});

});

The “hashfilter” variable may seem a bit complex at first, but it’s quite simple. We’re taking the “location.hash”, which is the current hash of the URL, and deleting the first character. Why? Because the first character is a “#”, and we don’t need it. We then append a period to the beginning of a variable. Here’s what the process looks like: #cat1 => cat1 => .cat1.

While it may seem that the “hashchange” function works exactly as it has to, that’s incorrect. There’s one big issue with this – try clicking on the “All” button. Notice how nothing happens? That needs fixing.

$(window).hashchange( function(){
	
	if(location.hash!="#"){
		var hashfilter = "." + location.hash.substr(1);
	}
	else{
		var hashfilter = "*";
	}

	$container.isotope({
		filter: hashfilter,
		animationOptions: {
			duration: 750,
			easing: 'linear',
			queue: false,
		}
	});

});

The “if…else” statement fixes this. If the “location.hash” is NOT equal to a blank, the “hashfilter” is what created earlier. If it IS a blank space, then the “hashfilter” is a “*”, which basically means “All” in isotope.

We’re almost done – there’s just one thing left. If the page doesn’t get refreshed, everything works exactly as it should – but what if the page is refreshed, or is opened in a new window? The code doesn’t know what to filter it by, so it just goes with “*”. This is easy to fix though; we already wrote all the code we need.

$(document).ready(function(){
	var $container = $('#content');
		
	if(location.hash!=""){
		var hashfilter = "." + location.hash.substr(1);
	}
	else{
		var hashfilter = "*";
	}
		
	$container.isotope({
		filter: hashfilter,
		animationOptions: {
			duration: 750,
			easing: 'linear',
			queue: false,
		}
	});

Boom. Copy-pasted from inside the “hashchange” function, and it does exactly what we need to it do. At this point, everything should work perfectly for you. If it doesn’t, just download the files for the post and compare them to yours, but if it does, good job! That’s the end of this tutorial. If you have any questions or comments, feel free to post them below, and I’ll do my best to answer them.

]]>
https://www.designlunatic.com/2012/08/a-continuation-of-the-isotope-tutorial-hash-history-with-isotope/feed/ 10
A Continuation of the Isotope Tutorial: Combination Filters https://www.designlunatic.com/2012/07/a-continuation-of-the-isotope-tutorial-combination-filters/ https://www.designlunatic.com/2012/07/a-continuation-of-the-isotope-tutorial-combination-filters/#comments Thu, 26 Jul 2012 04:55:04 +0000 Design Lunatic http://www.designlunatic.com/?p=1177 Isotope.js is a powerful tool for creating dynamic webpages with interactive capabilities. It does this by using “filtering”, by which certain elements on the page are removed or added, depending on what the user requests. This by itself is incredibly useful, but it can be made even better, by using combination filters. This allows the user to select two criteria by which content is filtered. In this tutorial, I’ll show how to do just that.

This post will be based on the code from the isotope tutorial I wrote a while ago, so grab a copy of the code from there.

HTML

The HTML structure is the same as in the original isotope tutorial, but with minor differences in the class names and titles.

Here’s a sample content box:

<div class="box june y2010">
	<h2 class="box-title">Lorem Ipsum - June, 2010</h2>
	<div class="box-text">
	Urna vut, eros aliquet sagittis augue? Augue adipiscing duis? Et a placerat, magna enim? Lacus sit. Nunc montes tristique purus auctor. Nascetur? Vut amet, phasellus pulvinar et odio. Ut aliquet integer sed enim ac amet nunc? Tincidunt sit, cum ridiculus, placerat cum, vut magna ridiculus ut phasellus ridiculus? Eu hac, mattis adipiscing, montes adipiscing urna montes rhoncus!
	</div>
</div>

We have a class called “june”, which is the month this post was published, and a class called “y2010″, which is the year. It’s not possible to have a class with just numbers, so the “y” is necessary. The same concept applies to every other post.

<div class="box june y2010">
	<h2 class="box-title">Lorem Ipsum - June, 2010</h2>
	<div class="box-text">
	Urna vut, eros aliquet sagittis augue? Augue adipiscing duis? Et a placerat, magna enim? Lacus sit. Nunc montes tristique purus auctor. Nascetur? Vut amet, phasellus pulvinar et odio. Ut aliquet integer sed enim ac amet nunc? Tincidunt sit, cum ridiculus, placerat cum, vut magna ridiculus ut phasellus ridiculus? Eu hac, mattis adipiscing, montes adipiscing urna montes rhoncus!
	</div>
</div>
			
<div class="box july y2010">
	<h2 class="box-title">Lorem Ipsum - July, 2010</h2>
	<div class="box-text">
	Urna vut, eros aliquet sagittis augue? Augue adipiscing duis? Et a placerat, magna enim? Lacus sit. Nunc montes tristique purus auctor. Nascetur? Vut amet, phasellus pulvinar et odio. Ut aliquet integer sed enim ac amet nunc? Tincidunt sit, cum ridiculus, placerat cum, vut magna ridiculus ut phasellus ridiculus? Eu hac, mattis adipiscing, montes adipiscing urna montes rhoncus! Odio placerat pellentesque risus urna elit, odio phasellus, rhoncus, est ridiculus purus etiam, penatibus integer! 
	</div>
</div>
			
<div class="box august y2010">
	<h2 class="box-title">Lorem Ipsum - August, 2010</h2>
	<div class="box-text">
	Urna vut, eros aliquet sagittis augue? Augue adipiscing duis? Et a placerat, magna enim? Lacus sit. Nunc montes tristique purus auctor. Nascetur?
	</div>
</div>
			
<div class="box june y2011">
	<h2 class="box-title">Lorem Ipsum - June, 2011</h2>
	<div class="box-text">
	Amet dolor? Diam cras ac quis a ut, augue massa cursus natoque cursus in sociis rhoncus, scelerisque mus ac. Pellentesque odio rhoncus, aliquet tempor? Nisi cursus lorem tincidunt penatibus eu scelerisque! Scelerisque mid rhoncus turpis eros? Nunc rhoncus in turpis, mus, nec augue, odio, mid tempor aliquam, ultricies.
	</div>
</div>

<div class="box july y2011">
	<h2 class="box-title">Lorem Ipsum - July, 2011</h2>
	<div class="box-text">
	Diam cras ac quis a ut, augue massa cursus natoque cursus in sociis rhoncus, scelerisque mus ac. Pellentesque odio rhoncus, aliquet tempor? Nisi cursus lorem tincidunt penatibus eu scelerisque! Scelerisque mid rhoncus turpis eros? Nunc rhoncus in turpis, mus, nec augue, odio, mid tempor aliquam, ultricies.
	</div>
</div>

<div class="box august y2011">
	<h2 class="box-title">Lorem Ipsum - August, 2011</h2>
	<div class="box-text">
	Urna vut, eros aliquet sagittis augue? Augue adipiscing duis? Et a placerat, magna enim? Lacus sit. Nunc montes tristique purus auctor. Nascetur? Vut amet, phasellus pulvinar et odio. Pellentesque odio rhoncus, aliquet tempor? Nisi cursus lorem tincidunt penatibus eu scelerisque! Scelerisque mid rhoncus turpis eros? Nunc rhoncus in turpis, mus, nec augue, odio, mid tempor aliquam, ultricies.
	</div>
</div>
			
<div class="box june y2012">
	<h2 class="box-title">Lorem Ipsum - June, 2012</h2>
	<div class="box-text">
	Urna vut, eros aliquet sagittis augue? Augue adipiscing duis? Et a placerat, magna enim? Lacus sit.
	</div>
</div>
			
<div class="box july y2012">
	<h2 class="box-title">Lorem Ipsum - July, 2012</h2>
	<div class="box-text">
	Amet dolor? Diam cras ac quis a ut, augue massa cursus natoque cursus in sociis rhoncus, scelerisque mus ac. Pellentesque odio rhoncus, aliquet tempor? Nisi cursus lorem tincidunt penatibus eu scelerisque! Scelerisque mid rhoncus turpis eros? Nunc rhoncus in turpis, mus, nec augue, odio, mid tempor aliquam, ultricies.
	</div>
</div>
			
<div class="box august y2012">
	<h2 class="box-title">Lorem Ipsum - August, 2012</h2>
	<div class="box-text">
	Urna vut, eros aliquet sagittis augue? Augue adipiscing duis? Et a placerat, magna enim? Lacus sit. Nunc montes tristique purus auctor. Amet dolor? Diam cras ac quis a ut, augue massa cursus natoque cursus in sociis rhoncus, scelerisque mus ac. Pellentesque odio rhoncus, aliquet tempor? Nisi cursus lorem tincidunt penatibus eu scelerisque! Scelerisque mid rhoncus turpis eros? Nunc rhoncus in turpis, mus, nec augue, odio, mid tempor aliquam, ultricies.
	</div>
</div>

The navigation is also slightly different. Since we have two different ways by which to filter the content, we’ll need two separate menus.

<div id="nav">
	<ul id="month">
		<li><a href="#" data-filter="*">All</a></li>
		<li><a href="#" data-filter=".june">June</a></li>
		<li><a href="#" data-filter=".july">July</a></li>
		<li><a href="#" data-filter=".august">August</a></li>
	</ul>
			
	<ul id="year">
		<li><a href="#" data-filter="*">All</a></li>
		<li><a href="#" data-filter=".y2010">2010</a></li>
		<li><a href="#" data-filter=".y2011">2011</a></li>
		<li><a href="#" data-filter=".y2012">2012</a></li>
	</ul>
</div>

There’s the menu for filtering the month, and the one for filtering the year. The data-filter attributes contain the class name by which the elements should be filtered.

CSS

Nothing to do here, carry on. The CSS is unchanged from the original isotope tutorial.

Jquery

We’ll rewrite the javascript from scratch here. First off, we’ll isotope the main container.

$(document).ready(function(){
	
	var $container = $('#content');
		
	$container.isotope({
		filter: '*',
		animationOptions: {
    		duration: 750,
    		easing: 'linear',
    		queue: false,
   		}
	});
});

Now, all the boxes are “isotoped”. Let’s get to work on the code powering the rearranging.

When the user clicks on a link, something needs to happen.

$('#month a').click(function(){
  		
  	var month = $(this).attr('data-filter');
  
  	$('#month').attr('data-active', month);

  	reorder();
 
 	return false;
});

When a link inside the “#month” div is clicked, that means the user wants to filter the posts according to a single month. So, we need to withdraw the value of the “data-filter” attribute to find out how exactly we need to filter the content. Now, we’ll create a “data-active” attribute to hold what month the content should be filtered by. Lastly, we call the reorder function, which we’ll create in a moment.

Very similar code can be used for the “year” links.

$('#year a').click(function(){
  		
  	var year = $(this).attr('data-filter');
  
  	$('#year').attr('data-active', year);
  
  	reorder();
  
  	return false;
});

Same logic as for the “month” links. When a link is clicked, store its “data-filter” attribute in the “data-active” attribute.

Lastly, we need to create the “reorder” function. When this function is called, it will check the values of the “#month” and “#year” divs, combine them, and filter the content with them. How is it possible to combine them? Simple: jQuery can use the following syntax in selecting elements:

$('.class1.class2')

This selects any elements with both classes. Isotope can also do this.

function reorder(){
		
	var month = $('#month').attr('data-active');
	var year = $('#year').attr('data-active');
	
	var filterString = month+year;
	
	$container.isotope({
		filter: filterString,
		animationOptions: {
   			duration: 750,
    		easing: 'linear',
   			queue: false,
   		}
	});		
}

This works in some cases, but there are some things this is missing. First of all, what if the user has only clicked a “month” link, but not a “year” link? The variable “filterString” will look something like this: “.julyundefined”. The “undefined” is there because the year hasn’t actually been defined yet, since a “year” link hasn’t been clicked yet.

So, to fix this:

if (typeof month === 'undefined') {
   	month = "";
}
if (typeof year === 'undefined') {
  	year = "";
}
		
var filterString = month+year;

This checks to see if each variable has been defined yet, and if it hasn’t, changes the variable’s value to “”, so isotope can filter properly even with only one link clicked.

The resulting function works better, but there are still some issues. If both “All” links are clicked, the “filterString” looks like this: “**”. That doesn’t work…

var filterString = month+year;
		
if(filterString=="**"){
	filterString = "*";	
}

…But this fixes it.

Lastly, we just need to tell the container to reorder its content:

$container.isotope({
	filter: filterString,
	animationOptions: {
  		duration: 750,
    	easing: 'linear',
   		queue: false,
   	}
});

So, the resulting function looks like this:

function reorder(){
	
	var month = $('#month').attr('data-active');
	var year = $('#year').attr('data-active');
	
	if (typeof month === 'undefined') {
    	month = "";
	}
	if (typeof year === 'undefined') {
    	year = "";
	}
		
	var filterString = month+year;
	
	if(filterString=="**"){
		filterString = "*";	
	}
		
	$container.isotope({
		filter: filterString,
		animationOptions: {
    		duration: 750,
    		easing: 'linear',
   			queue: false,
   		}
	});
			
}

With this code, you should be able to create combination filters on your site as well. That concludes this tutorial; I hope this helped in some way.

]]>
https://www.designlunatic.com/2012/07/a-continuation-of-the-isotope-tutorial-combination-filters/feed/ 4
Create An Image Gallery With CSS3 3D Transforms https://www.designlunatic.com/2012/06/create-an-image-gallery-with-css3-3d-transforms/ https://www.designlunatic.com/2012/06/create-an-image-gallery-with-css3-3d-transforms/#comments Sat, 23 Jun 2012 07:16:48 +0000 Design Lunatic http://www.designlunatic.com/?p=1153 CSS3 offers many exciting new opportunities for web designers looking to spice up their webpages, but one of the most interesting ones are the 3D transforms. Objects on the page can be manipulated in 3D space. In this tutorial, we’ll make an image gallery that utilizes 3D transforms to make things a bit more interesting.

HTML

The first thing we need is an element that will act as a container for the images.

<section id="images">

</section>

Now, we need to create the markup for each image.

<div class="image" title="This is random nonsense, this is random nonsense.">

	<img src="images/1.jpeg">

</div>

There’s a div with a class of “image”, along with a title. This title will be what’s contained in the caption on the back of the image. Inside the div, we have the actual image displayed.

Repeat this structure for 8 more images.

<section id="images">


<div class="image" title="This is random nonsense, this is random nonsense.">

	<img src="images/1.jpeg">

</div>

<div class="image" title="This is random nonsense, this is random nonsense.">

	<img src="images/2.jpeg">

</div>

<div class="image" title="This is random nonsense, this is random nonsense.">

	<img src="images/3.jpeg">

</div>

<div class="image" title="This is random nonsense, this is random nonsense.">

	<img src="images/4.jpeg">

</div>

<div class="image" title="This is random nonsense, this is random nonsense.">

	<img src="images/5.jpeg">

</div>

<div class="image" title="This is random nonsense, this is random nonsense.">

	<img src="images/6.jpeg">

</div>

<div class="image" title="This is random nonsense, this is random nonsense.">

	<img src="images/7.jpeg">

</div>

<div class="image" title="This is random nonsense, this is random nonsense.">

	<img src="images/8.jpeg">

</div>

<div class="image" title="This is random nonsense, this is random nonsense.">

	<img src="images/9.jpeg">

</div>


</section>

That’s all the HTML that’s necessary.

CSS

We’ll start off with some simple styling to make the page look nice. Right now, there’s just a bunch of images stacked vertically on the page. As far as layouts go, it’s not too bad. I’ve seen worse. But in this case, let’s make it a bit easier on the eyes.

body {
background: #eee;	
}

#images {
width: 450px;
height: 450px;
margin: 100px auto 0 auto;

-webkit-box-shadow: 0px 0px 20px 5px #888;
}

A box with a drop shadow on a grey background. Much better. Unfortunately, the images aren’t completely inside it yet.

.image {
width: 150px;
height: 150px;
float: left;
}

This looks nice, but there’s still a few things that need to be added.

.image {
width: 150px;
height: 150px;
float: left;
opacity: 0.9;
-webkit-transition: all 300ms ease;
}

.image:hover {
cursor: pointer;
opacity: 1;
}

That’s all the styles we need for now.

Remember the “title” attribute that each “image” div has? We need a way to put that on the back of each image, and this is where CSS3 psuedo-elements come in. Basically, with only CSS, it is possible to create another element right next to each “image” div we have on the page.

.image:after {
content: attr(title);
}

Now, right after each “image” will be an element with the contents of the “title” attribute inside. However, we also need to position this on the back of each image, and for that we will use CSS3 3D transforms. Before they can be used, the following code needs to be added to the parent element of whatever we’re going to manipulate.

-webkit-perspective: 1000;

Defining perspective is necessary for 3D elements to have… perspective, surprisingly enough. WSC does an excellent job of explaining this.

Without perspective, the elements would look boring and flat when rotating.

#images {
-webkit-perspective: 1000;
width: 450px;
height: 450px;
margin: 100px auto 0 auto;
background: #888;
-webkit-box-shadow: 0px 0px 20px 5px #888;
}

Now the “#images” section is properly set up.

You’ll notice that the “:after” part of each “image” still isn’t in the right spot. Let’s fix this.

.image:after {
content: attr(title);
display: block;
width: 138px;
height: 138px;
padding: 5px;
background: #eee;
border: 1px solid #999;
-webkit-transform: rotateY(180deg) translateY(-153px);
}

Right now, all the pseudo-elements are behind the images – but we can still see them. Paste this code into the “.image:after” part:

-webkit-backface-visibility: hidden;

This makes the backface of it invisible, which allows us to stick it to the back of another element without showing through.

Also, the text looks boring.

font-family: arial;
font-size: 16px;
line-height: 24px;
color: #333;

Better.

So far, for the “.image:after”, you should have the following code.

.image:after {
content: attr(title);
display: block;
width: 138px;
height: 138px;
padding: 5px;
background: #eee;
border: 1px solid #999;
-webkit-transform: rotateY(180deg) translateY(-153px);
-webkit-backface-visibility: hidden;

font-family: arial;
font-size: 16px;
line-height: 24px;
color: #333;
}

Javascript

What do we want to happen when we click on an image? For the image to flip over and reveal the caption underneath. There are several ways to do this, but let’s just use some javascript.

Before we begin, include the jquery library in your code.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>

Now, let’s start.

$(document).ready(function(){

});

This part is necessary so that the code inside only executes when all the elements on the page are fully loaded.

Let’s think this through; we want something to happen when an image is clicked.

$('.image').click(function(){

});

We want it to switch back and forth between being rotated 180 degrees around the Y axis and being rotated 0 degrees around the Y axis. For this, we’ll use the HTML5 “data-” attributes capability. Part of HTML5 is that it is now perfectly acceptable to define a custom attribute beginning with “data-”, such as “data-flipped”, which is what we’ll use. In here, we’ll store whether or not that particular element is flipped.

$('.image').click(function(){
	var flipped = $(this).attr('data-flipped');
});

We can now use this to check if the element is flipped or not.

if(flipped=='yes'){	
	$(this).attr('data-flipped','no');
}
else {
	$(this).attr('data-flipped','yes');			
}

If it isn’t flipped, it is after being clicked. If it was, now it isn’t. Simple. However, this doesn’t actually make the thing flip. Let’s fix that.

if(flipped=='yes'){	
	$(this).attr('data-flipped','no');
			
	$(this).attr('style','-webkit-transform: rotateY(0deg);');
}
else {
	$(this).attr('data-flipped','yes');
			
	$(this).attr('style','-webkit-transform: rotateY(-180deg);');
			
}

Done. Here’s all the code you should have:

$(document).ready(function(){
	
	$('.image').click(function(){
		var flipped = $(this).attr('data-flipped');
		
		
		if(flipped=='yes'){	
			$(this).attr('data-flipped','no');
			
			$(this).attr('style','-webkit-transform: rotateY(0deg);');
		}
		else {
			$(this).attr('data-flipped','yes');
			
			$(this).attr('style','-webkit-transform: rotateY(-180deg);');
			
		}
	
	});
	
});

At this point, you should have a working image gallery with flipping images and captions. I hope you enjoyed creating this, and that you learned something today. As always, the comment section is below if you have any questions or… well, comments.

]]>
https://www.designlunatic.com/2012/06/create-an-image-gallery-with-css3-3d-transforms/feed/ 0
A Continuation of the Isotope Tutorial: Highlight the currently active link https://www.designlunatic.com/2012/05/a-continuation-of-the-isotope-tutorial-highlight-the-currently-active-link/ https://www.designlunatic.com/2012/05/a-continuation-of-the-isotope-tutorial-highlight-the-currently-active-link/#comments Sun, 20 May 2012 19:52:33 +0000 Design Lunatic http://www.designlunatic.com/?p=1122 Isotope.js, the user won't know what is currently being displayed. In this post, I'll show how that can be fixed so that the user can have an excellent experience even on a site using Isotope.]]> In web design, the navigation bar is crucial in telling the user where he is located. Usually, the user is further helped out by highlighting the currently active menu item. For example, if the user is on the “About Us” page, the “About Us” link in the navigation bar will be styled to look different. Unfortunately, if the site uses Isotope.js, the user won’t know what is currently being displayed. In this post, I’ll show how that can be fixed so that the user can have an excellent experience even on a site using Isotope.

This post will be based on the code from the isotope tutorial I wrote a while ago, so grab a copy of the code from there.

HTML

The HTML we’ll use is identical to the code from the isotope tutorial you just downloaded, except for one small thing.

Add data-current="" to the #content div, so that the result looks like this:

<div id="content" data-current="">

We’ll be using this attribute to store the category that is currently being shown.

CSS

The CSS is exactly the same as from the isotope tutorial previously. No need to change anything here.

Javascript

We’ll rewrite the javascript code from the previous tutorial, as it has changed considerably.

First of all, make a nice $(document).ready function:

$(document).ready(function(){

});

Now, we need to write the code that will “isotope” the boxes on the page.

var $container = $('#content');
var toFilter = '*';

$container.isotope({
	filter: toFilter,
	animationOptions: {
		duration: 750,
		easing: 'linear',
		queue: false,
	}
});

Here, the variable $container is whatever container you want to isotope. The variable toFilter is what the $container is filtered by. The reason we have a variable for this is because later on in the code, we have to know what what $container is filtered by. The rest of the code is isotope-specific, and is completely self-explanatory.

Remember that “data-current” attribute on the $container? We’ll start to use it now.

$container.attr('data-current',toFilter);

This code sets teh “data-current” attribute to what the $container was originally filtered by. This way, we can highlight the currently active navigation as soon as the page loads. More on that later.

We can now write the function that will determine what the $container is currently being filtered by, which we’ll call “checkActive”.

function checkActive(){

	$('#nav a').each(function(){
	
	});

}

Inside the “checkActive” function, we have a .each function. This basically iterates over each element that matches the selector. In this case, the code inside the “each” function repeats itself for each #nav a.

Now, take a look at the title of each nav link. Notice the fact that it doesn’t have a “.” at the beginning of it. This needs to be fixed before we can accurately compare the “data-current” attribute with the title of each nav link.

function checkActive(){

	$('#nav a').each(function(){
		
		var title = $(this).attr('title');	
		title = '.'+title;
		
	});

}

This takes the title attribute of the nav link the each function is currently iterating over, and adds a “.” to the beginnnig of it.

But wait! What if the title attribute is “*”, like in the link that says “All”?

function checkActive(){

	$('#nav a').each(function(){
		
		var title = $(this).attr('title');	
		title = '.'+title;
		
		if(title=='.*'){
			title = '*';
		}
		
	});

}


That fixes it.

In order to find out which link to highlight, we need to find out which category is currently being displayed.

function checkActive(){

	$('#nav a').each(function(){
		
		var title = $(this).attr('title');	
		title = '.'+title;
		
		if(title=='.*'){
			title = '*';
		}
		
		var currentCat = $container.attr('data-current');
	});

}

Now, we can compare the two to find out whether the link the each function is currently on is the right one or not.

if(title==currentCat){
	$(this).css({
		color: '#00ff00'
	});
}

Here’s what we have so far:

function checkActive(){

	$('#nav a').each(function(){
		
		var title = $(this).attr('title');	
		title = '.'+title;
		
		if(title=='.*'){
			title = '*';
		}
		
		var currentCat = $container.attr('data-current');
		
		if(title==currentCat){
			$(this).css({
				color: '#00ff00'
			});
		}
		
	});

}

However, there’s a slight problem with this code: the links won’t return to their previous states if the active category changes. We can fix this by making a type of “reset” that will make all links the way they were originally, and then changing whichever one needs to be changed.

function checkActive(){

	$('#nav a').each(function(){
		
		$(this).css({
			color: '#595959'
		});
		
		var title = $(this).attr('title');	
		title = '.'+title;
		
		if(title=='.*'){
			title = '*';
		}
		
		var currentCat = $container.attr('data-current');
		
		if(title==currentCat){
			$(this).css({
				color: '#00ff00'
			});
		}
		
	});

}

We can now create the rest of the javascript code.

Here’s where we left off:

var $container = $('#content');
var toFilter = '*';

$container.isotope({
	filter: toFilter,
	animationOptions: {
		duration: 750,
		easing: 'linear',
		queue: false,
	}
});

$container.attr('data-current',toFilter);

checkActive();

With this code, the “checkActive” function will fire right after the $container is isotoped, and will highlight the “All” link.

Now, we need to make the nav links actually work.

$('#nav a').click(function(){
	return false;
});

This way, when a nav link is clicked, it won’t actually redirect the user to a different page.

In order to filter the $container, we need to define a few variables.

$('#nav a').click(function(){
	
	var title = $(this).attr('title');
	var text = $(this).text();
		
	return false;
});		

Now, we have to check with or not the link that was just clicked is the “All” link or not.

$('#nav a').click(function(){
	
	var title = $(this).attr('title');
	var text = $(this).text();
		
	if(text == "All"){
		var selector = title;
	}
	else {
		var selector = "." + title;
	}	
	
	
	return false;
});	

Next, we need to set the “data-current” attribute of the $container to reflect what it is being filtered by.

$('#nav a').click(function(){
	
	var title = $(this).attr('title');
	var text = $(this).text();
		
	if(text == "All"){
		var selector = title;
	}
	else {
		var selector = "." + title;
	}	
	
	$container.attr('data-current',selector);
	
	return false;
});	

Now that we’ve defined what the $container is currently being filtered by, we need to actually filter the $container.

$('#nav a').click(function(){
	
	var title = $(this).attr('title');
	var text = $(this).text();
		
	if(text == "All"){
		var selector = title;
	}
	else {
		var selector = "." + title;
	}	
	
	$container.attr('data-current',selector);
	
	$container.isotope({ 
		filter: selector,
		animationOptions: {
			duration: 750,
			easing: 'linear',
			queue: false,
		}
	});
	
	return false;
});	

After the $container has been filtered, we have to run the “checkActive” function to highlight the currently active link.

$('#nav a').click(function(){
	
	var title = $(this).attr('title');
	var text = $(this).text();
		
	if(text == "All"){
		var selector = title;
	}
	else {
		var selector = "." + title;
	}	
	
	$container.attr('data-current',selector);
	
	$container.isotope({ 
		filter: selector,
		animationOptions: {
			duration: 750,
			easing: 'linear',
			queue: false,
		}
	});
	
	checkActive();
	
	return false;
});	

And there you have it: upon clicking a link in the navigation, it becomes different-looking so that the user knows what is currently being displayed. Now, you may wonder why we didn’t just make the link change color upon being clicked without worrying about the “data-current” attribute and all that. The reason is that this code works much more flexibly and with many other situations. For example, what if there’s a link inside the content of the page? All you need to do is modify the $('#nav a') selector to include links inside the post, and when a link in the post is clicked that filters the content, the navigation changes to reflect that. Or, what if there’s another piece of code that needs to know what category is currently being displayed? You don’t even have to modify anthing! Just find out the “data-current” attribute of the $container, and you’re done.

In other words, this code is highly flexible and adaptible, and not just this situation specific. I hope you learned something from this tutorial. If you have any questions or comments, feel free to use the comment form below.

]]>
https://www.designlunatic.com/2012/05/a-continuation-of-the-isotope-tutorial-highlight-the-currently-active-link/feed/ 13
Jquery Lavalamp Menu with Keyboard Control https://www.designlunatic.com/2011/12/jquery-lavalamp-menu-with-keyboard-control/ https://www.designlunatic.com/2011/12/jquery-lavalamp-menu-with-keyboard-control/#comments Thu, 29 Dec 2011 02:56:17 +0000 Design Lunatic http://www.designlunatic.com/?p=899 Today, I will explain how to create a jquery lavalamp menu. However, this is more than just a simple lavalamp menu; it will also have keyboard navigation. Sound interesting? Let’s get started!

HTML

The menu we’ll be creating has a simple markup consisting of “nav” element to hold everything, a “ul” to hold the menu content, and an “underline” div that will change position depending on what nav item is currently active.

<nav id="menu">

	<ul>
		<li id="nav1"><a href="#home">Home</a></li>
		<li id="nav2"><a href="#blog">Blog</a></li>
		<li id="nav3"><a href="#about">About</a></li>
		<li id="nav4"><a href="#contact">Contact</a></li>
	</ul>
	
	<div id="underline" class="pos1"></div>
	
</nav>

That’s all the HTML we’ll need.

CSS

Grab Eric Meyer’s CSS Reset before continuing. Now, we’ll give the body some simple styling.

body {
background: #f8f8f8;
font-family: arial;
}

This way, we’ll have a light grey body background, with the text on the page being Arial.

The menu requires some slightly more complicated styling.

#menu {
margin: 0 auto;
margin-top: 50px;
width: 400px;
height: 45px;
font-size: 18px;
line-height: 45px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
background: #ffffff;
border: 1px solid #CACACA;
-webkit-box-shadow: 0px 0px 3px 1px #ebebeb;
-moz-box-shadow: 0px 0px 3px 1px #ebebeb;
box-shadow: 0px 0px 3px 1px #ebebeb;
}

The menu is centered, and is 50px from the top of the page. It’s got a nice width of 400px, and a height of 45px. The menu text is 18px, and has a line-height of 45px. The line-height is the same as the height of the menu so that the text is vertically centered. We then give the menu some nice rounded corners by using the “border-radius” CSS3 property. We also give the menu a white background and a grey border, as well as a box-shadow to make it more interesting.

Now, we have to style the menu items.

#menu ul li{
float: left;
width: 100px;
text-align: center;
}

Each menu item is floated to the left so that the menu items are in a horizontal row. They all have a width of 100px so that the four menu items end up fitting inside the 400px menu perfectly. They also have “text-align” set to “center” so that the text inside is centered rather than being aligned to the left.

Now, the links.

#menu ul li a {
display: block;
color: #515151;
}

Each menu link has “display: block” so that the link takes up the whole “li” space. In other words, the whole item is clickable rather than the just the text. They also have a color of #515151, which is a nice dark grey color.

Lastly, we’ve got to style the underline that will change position depending on what menu item is active.

#underline {
-webkit-transition: all 300ms ease;
-moz-transition: all 300ms ease;
-o-transition: all 300ms ease;
transition: all 300ms ease;

-moz-border-radius-topleft: 0px;
-moz-border-radius-topright: 0px;
-moz-border-radius-bottomright: 10px;
-moz-border-radius-bottomleft: 10px;
-webkit-border-radius: 0px 0px 10px 10px;
border-radius: 0px 0px 10px 10px;

position: relative;
top: 40px;
width: 100px;
height: 5px;
background: #515151;
}

First of all, we make the underline have an animation length so that when it changes position, it moves over instead of instantly jumping over to the new spot. It also has a border-radius that is the same as the menu’s so that when the underline is at the edge of the menu, it doesn’t pop out of the borders. Its “position” is set to “relative” so that we can use the “top” property. Next, we use “top” to shift it 40px down. This way, the underline is right at the bottom of the menu. Then, we give it a width of 100px which is the same as each menu item, and a height of 5px. Lastly, we give it a background color.

Now, we have one more thing left to do.

.pos1 {
left: 0px;
}

.pos2 {
left: 100px;
}

.pos3 {
left: 200px;
}

.pos4{
left: 300px;
}

We’ll be using javascript to apply these classes to the underline depending on what link is currently active. For example, if the user hovers over the third link, the javascript will apply the “pos3″ class to the underline.

Jquery

Before we start with the code, I’ll go over what we’ll have once we’re done.

  1. A $(document).ready function so that the code executes only when the document is fully loaded.
  2. A menu item hover function so that we can move the underline to the correct spot.
  3. A $(document).keydown function with a switch so that we can check which key was pressed and apply the correct javascript.
  4. Two different cases inside the switch – one of them for the right arrow key and the other for the left arrow key.

Now, we can start.

$(document).ready(function(){
	$('#menu ul li').hover(function(){

	});
});

There’s the document ready function, and the menu item hover function. This checks to see if the user has hovered over one of the menu items.

$('#menu ul li').hover(function(){
		
	var pos = $(this).attr('id').substring(3);
			
	$('#underline').removeClass();
	$('#underline').addClass('pos'+pos);
		
});

First off, we create a variable called “pos” which is the number of the menu item just hovered over. We get this number by taking the ID of the item just hovered on, and then using the “substring” method to remove the first three characters.

Next, we remove all the classes from the underline, so that we have a clean foundation to work on. Then, we add one of the four “pos” classes to make the underline move over underneath the hovered link.

That’s it for the hover function. Now, we’ll write the javascript to handle the key presses.

$(document).keydown(function(e){
	switch(e.which)
	{
		// user presses left
		case 37:
		
		break;
	
		// user presses right
		case 39:
		
		break;
		
		//user presses enter
		case 13:
		
		break;
	
	}
});		

This is a simple keydown function with a switch inside. Each key on the keyboard has a unique ID that we can use to check what key was pressed. Depending on what key was pressed, different things will happen.

// user presses left
case 37:
			
	var prevPosStr = $('#underline').attr('class').substring(3);
	var prevPos = parseInt(prevPosStr);
			
	var newPos = prevPos-1;
			
	if(newPos<1){
		newPos=4;
	}
	
	$('#underline').removeClass();
	$('#underline').addClass('pos'+newPos);
	
break;

This is what happens if the user presses the left arrow key. First of all, we create a variable called “prevPosStr”. This variable takes the current class of the underline, and removes the first 3 characters. We then turn this variable into an integer by using the “parseInt” method. Now, we have a “prevPos” variable which contains the number of the menu item before the underline animates. In other words, if the underline was underneath the second menu item and the user presses the left arrow key, the value of the “prevPos” variable would be 2.
Now, we create a variable called “newPos”. The value of this variable is prevPos-1 so that the underline moves on spot to the left. Once we define the “newPos” variable, we have a simple “if” statement. This statement checks to see if the “newPos” variable is less than 1. If it is, it changes the value to be 4. This way, if the underline is under the first menu item and the user presses left, the underline will move over to the last menu item.
Lastly, we actually animate the underline. We remove all classes from the underline, and then we add one of our four “pos” classes.

Now, we’ll write the code that handles the right arrow key.

// user presses right
case 39:
			
	var prevPosStr = $('#underline').attr('class').substring(3);
	var prevPos = parseInt(prevPosStr);
			
	var newPos = prevPos+1;
			
	if(newPos>4){
		newPos=1;
	}
			
	$('#underline').removeClass();
	$('#underline').addClass('pos'+newPos);
			
break;

This code is very similar to the code for the left arrow key. The two differences here are:

  1. The “newPos” variable is 1 larger than the “prevPos” variable.
  2. The “if” statement is the opposite of the one for the left arrow key. If the underline is underneath the fourth menu item and the user presses the right arrow key, the underline moves over to the first menu item.

There’s one last thing we need to do. We’ll make the enter key follow the link of the item underneath the underline. For example, if the underline is under the “Blog” link, pressing enter will redirect the user to the blog.

//user presses enter
case 13:
	var posStr = $('#underline').attr('class').substring(3);
	var pos = parseInt(posStr);
			
	var link = $('#nav'+pos+' a').attr('href');
			
	window.location.href = link;
			
break;

First off, we create the “posStr” and “pos” variables so that we know under what menu item the underline is. Next up, we create a variable called “link. This variable takes the value of the “href” attribute of the “a” element inside the current menu item. Lastly, we use “window.location.href” to redirect the user to the link.

Well, that’s the end of this tutorial. If you have any questions or comments, feel free to post them below. Good luck and have fun!

]]>
https://www.designlunatic.com/2011/12/jquery-lavalamp-menu-with-keyboard-control/feed/ 0
Swipe Gestures With Jquery https://www.designlunatic.com/2011/10/swipe-gestures-with-jquery/ https://www.designlunatic.com/2011/10/swipe-gestures-with-jquery/#comments Wed, 26 Oct 2011 05:41:51 +0000 Design Lunatic http://www.designlunatic.com/?p=823 In this tutorial, I will explain how to create swipe gestures in Jquery, and use these gestures to create a simple image gallery.

We’ll do this tutorial in two parts: Part 1 will be how to actually figure out which way the mouse was moved, and Part 2 will be about how to use this to create a gallery.

Part 1

First, we’ll write some simple HTML.

<div id="status1"></div>
<div id="status2"></div>
<div id="dir"></div>

Before we can start the gallery, we’re going to have to build the fundamentals. Here’s how this works: On mouse click, the X position of the mouse is recorded into a the div “status1″. When the mouse is released(presumably in a different spot), the mouse’s coordinates are recorded into “status2″. This way, we can compare the two coordinates. Depending on which is larger, we can tell in which direction the mouse was moved. Then, the direction the mouse was moved is recorded into the “dir” div.

Now, we can write the javascript for the above logic.

$(document).ready(function(){

$(document).mousedown(function(e){
	
	var mousePos1 = e.pageX;
		
	$('#status1').html(mousePos1);
}); 

});

When the document is ready, create a “mousedown” handler. Using jquery’s “pageX” attribute, we find the mouse’s X position and put that into the “mousePos1″ variable. We then place the value of the variable into the “status1″ div. We do this so that we can later on extract the text inside the “status1″ div and compare that to the mouse’s position when it is released.

Now that we’re done with the “mousedown” function, we can create the “mouseup” function.

$(document).mouseup(function(e){
	
		var mousePos2 = e.pageX;
		
		$('#status2').html(mousePos2);
		
		var status1 = $('#status1').text();
		var status2 = $('#status2').text();
		
		var dif = status2 - status1;

    }); 

The variable “mousePos2″ contains the mouse’s X position. Then, we write the value of the variable into the “status2″ div. Once we have the 2 different positions of the mouse inside the two status divs, we can compare them. The “dif” variable is the difference between the second and first position. If the difference is positive, the mouse was moved towards the right. If the difference is negative, the mouse was moved to the left. Then, we place the direction into the “dir” variable. This isn’t actually necessary, but it’s nice to have some feedback.

if(dif>0){
	var dir = 'right';	
}
else{
	var dir = 'left';
}
		
$('#dir').html(dir);

Well, if you did everything right up until this point, you should have three blocks of text at the top of your page. The first position, the second position, and the direction the mouse was moved in.

Part 2

Now, we can move on to the swipe-based gallery.

First off, we’ll need some simple HTML.

<div id="gallery">
<div id="slides">

	<section class="slide" id="slide1">
		<img src="images/test1.jpg">
	</section>
	
	<section class="slide" id="slide2">
		<img src="images/test2.jpg">
	</section>
	
	<section class="slide" id="slide3">
		<img src="images/test3.jpg">
	</section>
	
	<section class="slide" id="slide4">
		<img src="images/test4.jpg">
	</section>
	
	<section class="slide" id="slide5">
		<img src="images/test5.jpg">
	</section>
	
	<section class="slide" id="slide6">
		<img src="images/test6.jpg">
	</section>

</div>
</div>

There’s a “gallery” div which contains all of the gallery content. The “slides” div contains all of the images, stacked side by side. Simple.

Now, we’ll style this a little bit.

body {
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
background: #f8f8f8;
font-family: arial;
font-size: 15px;
line-height: 25px;
color: #515151;
}

#gallery {
margin: 0 auto;
margin-top: 50px;
overflow: hidden;
width: 640px;
height: 360px;
}

#slides {
width: 10000px;
}

.slide {
float: left;
}

The body has CSS3 user-select styles set to none so that users can’t select anything on the page. This is necessary so that when the user is dragging his mouse, nothing gets selected. Everything else is just simple gallery styling. The “gallery” div has a width, height, and overflow: hidden. The “slides” div inside the “gallery” div has a huge width, and each “slide” is floated to the left to be side by side.

At this point, we have everything we need to create the gesture-based gallery. Let’s get to work.

var pos = 0;
	
	$(document).mouseup(function(e){
	
		var mousePos2 = e.pageX;
		
		$('#status2').html(mousePos2);
		
		var status1 = $('#status1').text();
		var status2 = $('#status2').text();
		
		var dif = status2 - status1;

Notice the “pos” variable we’ve added right before the mouseup function. This is where the slideshow is currently at; the value of this variable will be changed each time the user swipes across the screen.

Now, we’ll have to write some functions that will animate the “slides”.

function slideToLeft(slidePos) {
	
	$('#slides').animate({
		marginLeft: '-' + slidePos,
	});
	
}

A “slidePos” variable is passed to this function. This number has to be a multiple of 640, or else we’ll end up seeing 2 images at the same time.

function slideToRight(slidePos) {
	
	$('#slides').animate({
		marginLeft: slidePos,
	});
	
}

This is the same exact thing, except without the negative sign before the “slidePos”.

Now that we have these two functions, we can modify the if…else statement to make the slideshow work.

if(dif>0){
	var dir = 'right';
			
	if(pos>0){
		pos--;
	}
	else{
	}
			
	slideToLeft(640*pos);
}
else{
	var dir = 'left';
			
			
	var marginLeft = $('#slides').css('margin-left');
	if(pos > 4){
	}
	else{
		pos++;
		slideToLeft(640*pos);
	}
	
}

In the each section of the if…else statement, you’ll notice another if…else statement. The “if” clause inside the second if…else statement checks to see if the “pos” variable is too big or to small. If the position of the slideshow is too big or too small, it won’t be animated. Otherwise, we call on the “slideToLeft” or “slideToRight” functions. In the “else” clause of the second if…else statements, we increment the value of “pos” if the slides are moving to the left, and decrement it if the slides are moving to the right. Then, once the value of the “pos” variable has changed, we call the appropriate function. We then pass the value of 640 times the “pos” variable to the function, so that the “margin-left” of the slides is animated to the right position.

This tutorial was quite complicated, but the result is pretty great. That’s the end of this tutorial; Good luck and have fun!

]]>
https://www.designlunatic.com/2011/10/swipe-gestures-with-jquery/feed/ 5