Tag Archives: javascript

Javascript countdown

So I’ve created this little countdown tool.

This will count down to a specific date and time… and then display a specific message during and then after the specified time.

The tool being used to countdown to Earth Hour on the WWF website
The tool being used to countdown to Earth Hour on the WWF website

It’s pretty lightweight (and relies on JQuery – again)

The Countdown HTML:

<span class="lineOne">This is where the countdown goes </span>
<span class="subLine">until the event</span>

The Countdown Javascript:

You’ll see on line 8 and 9 there are timestamps – these are for the beginning and the end of the event – you’ll have to figure out what the timestamps for these dates and times are.

Line 44 and 49 are the messages that will come up during and after the event.

$(document).ready(function(){
		console.log("ping");
		var 	countSpeed = 2,
			dayLength = 86400000,
			hourLength = 3600000,
			minLength = 60000,
			secondLength = 1000,
			eventStamp = 1396125000000,
			eventOverStamp = 1396128600000;
			setInterval(countUp,1000 / countSpeed);

		function countUp(){

			var 	thisNow = jQuery.now(),
				eventDiff = eventStamp - thisNow,
				daysLeft = eventDiff / dayLength,
				daysLeft = Math.floor(daysLeft),
				hoursLeft = (eventDiff - (daysLeft * dayLength)) / hourLength,
				hoursLeft = Math.floor(hoursLeft),
				minsLeft = (eventDiff - (daysLeft * dayLength) - (hoursLeft * hourLength)) / minLength,
				minsLeft = Math.floor(minsLeft),
				secsLeft = (eventDiff - (daysLeft * dayLength) - (hoursLeft * hourLength) - (minsLeft * minLength)) / secondLength,
				secsLeft = Math.floor(secsLeft);
				millisLeft = eventDiff - (daysLeft * dayLength) - (hoursLeft * hourLength) - (minsLeft * minLength) - (secsLeft * secondLength);
				if(millisLeft > 99) { 
					millisLeft = ""+millisLeft;
					millisLeft = millisLeft.substring(0, millisLeft.length - 1);
				}
				if(secsLeft<10){ secsLeft = "0" + secsLeft; }
				if(minsLeft<10){ minsLeft = "0" + minsLeft; }
				if(hoursLeft<10){ hoursLeft = "0" + hoursLeft; }
				if(daysLeft<10){ daysLeft = "0" + daysLeft; }

			$(".lineOne").empty().append("00 days 00 hours 00 minutes 00 seconds ");
			$("#days").empty().append(daysLeft);
			$("#hours").empty().append(hoursLeft);
			$("#minutes").empty().append(minsLeft);
			$("#seconds").empty().append(secsLeft);
			$("#millis").empty().append(millisLeft);

			if(thisNow > eventStamp && thisNow < eventOverStamp){ 				$(".lineOne").empty().append("Earth Hour"); 				$(".subLine").empty().append("is currently underway").css("margin-top", "180px"); 				$("#heroSpace .wwf_button").empty().append("Find out what's happening"); 			} 			else if (thisNow > eventOverStamp){
				$(".lineOne").empty().append("Earth Hour");
				$(".subLine").empty().append("has been and gone").css("margin-top", "180px");
				$("#heroSpace .wwf_button").empty().append("Find out what happened");
			}

		};

	})

Obviously – please feel free to use as you wish. Let me know how you’ve found it in the comments.

Count down to Earth Hour

So this week was the 60 day count down to Earth Hour and to celebrate WWF produced a list of 60 things to do in the dark.

To remind visitors about the campaign we booked in a homepage take over of the main WWF site focusing on Earth Hour and in particular the count down… which gave me an opportunity to play with some simple js and do something a little fun.

Earth Hour on the WWF homepage
Earth Hour on the WWF homepage

The code (if you’re interested) is below – for your enjoyment. The stats – so far – are looking good.

Homepages are funny things – and I plan to write a blog post on them soon – but in short we sometimes put a lot of focus on them and forget that visitors usually arrive at our sites for a reason… and that reason is rarely to see what random offering is being featured on the HP.

Anything we can do to draw attention toward valuable calls to action – including the occasional bit of movement – should always be considered (if only to be dismissed). But it is also important not let that get in the way of the user’s journey toward the reason for their visit. This can only lead to a ruined online relationship… so when you’re monitoring look for the impact elsewhere also (negative or positive).

Anyhow – the code:

$(document).ready(function(){
	var countMe = 0,
		countSpeed = 40;
	$(".subLine").fadeOut(0);
	$(".count").empty();
	setInterval(countUp,countSpeed);

	function countUp(){
		$(".count").empty();
		if(countMe<10){ $(".count").append("0" + countMe); }
		else { $(".count").append(countMe); }
		
		if(countMe<60){
			countMe = countMe+1;
		} else {
			$(".subLine").fadeIn(1000);
		}
	}
})

Highlight some text – a dare ya

Today I’ve implemented a little bit of script on my site that allows you – the visitors of this site – to highlight any bit of text that you might want to tweet… and tweet it at the click of a buttons.

Go on…

Give it a go.

It’s quite a simple bit of jQuery script that activates on text highlight.

var myCopy;

function clickToCopy(){
    $(".panel").remove();
}

if(!window.Kolich){
    Kolich = {};
}

Kolich.Selector = {};
Kolich.Selector.getSelected = function(){
    var t = '';
    if(window.getSelection){
        t = window.getSelection();
    } else if(document.getSelection){
        t = document.getSelection();
    } else if(document.selection){
        t = document.selection.createRange().text;
    }
    return t;
}

Kolich.Selector.mouseup = function(event){
    st = Kolich.Selector.getSelected();
    if(st!=''){
        $("body").append("<div class='panel'><a href='http://www.twitter.com' target='_blank' id='textTweet'>Tweet this</a></div>");
        $(".panel").css({
            "left": event.pageX,
            "top": event.pageY
        });
        myCopy = "" + st;

        if(myCopy.length>100){
            var whatDiff = myCopy.length - 100;
            myCopy = myCopy.slice(0,-whatDiff);
        }

        myTweet = myCopy.replace(/\%/g,"%25").replace(/ /g, '%20').replace(/!/g,"%21").replace(/"/g,"%22").replace(/#/g,"%23").replace(/\$/g,"%26").replace(/\&/g,"%26").replace(/'/g,"%27").replace(/\(/g,"%28").replace(/\)/g,"%29").replace(/@/g,"%40");

$("#textTweet").attr("href", "http://twitter.com/home?status=" + myTweet + "...%20" + window.location.href);

    } else { $(".panel").remove();}
}

$(document).ready(function(){
    $(document).bind("mouseup", Kolich.Selector.mouseup);
});

The purpose of this is less about the what it does (and being a smart-arse)… but more an experiment in allowing visitors to better choose what they share socially (rather than the bog-standard “Share this page”-type button.

Part two of this will be to also include a “copy to clipboard” option… which also allows for better analytical tracking… but this is yet to come (watch this space).

Update: I’m also going to try and make it work a little better in instances where the selected text is longer  than the characters allowed.

Load on scroll

On the homepage of this (my) site you may have noticed that each article only appears as you scroll to it.

I say “may have noticed” as hopefully each section loads before you reach it so the only thing you’ll notice is the scroll bar jumping from the bottom of the bar to somewhere higher as the page becomes longer.

It’s quite a simple bit of script that basically removes all specified elements as the page loads. It then re-adds them to the DOM as the user scrolls down the page. This has decreased the load time for my homepage by around 75%.

There are probably more sophisticated ways of doing this (certainly some using AJAX) but this is a reasonably quick win that effectively reduced load time.

Here is how to make sections or elements of your page appear as you scroll to them:

The JS:

var windowHeight = $(window).height();
	storedDivs = [];

$(document).ready(function(){
	console.log(windowHeight);
	$(".post").each(function(){
		var myPosition = $(this).offset();
		//console.log(myPosition);
		if(myPosition.top>windowHeight){
			$(this).addClass("hidden");
			var myContents = $(this).html();
			storedDivs.push(myContents);
			$(this).empty();
		}
	});
})

$(window).scroll(function(){
	    var fromTop = $(window).scrollTop();
		$(".hidden").each(function(){
			var myDifference = $(this).offset().top - fromTop;
			//console.log(myDifference);
			if(myDifference < windowHeight){
				$(this).empty();
				$(this).append(storedDivs[0]);
				storedDivs.shift();
				console.log("changed something");
				$(this).removeClass("hidden");

				/*  ADD AND JS FUNCTIONS TO FIRE HERE  */
				//exampleFunction();
			}
		});
	});

In the above JS you’ll notice on line six the class “post” is specified. This is the element(s) which the JS searches for – and then hides – when the page loads.

To make this work on your site simply add the “post” class to each element you want to be effected or change the class specified on line six to the class you currently use on your site.

It is also worth noting the space on line 32 which is where you can add functions that need to fire after the content has been added back into the page. For instance Facebook comments use a bit of JS to render them – you’d need to fire this JS at this point.

Simple jquery quiz

So I was inspired by the BBC’s quiz of the year but thought – why do they use flash (eurgh)… so figured I’d see how difficult it might be to create a fully html version of it.

What I’ve ended up with is a simple-to-use bit of JS script – using jQuery – and some basic HTML and CSS mark up. It does most of the heavy lifting automatically (hopefully making it easy to implement for coders at any level).

Please note: this is my first ever tutorial so if this doesn’t make sense feel free to let me know in the comments so that I can update it accordingly.

This is (an largely un-styled) version of what you’ll end up with:

  • Q1:Is this question one?




    Next
  • Q2:Is this question two?




    Next
  • Q3:Is this question three?




    Next
  • You have scored

    Some summary text here to end the quiz

“How can I add this sexy quiz to my site?” I hear you ask. Well simply download the zip file and/or follow the steps outlined below.

HTML:
Basically to add a new question to your quiz you simply need to add a new list item (<li>) containing the question… copy & pasting might be the easiest way to do this.
Then all you need to do is update the labels, ids and values for the answers – e.g. the values for the fourth questions should be “answer4a”, “answer4b”, etc.

<ul class="theQuiz">
<li class="question q1 transition">
<form class="quizQ">
<h1>Q1:<span>Is this question one?</span></h1>
<label for="answer1a"><input class="answer" id="answer1a" type="radio" name="answer1" value="answer1a" />Yes</label>
<label for="answer1b"><input class="answer" id="answer1b" type="radio" name="answer1" value="answer1b" />No</label>
<label for="answer1c"><input class="answer" id="answer1c" type="radio" name="answer1" value="answer1c" />Nope</label>
<label for="answer1d"><input class="answer" id="answer1d" type="radio" name="answer1" value="answer1d" />Incorrect</label>
<div class="submit">Next</div>
</form>
</li>
<li class="question q2 transition">
<form class="quizQ">
<h1>Q2:<span>Is this question two?</span></h1>
<label for="answer2a">
<input class="answer" id="answer2a" type="radio" name="answer2" value="answer2a" />No</label>
<label for="answer2b"><input class="answer" id="answer2b" type="radio" name="answer2" value="answer2b" />You bet</label>
<label for="answer2c"><input class="answer" id="answer2c" type="radio" name="answer2" value="answer2c" />Nope</label>
<label for="answer2d"><input class="answer" id="answer2d" type="radio" name="answer2" value="answer2d" />Not at all</label>
<div class="submit">Next</div>
</form>
</li>
<li class="question q3 transition">
<form class="quizQ">
<h1>Q3:<span>Is this question three?</span></h1>
<label for="answer3a"><input class="answer" id="answer3a" type="radio" name="answer3" value="answer3a" />Not on your life</label>
<label for="answer3b"><input class="answer" id="answer3b" type="radio" name="answer3" value="answer3b" />No</label>
<label for="answer3c"><input class="answer" id="answer3c" type="radio" name="answer3" value="answer3c" />Indeed</label>
<label for="answer3d"><input class="answer" id="answer3d" type="radio" name="answer3" value="answer3d" />Never</label>
<div class="submit">Next</div>
</form>
</li>
<li class="finalPage">
<p class="yourScore">You have scored</p>
<p class="info">Some summary text here to end the quiz</p>

<div class="shareSpace">
<a class="nav-twitter transition" title="Tweet this page" href="http://twitter.com/home?status=[YOUR_DEFAULT_TWEET]" target=" _blank"><span class="share">Tweet your score</span></a>
<a class="nav-facebook transition" title="Share this page on Facebook" href="http://facebook.com/sharer/sharer.php?u=[URL_TO_SHARE]" target="_blank"><span class="share">Share on Facebook</span></a>
</div>
</li>
</ul>

JS:
The JS here automatically identifies how many questions you’ve added in the HTML.
It also figures out the score (and out of how many it’s from) and generates the tweet (that includes the correct score) at the end.
This does not need altering and should work automatically.
NB: The quiz uses jQuery – so it goes unsaid that this will need to be included on whichever page the quiz will sit. To keep things simple I tend to use the Google Library script.

$(document).ready (function(){
	$(".theQuiz").append('Score:  of ');
	var quizHeight = $(".theQuiz").height(),
		quizQuestionNos = $(".theQuiz li").size()-1,
		answers = [],
		submitted = 0;
	$( ".theQuiz li" ).each(function() {
		$( this ).css("height",quizHeight);
	});
	var thisID = $(this).closest(".quizQ").attr('id');
	$("input").change(function(){
		$(this).closest(".question").attr('id', 'checked');
		thisAnswer = $(this).val();
	});
	$(".submit").click(function(){
		if( $(this).closest(".question").attr('id') == "checked"){
			//pageTracker._trackEvent("Quiz", "question answered", quizName + " - " + thisAnswer);
			$(this).closest(".question").css({
				"position": "absolute",
				"top": "-" + quizHeight + "px",
				"height": quizHeight-10 + "px",
				"margin-bottom": "10px"
			});
			answers.push(thisAnswer);
			checkCorrects();
			submitted++;
			if(submitted>=quizQuestionNos){
				$(".theQuiz").addClass("finished");
				//pageTracker._trackEvent("Quiz", "completed", quizName + " - " + corrects);
				console.log(corrects);
			}
		} 
	});
	checkCorrects();
	function checkCorrects(){
		corrects = 0;
		for(var i=0; i<=(quizQuestionNos-1) && i<=answers.length; i++){
			if(answers[i] == correctAnswers[i]){
				corrects++;
			}
		}
		$("#correctAnswers").empty();
		$("#potentialAnswers").empty();
		$("#correctAnswers").append(corrects);
		$("#potentialAnswers").append(quizQuestionNos);
		var tidyName = quizName.replace(" ", "%20");
		$(".nav-twitter").attr("href", "http://twitter.com/home?status=I've%20scored%20" + corrects + "%20out%20of%20" + quizQuestionNos + "%20in%20" + tidyName + ".%20How%20will%20you%20do?%20" + window.location.href);
	};
})

CSS:
This is the bare-bones CSS. Add images, button styles (etc) to make it your own… knock yourself out.
Also – why not try messing with the transformations to affect how the questions disappear when they’ve been answered.

 .theQuiz {
	font-family: 'Open Sans', sans-serif;
	height:400px;
	list-style-type: none;
	margin:0;
	overflow: hidden;
	padding:0;
	position:relative;
	width:100%;

	background:white;
	background-size:cover;
	border: 1px solid #c4c4c4;
}

	 .theQuiz li {
	 	background:white;
		display: block;
		float:left;
		list-style-type: none;
		list-style: none;
		margin:0;
		padding:0;
		width:100%;

		background: white;
		border-bottom: solid black 1px;
		box-shadow: 0px 4px 4px rgba(0,0,0,0.5);
	}

		li.q1, li.q2, li.q3 { background: #fff4dc;}

		 .theQuiz li form {
			background:white;
			background:rgba(255,255,255,0.8);
			float:left;
			margin:3.3em 0 0 1em;
			padding:10px;
			width:80%
		}

		 .theQuiz li h1 {
			float: left;
			font-family: 'Open Sans',Helvetica,Arial,sans-serif;
			font-size: 3em;
			font-weight: normal;
			line-height: 0.8em;
			position: relative;
			margin: 0 0 10px 0;
			padding: 0;
		}

			 .theQuiz li h1 span {
				clear:left;
				font-size: 0.7em;
				margin: 0 0 0 8px;
			}

			 .question input.answer {
				clear: left;
				float: left;
				margin: 3px 10px 0 10px;
			}

			 .question label {
				float:left;
				margin:10px 0 0 0;
				width:90%;
			}

			 .question .submit {
				clear:left;
				cursor: hand;
				float:right;
				margin:8px 10px 0 10px;
				opacity: 0.3;
			}

				 .question#checked .submit {
					opacity: 1;
				}

			/*.q1, .q2, .q3, .q4, .q5 {
				position:absolute;
					top:0;
					left:0;
			}*/

	 .finalPage {
		background:white;
		background: rgba(255,255,255,0.7);
		float:left;
		margin:1.6em 5%;
		width:90%;
	}

		 .finalPage .yourScore {
			font-size: 2.7em;
			text-align: center;
			margin:0.2em 0 3em 0;
			width:100%;
		}

		 .finalPage .info {
			margin:0 1.1em;
		}

	 .progress {
		background:white;
		background: rgba(255,255,255,0.7);
		font-size: 1em;
		line-height: 0.95em;
		margin: 0;
		padding: 0.4em;
		position: absolute;
			top:0;
			right:0;
		text-align: center;
	}

		 .progress span#correctAnswers,  .progress span#potentialAnswers {
			font-size: 1.4em;
		}

		 .finished .progress {
			background:none;
			font-size: 5em;
			text-align: center;
				top:0.9em;
				right:0;
			width:100%;
		}

			 .finished .progress span#score { display:none; }

	 .yourScore {
		font-size: 2.7em;
		text-align: center;
		margin:0.2em 0;
		width:100%;
	}

.transition {
	-moz-transition: all 600ms ease-out;
	-webkit-transition: all 600ms ease-out;
	-o-transition: all 600ms ease-out;
	transition: all 600ms ease-out;
}

FINALLY:
You will need to include this last bit of JS in your page (ideally somewhere separate within the head). This is the name of your quiz – this will be used in the automatically generated tweet at the end) and the answers.
The adding answers is pretty simple: you just need to add a correct answer for each question you’ve added to your quiz. The correct answer is identified with the value radio of the correct answer from that question. I use the format “answer[question_number][correct_answer_letter]” – e.g. “answer1c” or “answer6a”.
NOTE: these must be added in the correct order – i.e. answer1, answer2, answer3…

<script type="text/javascript">
var correctAnswers = ["answer1a","answer2b","answer3c"],
quizName = "my quiz name";
</script>

Let it snow… let it snow (the return)

Last year I published a post on html5 canvas snow generated with some JS.

To be honest it was a little sh*te… so this year I created some better snow and thought I’d share it with you all to use.

This is an example of what you’re aiming to create:

As you can (hopefully) see it produces snow flakes of varying size and weight that float at random speeds and directions (all whilst spinning in at a random speed and direction).

As if that weren’t enough – thanks to @kgu the JS now measures the CPU impact and alters the amount of snow that is generated so that it is produced at a rate the viewer’s computer can handle.

In this version the background of the canvas element is red but this can be altered in the CSS. I’ve  used this with a transparent background and a absolute position to overlay it above some graphics in the background before.

Play about… have fun… and let me know if it’s worked for you in the comments below.

The HTML:

<canvas id="snowSpace" width="500" height="300"></canvas>

The JS:

var a_canvas = document.getElementById("snowSpace"),
		c = a_canvas.getContext('2d'),
		particles = [],
		j = 0,
		canvasWidth = document.getElementById("snowSpace").width,
		canvasHeight = document.getElementById("snowSpace").height,
		snowColour = "white";
	//LET'S INPUT SOME CODE HERE:
	setInterval(draw, 1000/60);
	var t,t1
	t=new Date();
	t1=new Date();
	function draw(){
		c.clearRect(0,0,canvasWidth,canvasHeight);
		var p = new Particle();
	    if (j%10==0 &&t1.getTime()- t.getTime()<1){
				particles.push(p);
	    }
	t=new Date();
		//RUN THROUGH AN ARRAY OF SNOW FLAKES:
		for(var i = 0; i<particles.length; i++) {
 			p = particles[i];
 			c.save();
 			c.translate(p.xPos,p.yPos);
 			c.rotate(p.ang);
 			c.scale(p.size,p.size);
 			drawFlake(p.thickness);
 			c.restore();
 			p.xPos += p.xVel;
 			p.yPos += p.yVel;
 			p.ang += p.spin;
 			if(p.yPos>canvasHeight*2){
				particles.shift();
			}
		}
		particles.xVel += random(-0.4, 0.4);
		j+=1;
		t1=new Date();
	}
	function Particle(){
		this.size = random(0.05,0.15);
		this.xPos = random(-30, canvasWidth + 30);
		this.yPos = -80;
		this.xVel = random(-0.7, 0.7);
		this.yVel = random(1, 2);
		this.ang = random (-0.5,0.5);
		this.spin = random (-0.05,0.05);
	    this.thickness = random(2,20);
	}
	function drawCross(thickness){
	    c.beginPath();
		c.moveTo(-40, -40);
	    c.lineTo(40,40);
	    c.moveTo(-40, 40)
	    c.lineTo(40, -40)
	    c.lineWidth=thickness ;
		c.strokeStyle = snowColour;
		c.stroke();
	}
	function drawFlake(thickness) {
		c.save();
			drawCross(thickness);
		c.rotate(Math.PI / 4);
			drawCross(thickness);
		c.restore();
	}
	//CREATE RANDOM FUNCTION
	function random(min, max) {
		return Math.random() * (max - min) + min;
	}

The CSS

#snowSpace {
	background: #b80333;
	margin:0;
	overflow:hidden;
}