TutorialZine Tutorials and Freebies

Web Development Tutorials & Resources
Updated: 32 min 11 sec ago

Enhance Your Website with the FullScreen API

4 hours 37 min ago

One of the benefits to having new browser versions out every six weeks, is the rapid pace with which new functionality is introduced. The transition from nightly builds to official releases is merely weeks away. This means that even those of you who keep a close eye on the feature lists might miss an api or two.

This is the case with the Full Screen API. As if overnight, it went from a neat experiment to a feature supported by more than half of the browsers in the wild. Right now you might be wondering how is this different from the regular full screen we’ve had for ages.

What you need to know

With this api, you can display not only entire pages full screen, but individual elements within them as well (something you can’t do with the regular full screen). The intent here is to allow for full screen HTML5 videos and games, so that we can finally declare HTML5 as a viable alternative to Flash.

In short, here is what you need to know about the FullScreen API:

  • Works in Firefox 10, Safari and Chrome;
  • You trigger it using the new requestFullScreen() method;
  • It can display any element full screen, not only the entire page;
  • For security reasons, full screen can only be triggered from an event handler (as to be user initiated);
  • Also for security, Safari blocks all keyboard input except for the arrows and control keys, other browsers show warning messages when typing;
  • The API is still a work in progress, so you have to use the vendor specific methods (prefixed with moz and webkit);

The idea of allowing developers to programatically take up the user screen doesn’t come without serious security implications, which is why keyboard usage is limited. Of course, there are many legitimate uses for keyboard input in full screen, which is going to be addressed in future revisions of the API via some kind of permission prompt.

However, even in its current, limited form, the API still gives us an opportunity to enhance the experience of the end user.

Click to go Full Screen

The basics

According to the W3 draft, we have access to a number of methods and properties that will aid us with the task of switching an element to full screen.

var elem = document.getElementById('#content'); // Make this element full screen asynchronously elem.requestFullscreen(); // When a full screen change is detected, // an event will be dispatched on the document document.addEventListener("fullscreenchange",function(){ // Check if we are in full screen if(document.fullscreen)){ // We are now in full screen! } else{ // We have exited full screen mode } }, false); // We can also exit the full screen mode with code document.exitFullscreen();

At this time, however, dealing with the API is quite more cumbersome, as no browser has support for these methods yet – we will need to use vendor specific ones like elem.mozRequestFullScreen() and elem.webkitRequestFullScreen().

The API also introduces a new CSS pseudo-selector that you can use to style the full screen element.

#content:fullscreen { font-size: 18; }

Of course, it goes without saying that you will also need to supply moz and webkit prefixed versions of this as well. But there is an easier solution.

The jQuery plugin

There is a more elegant solution than ending up with a bunch of ugly code checking for every browser. You can use the jQuery FullScreen plugin, which works around various browser differences and gives you a simple method for triggering full screen mode.

$('#fsButton').click(function(e){ // Use the plugin $('#content').fullScreen(); e.preventDefault(); });

This will bring the #content element full screen. The plugin also adds a flag to the jQuery support object, so you can conditionally show your full screen button or trigger:

if($.support.fullscreen){ // Show the full screen button $('#fsButton').show(); }

To exit the mode, call the fullScreen() method again.

The plugin adds the .fullScreen class to your element, so you can style it without needing to worry about browser-specific versions. Now let’s use it to do some good for the world!

The fun part

If you are a website owner you’ve probably made decisions that deteriorate the experience of your users. This should not come as a surprise to you – you need to show advertising, you need a search box, a navigation bar, a twitter widget, a comment section and all the things that make your site what it is. These are all necessary, but make your content, the very thing that people came to your site for, more difficult to read.

There is also a practical limit to how large your font can be before it gets out of place, not to mention the choice of a type face. If you have a sidebar, this also limits the horizontal space your content can take.

But we can fix this with the new API. We will use the functionality to bring the content section of your site full screen, thus improving the reading experience of your readers even on devices with small displays like laptops and netbooks.

Reader Mode Using the Full Screen API

Making the reading mode

It is pretty straightforward, we only need to some kind of button that will trigger the FullScreen plugin. We can use the $.support.fullscreen flag to test if the current browser supports the API. If it does, we will add the full screen button to the page.

if($.support.fullscreen){ var fullScreenButton = $('<a class="goFullScreen">').appendTo('#buttonStrip'); fullScreenButton.click(function(e){ e.preventDefault(); $('#main').fullScreen(); }); }

When the #main div is brought full screen, it is assigned a width and height of 100%. We will have to work around this if we want it centered in the middle of the screen. This will call for some additional styling, applied only in full screen mode.

a.goFullScreen{ /* The styling of the full screen button goes here */ } /* The following styles are applied only in Full Screen mode */ #main.fullScreen{ /* Adding a width and margin:0 auto to center the container */ width: 860px; margin: 0 auto; /* Increasing the font size for legibility*/ font: 17px serif; padding: 45px 45px 10px; } #main.fullScreen h1{ /* Styling the heading */ font: 56px/1.1 Cambria,"Palatino Linotype",serif; text-align: center; } #main.fullScreen h3{ /* Subheadings */ font: 28px Cambria,"Palatino Linotype",serif; } #main.fullScreen #postAuthor{ /* Centering the post author info */ /* ... */ } /* Hiding unneeded elements and ads */ #main.fullScreen #featuredImage, #main.fullScreen #topMiniShare, #main.fullScreen #wideZineBanner, #main.fullScreen #downloadDemo{ display:none; }

That is all there is to it! Only browsers that support full screen mode will display the button and users will enjoy a better, distraction-free reading experience.

Done!

There are plenty of places in a website where you can use a full screen view – from videos and canvas-based games, to reports and print preview dialogs. I would personally love to see this used for infographics and presentations. We can go a long way with a useful feature like this.

Question of the Day with CodeIgniter and MySQL

Thu, 01/19/2012 - 15:30

In this tutorial we will build a small application with CodeIgniter that will be backed by a MySQL database. It will present questions and give visitors the ability to post answers. There isn’t an admin interface for adding or changing questions, but if you follow and understand this tutorial, you will be able to create one yourself.

As this might be the first exposure to CodeIgniter for some of you, we will start with a brief intro. If you know what CI is, you can skip directly to the code.

First, what is CodeIgniter?

CodeIgniter is a framework for developing web applications in PHP. It will help you properly organize your code using the model-view-controller (MVC) pattern, and give you useful functionality for getting your site up and running quickly. It hides away the tedious work like building and validating forms, communicating with a database, managing error pages and much more.

There are certainly a lot of frameworks to choose from, but CI has the winning combination of a big community, nice documentation and good performance. Unless you enjoy spending time building sites from scratch (which is not a bad thing), using a framework is the smarter way to go.

You should probably start by reading the CodeIgniter introductory guide, which will give you a better understanding of how CI works. Of course, if you are experienced with PHP you can grab the zip and jump directly to the code.

Let’s begin!

The database

Naturally, we will need a table for the questions, and a table for the answers.

The Database Schema

The questions table has only two fields – the ID of the question (automatically assigned with auto_increment) and the question body field. The answers also have an ID column, but they also have a qid field for the id of the question they relate to. The rest of the fields are the email and name of the author, along with the answer body and a timestamp (the dt field).

It is possible to create these tables with PHP code (CI gives us the ability to manipulate tables), but we will keep things simple and design them using a database management system like phpMyAdmin. It is even simpler for you, as I’ve included an export of the tables as an SQL file (tables.sql in the download archive). Import it into your database or copy/paste the code into the SQL tab of phpMyAdmin and you should be ready to go.

Setting up CodeIgniter

At this point you should download CodeIgniter. In this tutorial I am using version 2.1.0, the latest at the time of writing. Extract it in the directory where you are developing your website (move the files outside the CodeIgniter_2.1.0 folder and remove it). We will need to edit a few settings so the framework works the way we want it.

Important: This section assumes that you are downloading a fresh copy of CodeIgniter. If you only want to make the downloaded demo work, you will only need to change your $config['base_url'] setting in config.php, and add your MySQL login details to database.php. The other changes are already made (you still need to create the MySQL tables).

Edit routes.php

The application/config/routes.php file determines which controller is called by default. We need to set this to questions, which we will be creating in a moment.

// Find this line: $route['default_controller'] = "welcome"; // Replace it with this: $route['default_controller'] = "questions";

This will show the questions controller as the start page of the application.

Edit config.php

The application/config/config.php file holds much of the configuration settings of the framework.

// Find this line: $config['base_url'] = ''; // Replace it with the following: $config['base_url'] = 'http://example.com/';

The above setting, base_url, tells CI where your site is located. This information is used when forming links and including resources like stylesheets and images.

The following setting is optional. CodeIgniter adds index.php to every URL by default (like so: http://example.com/index.php/products/). If you want to hide it (so that the url becomes http://example.com/products/), you will need to edit the index_page setting:

// Find this line: $config['index_page'] = 'index.php'; // Replace it with the following: $config['index_page'] = '';

You will also need to create an .htaccess file, which rewrites the URLs so that they still get to index.php, although it is not included explicitly. The .htaccess I use in the demo follows:

.htaccess Options +FollowSymLinks Options +Indexes RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond $1 !^(index\.php) RewriteRule ^(.*)$ index.php/$1 [L]

Now you only need to add your MySQL connection settings so that your application can connect to your database.

Edit database.php

Find these four lines in application/config/database.php and change them to reflect your connection settings:

$db['default']['hostname'] = 'localhost'; $db['default']['username'] = 'user'; $db['default']['password'] = 'pass'; $db['default']['database'] = 'your_database_name';

Great! We are done setting up CodeIgniter, so we can now move on with the code.

Question of the Day with CodeIgniter

Showing the questions

To show the questions we will need to create two files – a controller, which will be called when we visit the /question/ URL, and a view, which outputs the HTML code of the page. The controller will handle selecting records from the database and passing them to view. Note that we are not using any models in this app (the M in MVC). For simple applications like this one, they are purely optional and you can write CI apps without them.

/application/controllers/questions.php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); class Questions extends CI_Controller { public function index(){ // Loading only the libraries and helpers that we need. // This is one of the things that make CI fast. $this->load->database(); $this->load->helper(array('date','url')); // Get the id of the last question $res = $this->db-> select_max('id')-> get('qod_questions')-> result_array(); $id = $res[0]['id']; $this->show($id); } public function show($id = -1){ $this->load->database(); $this->load->helper(array('date','url')); // Select the question $q = $this->db-> where(array('id'=>$id))-> get('qod_questions')-> result_array(); if(empty($q)){ // Show an error page show_404(); } $a = $this->db-> where(array('qid'=>$id))-> order_by('id','desc')-> get('qod_answers')-> result_array(); // Get the ids of the previous // and next questions $prev = 0; $next = 0; $res = $this->db-> select_min('id')-> where("id > $id")-> get('qod_questions')-> result_array(); if(!empty($res)){ $next = $res[0]['id']; } $res = $this->db-> select_max('id')-> where("id < $id")-> get('qod_questions')-> result_array(); if(!empty($res)){ $prev = $res[0]['id']; } $this->load->view('question_of_the_day',array( 'question' => $q[0]['question'], 'answers' => $a, 'previous' => $prev, 'next' => $next, 'id' => $id )); } }

The controller is basically a class that extends CI_Controller and resides in the controllers folder. The class methods are called by the framework depending on the URL. For example http://example.com/questions/ will execute the index method, and http://example.com/questions/show/213 – the show method. In the latter case, 213 will be passed as the id parameter.

In the show method we select the question with the passed ID and display it in the view. What the index method does, is to select the id of the newest question, and also call the show method. Because it is set as the default controller, this would mean that when you visit the start page of the application (the base url you set in the previous section), the latest question will be shown.

Read more about the URLs, controllers, views, helpers and the database class of CodeIgniter in the docs.

Now let’s see how the view works. When we load it, we pass an array. Each of the array keys (question, answers, previous, next and id) will be extracted and transformed into a variable. Instead of a class, the view is a simple PHP file.

/application/views/question_of_the_day.php <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title><?php echo $question?> - Question of the day | Tutorialzine Demo</title> <!-- Our CSS stylesheet file --> <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Rancho" /> <link rel="stylesheet" href="<?php echo base_url()?>assets/css/styles.css" /> <!--[if lt IE 9]> <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> </head> <body> <header id="blackboard"> <h1><?php echo $question?></h1> <?php if($previous) echo anchor("questions/show/$previous",'&laquo;','class="arrow left"')?> <?php if($next) echo anchor("questions/show/$next",'&raquo;','class="arrow right"')?> </header> <?php // This method will create a link to the answer form. It is given relative // to your index page, but will be transformed depending on your base in config.php echo anchor("answers/add/$id",'Add your answer','class="addAnswer"'); ?> <ul id="answers"> <?php foreach ($answers as $ans): ?> <li> <?php // Forming the URL of the gravatar image. $gravatar = 'http://www.gravatar.com/avatar/'.md5( strtolower( trim($ans['email']) ) ).'?d=mm'; ?> <span class="avatar" style="background-image:url(<?php echo $gravatar?>)"></span> <span class="meta"> <a href="#" class="author"><?php echo $ans['name']?></a> <?php // We are using the built-in timestamp method. We are using // array slice to limit the shown time divisions. $ts = explode(',', timespan(strtotime($ans['dt']))); $t = implode(',',array_slice($ts,0,2)); ?> <i><?php echo $t?> ago</i> </span> <p class="answer"><?php echo $ans['answer']?></p> </li> <?php endforeach; ?> </ul> </body> </html>

The script loops through the $answers array and outputs a li element for each answer. It assembles a gravatar URL by generating an md5 hash of the email and includes it as the background-image of a rounded span element.

This gives us a functional answer browsing page. But how do we let people answer these questions?

The Blackboard

Posting answers

We will again need to write a controller and a view for adding answers. Here we will use a few more of the neat CodeIgniter features – generating forms and validating them. The generation is handled by the form helper, and the validation – by the form validation class.

You can see the answers controller below.

/application/controllers/answers.php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); class Answers extends CI_Controller { public function add($id = -1){ $this->load->database(); $this->load->helper(array('url','form')); $this->load->library('form_validation'); // Check if there is such a question $q = $this->db-> where(array('id'=>$id))-> get('qod_questions')-> result_array(); if(empty($q)){ // Show an error page show_404(); } // Adding validation rules. $this->form_validation->set_rules('name', 'Name', 'required|min_length[2]|max_length[32]'); $this->form_validation->set_rules('email', 'Email', 'required|valid_email'); $this->form_validation->set_rules('answer', 'Answer', 'required|min_length[5]|max_length[255]'); // If there are errors, show the form if ($this->form_validation->run() == FALSE){ $this->load->view('add_answer',array( 'question' => $q[0]['question'], 'qid' => $q[0]['id'] )); } else{ // Otherwise insert the answer to the database $this->db->insert('qod_answers', array( 'qid' => $q[0]['id'], 'email' => htmlspecialchars($this->input->post('email')), 'name' => htmlspecialchars($this->input->post('name')), // preserving new lines: 'answer'=> nl2br(htmlspecialchars($this->input->post('answer'))) )); redirect('questions/show/'.$q[0]['id']); } } }

With the help of the form validation class, we are able to add rules by which the data should be validated. We will insert the answer in the database only when presented with correct data. I am using the htmlspecialchars() PHP function to escape any HTML code that might have been typed in the form fields. When the answer is inserted, we redirect to the question page. If everything went as it should, the newly added answer should be at the top.

Equally interesting is how the answer form is generated. For this we will take a look at the view file.

/application/views/add_answer.php <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title><?php echo $question?> - Add Answer | Tutorialzine Demo</title> <!-- Our CSS stylesheet file --> <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Rancho" /> <link rel="stylesheet" href="<?php echo base_url()?>assets/css/styles.css" /> <!--[if lt IE 9]> <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> </head> <body> <header id="blackboard"> <h1><?php echo $question?></h1> </header> <?php // This will print a link to the question page echo anchor("questions/show/$qid",'Back to the question','class="addAnswer"'); // Creating the form using the form helper echo form_open(''); echo form_label('Name','name'); echo form_input(array( 'name' => 'name', 'id' => 'name', 'value' => set_value('name'), 'maxlength' => '64' )); echo form_label('Email (gravatar enabled)','email'); echo form_input(array( 'name' => 'email', 'id' => 'email', 'value' => set_value('email'), 'maxlength' => '128' )); echo form_label('Answer','answer'); echo form_textarea(array( 'name' => 'answer', 'id' => 'answer', 'value' => set_value('answer'), )); echo form_submit('subm', 'Add Answer!'); // Showing the validation errors $validation = validation_errors(); if($validation): ?> <div class="errorMessages"> <?php echo $validation?> </div> <?php endif;?> <?php echo form_close()?> </body> </html>

As we included the form helper in the controller, we have access to all of its functions here, in the view. These functions make it easier to create forms and form fields. Of course, you can directly write the HTML of the forms, but you will have to update the code if you change the URL of your site.

At the bottom of the file we are accessing the validate_errors() function which will return a string with error messages, generated by the validation class. If there are any errors, we show them in a .errorMessages div.

That is it! All that is left is to add a pretty stylesheet and some images.

The styling

To finish this application, we need to add a stylesheet and images. Where we put them is more a matter of personal preference. I have chosen to go with an assets folder in the base directory of the application (you can see it in the zip file).

In the views I have specified the URL of the stylesheet like this: <?php echo base_url()?>assets/css/styles.css which gives us the correct location. base_url() is a function defined in the URL helper of the framework, which we’ve included in the controller.

As the tutorial is already quite lengthy, I won’t be discussing the styling here. You can see it for yourself by opening /assets/css/styles.css in your code editor.

We’re done!

I am hoping that you learned a lot in this tutorial. If you decide to go with CodeIgniter for your next website, it will be a useful experience for you. Although there is a learning curve, once you understand the basics, you will appreciate just how much time you can save. And with Sparks, you will become even more productive by adding easy to use open source modules to your projects.

iPhorm Plugin Winners

Thu, 01/05/2012 - 15:33

Just before the holidays, you took part in the iPhorm WordPress Plugin Giveaway, where two of you had a chance of winning a copy of the plugin. Now it is time to draw the winners!

And the two of you who got a late Christmas present are WPH and Mike Dedmon. They have been contacted and will receive their prizes shortly.

iPhorm winners

For those of you who did not win, I wish the best of luck next time!

Making a jQuery Countdown Timer

Fri, 12/30/2011 - 07:02

When building a coming soon or event page, you find yourself in search for a good way to display the remaining time. A countdown gives the feel of urgency, and combined with an email field will yield more signups for your newsletter.

Today we are going to build a neat jQuery plugin for displaying a countdown timer. It will show the remaining days, hours, minutes and seconds to your event, as well as an animated updates on every second. Note: the plugin is also available on Github.

Let’s start with the markup!

The HTML

We will give the plugin the creative name of “countdown”. Called on an empty element, it will fill it with the HTML that is needed for the countdown timer. You don’t need to do anything but choose the element in which you want to show it.

Generated markup <div id="countdown" class="countdownHolder"> <span class="countDays"> <span class="position"> <span class="digit static"></span> </span> <span class="position"> <span class="digit static"></span> </span> </span> <span class="countDiv countDiv0"></span> <span class="countHours"> <span class="position"> <span class="digit static"></span> </span> <span class="position"> <span class="digit static"></span> </span> </span> <span class="countDiv countDiv1"></span> <span class="countMinutes"> <span class="position"> <span class="digit static"></span> </span> <span class="position"> <span class="digit static"></span> </span> </span> <span class="countDiv countDiv2"></span> <span class="countSeconds"> <span class="position"> <span class="digit static"></span> </span> <span class="position"> <span class="digit static"></span> </span> </span> <span class="countDiv countDiv3"></span> </div>

In the above example, the plugin has been originally called on a div with an id of countdown. The plugin has then added a countdownHolder class to it (so a few styles are applied to the element via CSS).

Inside is the markup for the digits. There are two digit spans for every time unit (days, hours, minutes and seconds), which means that you can count down towards a date that is no more than 99 days in the future (for such time frames you should probably not use the timer anyway, it would be discouraging).

The static class of the digits gives them their gradient background and box-shadow. When animated, this class is removed so that these CSS3 touches don’t slow down the animation. The digits are brought together in groups so you can easily style them. Adding a font-size declaration to .countDays, will affect the size of both day digits.

A jQuery Countdown Timer

The .countDiv spans are the dividers between the units. The colon is formed with :before/:after elements.

But how is this markup generated exactly?

The jQuery

First let’s write two helper functions used by the plugin:

  • init generates the markup you saw above;
  • switchDigit takes a .position span and animates the digits inside it;

Extracting this functionality as separate functions allows us to keep the plugin code clean.

assets/countdown/jquery.countdown.js function init(elem, options){ elem.addClass('countdownHolder'); // Creating the markup inside the container $.each(['Days','Hours','Minutes','Seconds'],function(i){ $('<span class="count'+this+'">').html( '<span class="position">\ <span class="digit static">0</span>\ </span>\ <span class="position">\ <span class="digit static">0</span>\ </span>' ).appendTo(elem); if(this!="Seconds"){ elem.append('<span class="countDiv countDiv'+i+'"></span>'); } }); } // Creates an animated transition between the two numbers function switchDigit(position,number){ var digit = position.find('.digit') if(digit.is(':animated')){ return false; } if(position.data('digit') == number){ // We are already showing this number return false; } position.data('digit', number); var replacement = $('<div>',{ 'class':'digit', css:{ top:'-2.1em', opacity:0 }, html:number }); // The .static class is added when the animation // completes. This makes it run smoother. digit .before(replacement) .removeClass('static') .animate({top:'2.5em',opacity:0},'fast',function(){ digit.remove(); }) replacement .delay(100) .animate({top:0,opacity:1},'fast',function(){ replacement.addClass('static'); }); }

Great! Now let’s move on with the plugin body. Our plugin must take an object with parameters for better configurability – a timestamp of the period we are counting towards, and a callback function, executed on every tick and passed the remaining time. For brevity, I’ve omitted the functions above from the code.

assets/countdown/jquery.countdown.js (function($){ // Number of seconds in every time division var days = 24*60*60, hours = 60*60, minutes = 60; // Creating the plugin $.fn.countdown = function(prop){ var options = $.extend({ callback : function(){}, timestamp : 0 },prop); var left, d, h, m, s, positions; // Initialize the plugin init(this, options); positions = this.find('.position'); (function tick(){ // Time left left = Math.floor((options.timestamp - (new Date())) / 1000); if(left < 0){ left = 0; } // Number of days left d = Math.floor(left / days); updateDuo(0, 1, d); left -= d*days; // Number of hours left h = Math.floor(left / hours); updateDuo(2, 3, h); left -= h*hours; // Number of minutes left m = Math.floor(left / minutes); updateDuo(4, 5, m); left -= m*minutes; // Number of seconds left s = left; updateDuo(6, 7, s); // Calling an optional user supplied callback options.callback(d, h, m, s); // Scheduling another call of this function in 1s setTimeout(tick, 1000); })(); // This function updates two digit positions at once function updateDuo(minor,major,value){ switchDigit(positions.eq(minor),Math.floor(value/10)%10); switchDigit(positions.eq(major),value%10); } return this; }; /* The two helper functions go here */ })(jQuery);

The tick function calls itself every second. Inside it, we calculate the time difference between the given timestamp and the current date. The updateDuo function then updates the digits comprising the time unit.

The plugin is ready! Here is how to use it (as seen in the demo):

assets/js/script.js $(function(){ var note = $('#note'), ts = new Date(2012, 0, 1), newYear = true; if((new Date()) > ts){ // The new year is here! Count towards something else. // Notice the *1000 at the end - time must be in milliseconds ts = (new Date()).getTime() + 10*24*60*60*1000; newYear = false; } $('#countdown').countdown({ timestamp : ts, callback : function(days, hours, minutes, seconds){ var message = ""; message += days + " day" + ( days==1 ? '':'s' ) + ", "; message += hours + " hour" + ( hours==1 ? '':'s' ) + ", "; message += minutes + " minute" + ( minutes==1 ? '':'s' ) + " and "; message += seconds + " second" + ( seconds==1 ? '':'s' ) + " <br />"; if(newYear){ message += "left until the new year!"; } else { message += "left to 10 days from now!"; } note.html(message); } }); });

Of course, for this to work, you will have to include the css and js file from the countdown folder in your page.

Done!

You can use this script as the perfect addition to every launch page. The best thing about it is that it doesn’t use a single image, everything is done with CSS alone. Increasing or decreasing the font size will result in everything scaling nicely, and you only need a display:none declaration to hide the units you don’t need.

Win a copy of the iPhorm WordPress plugin!

Wed, 12/21/2011 - 15:00

WordPress is undoubtedly the most popular CMS in the world. It is used for so much more than the authors initially envisioned. With all of its wonderful features and incredible plugins, you can build anything – from a personal blog to a fully-fledged online shop.

With the holidays right around the corner, we decided to give away two copies of the iPhorm plugin which will help you create forms for your website with an easy to use drag-and-drop builder directly from WordPress.

The iPhorm Plugin

iPhorm is a WordPress plugin that makes building forms easy with elements that include email address, date and time, file uploads and many more. The form submissions are received as emails or directly in your dashboard. Designers have full control on how the forms looks, and for everybody else, two themes are provided. For a live demo, see here.

How to Win

For a chance to win a copy of the plugin, do the following:

  • Leave a comment below this article;
  • Tweet it.

The winners will be announced on January 5th 2012.

HTML5 Charity Center Template

Mon, 12/19/2011 - 16:34

With the help of our friends over at Grafpedia, I am happy to share with you a beautiful charity web site template to kick-start your development efforts. It is fully coded in HTML5 and uses the tiny Craftyslider jQuery plugin.

HTML5 Charity Template

Grafpedia have also published a tutorial on how the design was created. Refer to the included readme for the license.

Happy coding!

How to Block Adblock

Fri, 12/16/2011 - 13:43

If you are a website owner, there is a pretty good chance that you rely on some form of advertising to pay for your hosting bills. And if you are lucky enough to have more than a few people visiting your site, you might even be able to pay yourself a supplement to your salary as a compensation for your hard work.

On the other side there are the people that browse the web. They are tired of being bombarded with intrusive advertising, flashy banners and announcements that ruin their browsing experience. They don’t need to be congratulated on being the millionth visitor of your website, they don’t want to shoot five iphones, their only wish is to read what you have to say.

As it is much easier for users to hide ads than for the entire industry to develop advertising ethics, a simple solution quickly emerged.

Then Came Adblockers

The idea of an adblocker is simple – it is a browser extension that blocks or removes advertising on the page. A “solution” is hardly the proper term, however, as it only serves one side – the users. There frankly couldn’t be a better deal for them. These extensions strip everything except the main content of the page, bringing a whole new dimension to the word free – it not only means that they don’t pay; it now means that you don’t get paid too!

Adblocker detected!

This didn’t use to be a big of a problem for website owners – people using ad blockers weren’t that many, and it did make users enjoy browsing your site more. But as the idea for browser extensions exploded in recent years, so did the proliferation of ad blockers. A quick look at the addon directories reveals that ad blockers are the most popular category.

Small sites are most at risk, as they can’t attract the same interest from advertisers and experiment with different formats. With more than 20% of pageviews eaten away by adblockers (these are the number for Tutorialzine), it becomes evident that something has to change.

Miraculously, in the past few weeks there were news that the most popular ad blocker – AdBlock Plus will start allowing acceptable advertising by default. Judging by the uproar this decision brought, a large percentage of people will still opt in for complete blocking of ads or move to a different extension. This means that we as publishers will still have to maneuver around this problem for some time to come. One solution would be to detect the presence of an ad blocker.

How To Detect AdBlock

It is simple – we will use ad blockers’ overzealous interference against it. To block ads such an extension must look for files it believes contain code that shows adverts and prevent them from loading. So the idea is to have a JS file named advertisement.js, which will trigger adblock’s filters, and after this, check whether the file has been loaded.

Here is the file itself:

assets/blockBlock/advertisement.js jQuery.adblock = false;

That’s all, one line. It creates a new property on the global jQuery object, which we will later look for. If it is undefined, it would mean that this file has been blocked from loading.

assets/blockBlock/blockBlock.jquery.js (function($){ if ($.adblock === undefined){ $.adblock = true; } $.fn.showOnAdBlock = function(){ if($.adblock){ this.show(); } return this; }; })(jQuery);

To find out if an ad blocker is present, simply do a conditional check for the $.adblock variable. In the same file, we also define a helper method that will conditionally show an element depending if such an extension is active.

Update: This plugin is also available on Github.

When including the plugin in your site, remember to include the files above after the jQuery library. For the demo page I am also using the confirm dialog replacement from last year to show a pretty dialog box informing the users they should disable adblock to view the page. Here is the code for that:

assets/js/script.js $(function(){ if($.adblock){ $.confirm({ 'title' : 'Adblocker active!', 'message' : 'You are running an ..', 'buttons' : { 'I will!' : { 'class' : 'blue', 'action': function(){ // Do nothing return; } }, 'Never!' : { 'class' : 'gray', 'action': function(){ // Redirect to some page window.location = 'http://tutorialzine.com/'; } } } }); } });

Bang! Now you can tell who is using an ad blocker. This simple method works with most of the popular ad cleaning plugins used at the moment.

What to use it for?

Okay, so you have a snippet of code that would tell you if a person is using an ad blocker or not. What to do now? Some ideas follow. I would not personally use any of the bad or evil ones, but I am obliged to share.

Good ideas
  • Track how many people are blocking ads on your website. If the percentage is high, you can try different (non-banner) types of advertisement;
  • Replace the areas of your website where ads usually go with some useful content;
  • Inform visitors how adblock harms small websites with a heartbreaking personal appeal ala Jimmy Wales.
Bad ideas
  • Show a big message that adblocked users are not welcome (like in the demo);
  • Beg for donations;
  • Replace with ads for affiliate programs that are not blocked by the extension.
Outright evil ideas
  • Set up a paywall for adblocked users;
  • Require a sign-in with facebook or a registration;
  • Redirect to a daily deal website with your affiliate link.
A bright future?

Hopefully the initiative behind AdBlock Plus’ decision to show non-intrusive ads resonates in the community and we will enjoy advertising that is accepted and useful for both publishers and visitors.

What are your thoughts about AdBlock?

IM Creator Lifetime Subscription Winners

Thu, 12/15/2011 - 07:04

Ten days ago you took part in the IM Creator giveaway, where three of you had a chance to win a lifetime subscription for their new web site building service. Now it is time to draw the winners!

And they are kit, Richard Bland and Chen YH. They have been contacted and will receive their prizes soon.

The Winners

I am wishing the best of luck in the coming competitions for those of you who did not win!

What You Need To Know About The HTML5 Slider Element

Fri, 12/09/2011 - 12:26

HTML5 brought a lot of new tags and new rules on how the old ones should be used. One of them is the range input element, or the slider. This control has been available in operating systems for decades, but is only now that it has found its way into the browser.

The reason for this delay is probably that it is easy to emulate the functionality with JavaScript alone. The jQuery UI library includes a pretty capable version that is also easy to style. But having it built into the browser and ready to go is much more convenient, at least for the browsers that support it.

20 years in the making, but we finally have it!

Browser support

All modern browsers support this element with the notable exception of Firefox, but it can be easily recreated with html5slider.js. Of course IE also does not support the range input (no surprise here), for which there are no easy fixes. This means that to use it cross-browser you will still need to include a separate enabling library like jQuery UI (more on that later on). The good thing is that even if the browser does not support the range element, it will fall back to a textbox.

Browser support for the range input

How it works

I referred to the slider as “range input” for a reason. It is a type of input element, rather than a separate tag – <input type="range" /> is all you need to display it in your page. It supports the regular value attribute shared by all input elements, along with min and max, which limit the range, and step which sets how much the value changes on every movement (default is 1).

Supported attributes by <input type=”range” /> Attribute Value Default Description value number not set The default position of the slider. min number 0 The bottom limit of the range. This is the value of the input when the slider is on the leftmost position. max number 100 The top limit of the range. This is the value of the input when the slider is on the rightmost position. step number 1 The amount with which the value changes on each movement of the slider.

You can change these attributes with JavaScript/jQuery as you would with any regular input element. You can also use the onchange event to listen for changes. This is what the code looks like:

Extracted from index.html <input id="defaultSlider" type="range" min="0" max="500" /> <p class="note">Current value: <span id="currentValue">0</span></p>

And this is the jQuery code that listens for the change event:

assets/js/slider-default.js $(function(){ var currentValue = $('#currentValue'); $('#defaultSlider').change(function(){ currentValue.html(this.value); }); // Trigger the event on load, so // the value field is populated: $('#defaultSlider').change(); });

Of course this code will only work if your browser supports the slider element. Otherwise you will be presented with a textbox.

Lets level the field

As more than two thirds of the internet population won’t be able to see our pretty slider, we need to take a different path. Lets build a quick and dirty version of the slider using jQuery UI, a library of interface components that sits on top of jQuery.

Extracted from slider-jqueryui.html <div id="slider"></div> <p class="note">Current value: <span id="currentValue">0</span></p>

You can see the code for the jQuery UI Slider control below (you need to include jQuery UI alongside jQuery in your page).

assets/js/slider-jqueryui.js $(function(){ var currentValue = $('#currentValue'); $("#slider").slider({ max: 500, min: 0, slide: function(event, ui) { currentValue.html(ui.value); } }); });

The code is pretty straightforward. It simply uses the slider method and the library does the rest.

The fun part

Here comes a realization – as we are already presenting our own custom version of the slider, we can as well present an entirely different control. Lets use the KnobKnob plugin from last week.

We will have the range input control on the page, but it will be hidden. KnobKnob will then create a rotating control that will have the same limits as the original slider. On every change we will update the value of the hidden slider:

slider-knob.html <div id="container"> <div id="control"></div> </div> <!-- The range input is hidden and updated on each rotation of the knob --> <input type="range" id="slider" min="0" max="500" value="25" /> <p class="note">Current value: <span id="currentValue">0</span></p>

And for the jQuery part:

assets/js/slider-knob.js $(function(){ var slider = $('#slider'), min = slider.attr('min'), max = slider.attr('max'), currentValue = $('#currentValue'); // Hiding the slider: slider.hide(); $('#control').knobKnob({ snap : 10, value: 250, turn : function(ratio){ // Changing the value of the hidden slider slider.val(Math.round(ratio*(max-min) + min)); // Updating the current value text currentValue.html(slider.val()); } }); });

The code above takes the min and max attributes of the range input and uses it to calculate the corresponding value of the slider.

Conclusion

The slider control is useful for giving users the ability to conveniently modify a value without having to explicitly type it in a text box. Although there is much to be desired in terms of browser support, you can use progressive enhancement to display an alternative control using jQuery.

Win a lifetime subscription to IM Creator!

Mon, 12/05/2011 - 18:01

Every website is different. From complex online stores that test your development skills, to presentation oriented pages that depend heavily on design, and everything in between. But there is a right tool for any job. You can use an open source CMS to lift the development burden off complex sites, but it would be an overkill for simpler ones.

This is where a tool like IM Creator comes into play.

IM Creator Lifetime License

IM Creator is a new simple and free HTML-based drag and drop website builder that allows you to create your website in a trouble-free, accessible and pleasant experience. With IM Creator, you can build a beautiful site, fast. Start from an existing design or make a new one - it’s up to you.

The Prize

The folks behind IM Creator have generously offered three lifetime licenses for their premium plan to Tutorialzine readers (valued at $95/year each). The offer applies to new clients of their service.

How to Win

For a chance to win a lifetime subscription, do the following:

  • Leave a comment below this article;
  • Tweet it.

The winners will be announced on December 15th 2011.

4Templates Premium Theme Winners

Thu, 12/01/2011 - 05:52

A week ago, you took part in the 4Templates giveaway. The curtains are closed, so are the comments, and now is time to draw the winners using the giveaway randomizer app from a while back.

The winners are: Momcilo, SubZero and Imran. They get to choose a premium theme or template from 4Templates for free.

4Templates Winners

For those that did not win, I am wishing best of luck in the giveaways that come!

Shiny Knob Control with jQuery and CSS3

Wed, 11/30/2011 - 11:00

In this tutorial we will be writing a jQuery plugin for creating a shiny knob control. Aptly named knobKnob, this plugin will use CSS3 transformations and jQuery’s new event handling methods to give visitors of your website a new way of interactively choosing a value from a range.

KnobKnob is also on Github.

Update: Thanks to ranyefet the plugin now works on mobile devices [changes].

The HTML

The HTML markup for the page is rather straightforward. We are only going to need a placeholder element for the control – the rest is going to be dynamically generated by the plugin. Just in case, here is the complete markup of the page:

index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Shiny Switches with CSS3 &amp; jQuery | Tutorialzine Demo</title> <!-- CSS stylesheets --> <link rel="stylesheet" href="assets/css/styles.css" /> <link rel="stylesheet" href="assets/knobKnob/knobKnob.css" /> <!--[if lt IE 9]> <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> </head> <body> <section id="main"> <div id="bars"> <div id="control"> <!-- The knob markup will go here --> </div> <!-- The colorful dividers will go here --> </div> </section> <!-- JavaScript includes --> <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script> <script src="assets/knobKnob/transform.js"></script> <script src="assets/knobKnob/knobKnob.jquery.js"></script> <script src="assets/js/script.js"></script> </body> </html>

First we include the latest version of jQuery, transform.js which levels cross-browser support of the CSS3 transform properties we will be using, the knobKnob plugin file and script.js, which pulls everything together.

The #control div is where the plugin markup will be generated. Below we will insert divs that will become the colorful bars around it. They are not part of the KnobKnob plugin, we will be showing them depending on the chosen value in the control. KnobKnob also comes with a stylesheet that determines the looks of the knob. You can see it included in the head section.

Now lets write this plugin!

Shiny Knob Control

The jQuery Code

You can find the plugin source files in the knobKnob folder. To use it in your project simply unzip it in your website’s assets folder and include the files you find inside. Here is the actual plugin file:

assets/knobKnob/knobKnob.jquery.js /** * @name jQuery KnobKnob plugin * @author Martin Angelov * @version 1.0 * @url http://tutorialzine.com/2011/11/pretty-switches-css3-jquery/ * @license MIT License */ (function($){ $.fn.knobKnob = function(props){ var options = $.extend({ snap: 0, value: 0, turn: function(){} }, props || {}); var tpl = '<div class="knob">\ <div class="top"></div>\ <div class="base"></div>\ </div>'; return this.each(function(){ var el = $(this); el.append(tpl); var knob = $('.knob',el) knobTop = knob.find('.top'), startDeg = -1, currentDeg = 0, rotation = 0, lastDeg = 0, doc = $(document); if(options.value > 0 && options.value <= 359){ rotation = currentDeg = options.value; knobTop.css('transform','rotate('+(currentDeg)+'deg)'); options.turn(currentDeg/359); } knob.on('mousedown', function(e){ e.preventDefault(); var offset = knob.offset(); var center = { y : offset.top + knob.height()/2, x: offset.left + knob.width()/2 }; var a, b, deg, tmp, rad2deg = 180/Math.PI; knob.on('mousemove.rem',function(e){ a = center.y - e.pageY; b = center.x - e.pageX; deg = Math.atan2(a,b)*rad2deg; // we have to make sure that negative // angles are turned into positive: if(deg<0){ deg = 360 + deg; } // Save the starting position of the drag if(startDeg == -1){ startDeg = deg; } // Calculating the current rotation tmp = Math.floor((deg-startDeg) + rotation); // Making sure the current rotation // stays between 0 and 359 if(tmp < 0){ tmp = 360 + tmp; } else if(tmp > 359){ tmp = tmp % 360; } // Snapping in the off position: if(options.snap && tmp < options.snap){ tmp = 0; } // This would suggest we are at an end position; // we need to block further rotation. if(Math.abs(tmp - lastDeg) > 180){ return false; } currentDeg = tmp; lastDeg = tmp; knobTop.css('transform','rotate('+(currentDeg)+'deg)'); options.turn(currentDeg/359); }); doc.on('mouseup.rem',function(){ knob.off('.rem'); doc.off('.rem'); // Saving the current rotation rotation = currentDeg; // Marking the starting degree as invalid startDeg = -1; }); }); }); }; })(jQuery);

The plugin takes a number of options as a parameter object – snap, value and turn:

  • snap is a number of degrees that are snapped to zero. You can test this by slowly turning the knob down;
  • value is the initial rotation of the knob (also in degrees);
  • turn is a callback function that is called every time the knob is turned. Its only argument is a ratio (from 0 to 1) of the rotation. We will use this function in a moment to determine how many of the colorful dividers to show.

In the code above you can see that we are using the Math.atan2 function (as we did in the PointPoint plugin) to calculate the angle (in radians) between the mouse pointer and the center of the knob. By keeping track of the angle in the start and end position of the drag, we can determine how much to rotate the knob.

Later we are also using jQuery 1.7′s new methods for manipulating event listeners – on and off.

Now lets see how we can use this plugin.

assets/js/script.js $(function(){ var colors = [ '26e000','2fe300','37e700','45ea00','51ef00', '61f800','6bfb00','77ff02','80ff05','8cff09', '93ff0b','9eff09','a9ff07','c2ff03','d7ff07', 'f2ff0a','fff30a','ffdc09','ffce0a','ffc30a', 'ffb509','ffa808','ff9908','ff8607','ff7005', 'ff5f04','ff4f03','f83a00','ee2b00','e52000' ]; var rad2deg = 180/Math.PI; var deg = 0; var bars = $('#bars'); for(var i=0;i<colors.length;i++){ deg = i*12; // Create the colorbars $('<div class="colorBar">').css({ backgroundColor: '#'+colors[i], transform:'rotate('+deg+'deg)', top: -Math.sin(deg/rad2deg)*80+100, left: Math.cos((180 - deg)/rad2deg)*80+100, }).appendTo(bars); } var colorBars = bars.find('.colorBar'); var numBars = 0, lastNum = -1; $('#control').knobKnob({ snap : 10, value: 154, turn : function(ratio){ numBars = Math.round(colorBars.length*ratio); // Update the dom only when the number of active bars // changes, instead of on every move if(numBars == lastNum){ return false; } lastNum = numBars; colorBars.removeClass('active').slice(0, numBars).addClass('active'); } }); });

The colorful bars that are displayed around the knob are not part of the plugin. And they shouldn’t be – the plugin only handles the control itself which makes it easier to reuse it.

The code above creates a set of 30 divs with colors gradually going from green to red. These are then rotated by 12 degree increments. Thanks to the turn callback function passed to the plugin, this code can determine how many of the colorful bars to show. You can see the rest of the bar styling in assets/css/styles.css.

We are done!

With this our plugin is complete! You can use it as part of control panels and other administrative pages, everywhere you want to give users the ability to choose from a pool of values. Next time we will use this plugin to enhance the new range form element.

Win a premium theme from 4Templates!

Tue, 11/22/2011 - 06:20

We are all programmers and writing code is what we do best. But there is a common pain we all share – making our sites look as good as they function. Lets face it – design is hard. Luckily for us however, there is a quick solution to this – a beautifully designed theme that is ready for use.

With the help of our friends at 4Templates, three of you will have a chance to win a premium theme or template of their choice for free.

Win a premium theme from 4Templates

4Templates.com has hundreds of awesome website templates and WordPress themes with amazing graphics, standards compliant XHTML and CSS code, PSD files, and great tech support whenever you need it. And with everything under 30 bucks, you’ll always find something that works great no matter the project or budget.

How to win?

To participate, do the following:

  • Leave a comment;
  • Tweet about this post.

The winners will be announced on December 1st 2011 in a followup post.

Lets Write Some Tests with Testify.php

Sat, 11/19/2011 - 13:23

If you have only recently started out with web development, testing your code is probably not very high on your list. You write something that does what you need to, refresh your browser, and quickly find out if it works or not. Testing is more of a chore than anything else. The less you do of it the better. And who knows, someday, when you become more experienced you won’t even need to test – we all know rockstar programmers never make mistakes.

So very wrong!

But there is something right in the paragraph above. Testing does feel like a chore. A hopelessly boring and tedious one at that. There isn’t much you can do about it, unless you start seeing it in terms of game mechanics. Tests should be your scoreboard and each passed test should be an achievement you are proud of. This is where a small framework I wrote the other day comes into play.

Introducing Testify.php

Testify is a micro testing framework for PHP, released under the GPL license. It aims to be elegant and easy to use. Testify takes advantage of PHP 5.3′s anonymous function syntax to make defining tests almost JavaScript-like. Tests are logically grouped in test cases. The collection of test cases is considered a test suite. Now lets see how we can use this micro framework to make our development lives easier.

Testify.php - a micro unit testing framework

Shall we write some tests?

As a short example, we will be writing a PHP class for converting timestamps like the ones you get from a date/time database column (“15-10-2011 22:32″), into relative time strings (“1 month ago”). This is the sort of class that requires a lot of testing to get right, which would be a great use case for Testify.

The RelativeTime class

There are a lot of ways you can calculate relative time offsets. You could simply dump a pile of if/else statements and it still might work, but the code would be really hard to maintain and bug prone. However, we will go with something a bit more elegant. We will use the fact that each period we use to measure time with, is fixed in relation to a lesser one. In other words one day has exactly 24 hours, each hour has 60 minutes and each minute has 60 seconds.

Here is the skeleton of our class that uses this observation:

RelativeTime.class.php class RelativeTime{ // The period names private $names = array('second','minute','hour','day','week','month','year'); // How many times is the current period bigger than the previous one private $divisions = array(1,60,60,24,7,4.34,12); private $time = NULL; public function __construct($timestr = NULL){ // You can pass a timestamp when constructing an object } public function getOffsetFrom($timestr = NULL){ // This method calculates the relative string. // This is where the magic happens. } public function __toString(){ // This is one of the convenient PHP magic methods } private function timestampFromString($time){ // This private method will parse the time string // into a valid time offset (in seconds) } }

Now lets write our tests.

Using Testify

There is a software development process called Test Driven Development (TDD), according to which you should write your tests first for best results. Lets explore how this would work with the framework.

The first step is to download Testify. After this, extract the testify folder and include it in a new PHP file, along with the RelativeTime class:

index.php include 'RelativeTime.class.php'; include 'testify/testify.class.php';

Now the stage is set for a new test suite. The first step is to create an instance of the Testify class.

$tf = new Testify("Testing RelativeTime with Testify");

The string you pass here is used as the title of the suite (and displayed on top of the page). We can now move on to defining the test cases (logical collections of tests). The first test is more general and oriented to the functionality of the class as a whole.

index.php $tf->test("General tests of the class", function($tf){ $relative = new RelativeTime(); // We haven't specified a timestamp yet. $tf->assert($relative == "Timestamp not specified!"); try{ // Should throw an exception $relative->getOffsetFrom(); // If we get to here, it means the test has failed: $tf->fail(); } catch (Exception $e){ $tf->assert($e->getMessage() == "Timestamp not specified!"); } try{ // Should work $relative->getOffsetFrom("22-10-2011"); $tf->pass(); } catch (Exception $e){ $tf->fail(); } });

The RelativeTime class throws an exception if we are accessing the relative time string but we haven’t yet passed a timestamp (either to the constructor or to the getOffsetFrom() method). But as the __toString magic method cannot throw exceptions, we will only return the exception text.

You can see some of the testing methods that testify supports – assert(), pass() and fail(). You can read more about them in the documentation.

We will now need to add a second test case, which tests the validity of the generated relative time strings.

index.php $tf->test("Testing the relative time functionality", function($tf){ // Testing the class with a string timestamp $relative = new RelativeTime(timestamp(time()-130)); // Testing the getOffsetFrom method $tf->assert($relative->getOffsetFrom() == "2 minutes ago"); // Testing using the __toString conversion $tf->assert($relative == "2 minutes ago"); // Quick and dirty tests $tf->assert( new RelativeTime( time()) == "just now"); $tf->assert( new RelativeTime( time()-11) == "11 seconds ago"); $tf->assert( new RelativeTime( time()-59) == "59 seconds ago"); $tf->assert( new RelativeTime( time()-60) == "1 minute ago"); $tf->assert( new RelativeTime( time()-89) == "1 minute ago"); $tf->assert( new RelativeTime( time()-90) == "2 minutes ago"); $tf->assert( new RelativeTime( time()-30*60) == "30 minutes ago"); $tf->assert( new RelativeTime( time()-59*60) == "59 minutes ago"); $tf->assert( new RelativeTime( time()-60*60) == "1 hour ago"); $tf->assert( new RelativeTime( time()-90*60) == "2 hours ago"); $tf->assert( new RelativeTime( time()-86400) == "1 day ago"); $tf->assert( new RelativeTime( time()-3*86400) == "3 days ago"); $tf->assert( new RelativeTime( time()-9*86400) == "1 week ago"); $tf->assert( new RelativeTime( time()-29*86400) == "4 weeks ago"); $tf->assert( new RelativeTime( time()-31*86400) == "1 month ago"); $tf->assert( new RelativeTime( time()-100*86400) == "3 months ago"); $tf->assert( new RelativeTime( time()-350*86400) == "12 months ago"); $tf->assert( new RelativeTime( time()-365*86400) == "1 year ago"); $tf->assert( new RelativeTime( time()-20*365*86400) == "20 years ago"); }); // Helper function for constructing string timestamps function timestamp($unixTime){ return date('r',$unixTime); }

Great! What is left is to call the run() method and we get a pretty (albeit failing) test report.

$tf->run();

Testify Unit Testing - Everything Failing

Now we can move on with writing the actual methods of the class. You can see the complete class implementation below:

class RelativeTime{ // The period names private $names = array('second','minute','hour','day','week','month','year'); // How many of the previous period are contained in the next private $divisions = array(1,60,60,24,7,4.34,12); private $time = NULL; public function __construct($timestr = NULL){ // You can pass a timestamp when constructing an object $this->timestampFromString($timestr); } public function getOffsetFrom($timestr = NULL){ // This method calculates the relative string $this->timestampFromString($timestr); if(is_null($this->time)){ throw new Exception("Timestamp not specified!"); } $time = $this->time; $name = ""; if($time < 10){ return "just now"; } for($i=0; $i<count($this->divisions); $i++){ if($time < $this->divisions[$i]) break; $time = $time/$this->divisions[$i]; $name = $this->names[$i]; } $time = round($time); if($time != 1){ $name.= 's'; } return "$time $name ago"; } public function __toString(){ // __toString cannot throw exceptions try{ return $this->getOffsetFrom(); } catch(Exception $e){ return $e->getMessage(); } } private function timestampFromString($time){ if(is_numeric($time)){ // a unix timestamp (number of seconds since 1st Jan 1970) $this->time = time() - $time; } else if(is_string($time)){ // a string timestamp $this->time = time() - strtotime($time); } } }

This gives us a satisfying all-green test page. Achievement unlocked!

Done!

Testing is necessary. It can give you peace of mind when changing existing code or help you in debugging new one. Hopefully this small framework will make testing more fun!

As always, be sure to share your thoughts and suggestions in the comment section.

Chained AJAX Selects

Thu, 11/03/2011 - 11:40

In today’s tutorial, we will build a set of chained select elements. Selecting an option in one of them will trigger an update on the page, showing you more choices to refine your selection. We will describe the options server side with PHP, so it is easy for you to hook today’s example to a database.

The idea for this tutorial was suggested by Casper Hansen from Denmark.

The HTML

As you can see from the screenshot below, the select box is accompanied by a title that explains what the selection is about. The title and the selectbox are enclosed in a LI item.

Chained AJAX Selects with jQuery and PHP

When adding more questions, additional LIs are created by jQuery. All of these sit inside an unordered list called #questions. The title and options for these items are served as JSON, as you will see in the PHP part of the tut. Here is the markup that is generated for the li items:

index.html – generated code <ul id="questions"> <!-- Generated by jQuery --> <li> <p>What would you like to purchase?</p> <select data-placeholder="Choose a product category"> <option data-connection="phoneSelect" value="Phones">Phones</option> <option data-connection="notebookSelect" value="Notebooks">Notebooks</option> <option data-connection="tabletSelect" value="Tablets">Tablets</option> </select> </li> <!-- The next sections are inserted here depending on the choices above --> </ul>

You might notice in the demo page that we aren’t using the default browser select controls. This is because we are making use of the Chosen jQuery plugin to upgrade our selects into the fancy widgets you see. We simply need to call the chosen() method on the selects, and the plugin will handle the rest.

The jQuery code

Here is what our jQuery code does in short – it fetches the select boxes information as JSON from the server, generates their HTML, and sets up event listeners for selection changes. If a change in the selection does occur, the process is repeated for the new select item.

In the code, this is achieved using two JavaScript functions:

  • refreshSelects triggers the Chosen plugin and binds event listeners every time an item is added to the page;
  • fetchSelect requests a JSON feed from the server and generates the markup from the response.

You can see them below.

assets/js/script.js $(function(){ var questions = $('#questions'); function refreshSelects(){ var selects = questions.find('select'); // Improve the selects with the Chose plugin selects.chosen(); // Listen for changes selects.unbind('change').bind('change',function(){ // The selected option var selected = $(this).find('option').eq(this.selectedIndex); // Look up the data-connection attribute var connection = selected.data('connection'); // Removing the li containers that follow (if any) selected.closest('#questions li').nextAll().remove(); if(connection){ fetchSelect(connection); } }); } var working = false; function fetchSelect(val){ if(working){ return false; } working = true; $.getJSON('ajax.php',{key:val},function(r){ var connection, options = ''; $.each(r.items,function(k,v){ connection = ''; if(v){ connection = 'data-connection="'+v+'"'; } options+= '<option value="'+k+'" '+connection+'>'+k+'</option>'; }); if(r.defaultText){ // The chose plugin requires that we add an empty option // element if we want to display a "Please choose" text options = '<option></option>'+options; } // Building the markup for the select section $('<li>\ <p>'+r.title+'</p>\ <select data-placeholder="'+r.defaultText+'">\ '+ options +'\ </select>\ <span class="divider"></span>\ </li>').appendTo(questions); refreshSelects(); working = false; }); } $('#preloader').ajaxStart(function(){ $(this).show(); }).ajaxStop(function(){ $(this).hide(); }); // Initially load the product select fetchSelect('productSelect'); });

Great! We are now left with generating the actual JSON feed. Notice that the fetchSelect function takes a string argument. This is the key we will be passing back to PHP, denoting which set of items we want.

Here is a sample response from our PHP script:

{ "items": { "Phones": "phoneSelect", "Notebooks": "notebookSelect", "Tablets": "" }, "title": "What would you like to purchase?", "defaultText": "Choose a product category" }

fetchSelect loops through the items and uses the keys as content of the option elements, and the values as connections. Phones and Notebooks would cause the script to generate new select boxes, while Tablets would not.

Improved Select boxes using the Chosen Plugin

The PHP

We need to somehow store the information about the select boxes, the options they contain and the connections between them. With a database this could be done by selecting a specific set of rows. But here we will be storing this data statically as objects. For this purpose, we will define a simple class that will hold the information for a select box:

ajax.php / 1 // Each select box will be an instance of this class class SelectBox{ public $items = array(); public $defaultText = ''; public $title = ''; public function __construct($title, $default){ $this->defaultText = $default; $this->title = $title; } public function addItem($name, $connection = NULL){ $this->items[$name] = $connection; return $this; } public function toJSON(){ return json_encode($this); } }

Now we only need to create an instance of this class for every select box, and call the addItem() to add options. This method has an optional $connection parameter, that holds the name of a dependent select box.

ajax.php / 2 /* Configuring the selectboxes */ // Product selectbox $productSelect = new SelectBox('What would you like to purchase?','Choose a product category'); $productSelect->addItem('Phones','phoneSelect') ->addItem('Notebooks','notebookSelect') ->addItem('Tablets','tabletSelect'); // Phone types $phoneSelect = new SelectBox('What kind of phone are you interested in?', 'Pick a phone type'); $phoneSelect->addItem('Smartphones','smartphoneSelect') ->addItem('Feature phones','featurephoneSelect'); // Smartphones $smartphoneSelect = new SelectBox('Which is your desired smartphone?','Choose a smartphone model'); $smartphoneSelect->addItem('Samsung Galaxy Nexus') ->addItem('iPhone 4S','iphoneSelect') ->addItem('Samsung Galaxy S2') ->addItem('HTC Sensation'); // Feature phones $featurephoneSelect = new SelectBox('Which is your desired featurephone?','Choose a feature phone'); $featurephoneSelect->addItem('Nokia N34') ->addItem('Sony Ericsson 334') ->addItem('Motorola'); // iPhone colors $iphoneSelect = new SelectBox('What color would you like?','Choose a color'); $iphoneSelect->addItem('White')->addItem('Black'); // Notebook select $notebookSelect = new SelectBox('Which notebook would you like to buy?', 'Choose a notebook model'); $notebookSelect->addItem('Asus Zenbook','caseSelect') ->addItem('Macbook Air','caseSelect') ->addItem('Acer Aspire','caseSelect') ->addItem('Lenovo Thinkpad','caseSelect') ->addItem('Dell Inspiron','caseSelect'); // Tablet select $tabletSelect = new SelectBox('Which tablet would you like to buy?', 'Pick a tablet'); $tabletSelect->addItem('Asus Transformer','caseSelect') ->addItem('Samsung Galaxy Tab','caseSelect') ->addItem('iPad 16GB','caseSelect') ->addItem('iPad 32GB','caseSelect') ->addItem('Acer Iconia Tab','caseSelect'); // Case select $caseSelect = new SelectBox('Buy protective casing?',''); $caseSelect->addItem('Yes')->addItem('No'); // Register all the select items in an array $selects = array( 'productSelect' => $productSelect, 'phoneSelect' => $phoneSelect, 'smartphoneSelect' => $smartphoneSelect, 'featurephoneSelect' => $featurephoneSelect, 'iphoneSelect' => $iphoneSelect, 'notebookSelect' => $notebookSelect, 'tabletSelect' => $tabletSelect, 'caseSelect' => $caseSelect );

The code above defines a number of select items and places them in the $selects array. When this script receives an AJAX request, it will look into this array and return a response:

ajax.php / 3 // We look up this array and return a select object depending // on the $_GET['key'] parameter passed by jQuery // You can modify it to select results from a database instead if(array_key_exists($_GET['key'],$selects)){ header('Content-type: application/json'); echo $selects[$_GET['key']]->toJSON(); } else{ header("HTTP/1.0 404 Not Found"); header('Status: 404 Not Found'); }

By calling the toJSON() method we defined in the beginning, we output all the data for the select object as JSON, ready for use by our jQuery frontend.

With this our Chained AJAX Selects example is complete!

Done

You can use this example to power user guides, product recommendations or search pages. Upgrading the script to use a live database is straightforward and it will actually simplify the PHP script.

Creating an iOS-like Home Screen with CoffeeScript

Thu, 10/20/2011 - 06:46

Today we are going to create an iOS-like home screen using CoffeeScript – a new JavaScript based language, and the jQuery library. CoffeScript has a clean syntax that lies somewhere in between Ruby and Python. If you haven’t used any of them, don’t worry – it is not required. However you will need to be familiar with JavaScript so you can better understand the concepts behind the language.

We are also going to use the Touchable plugin, so we can listen for touch-based events.

First, what is CoffeeScript?

CoffeeScript is a neat programming language meant to enhance the good parts of JavaScript, while working around the not so good. It makes OOP easy and introduces a number of useful additions such as comprehensions, new syntax for functions and scope handling, along with numerous small improvements.

CoffeeScript works in every browser out there, and is compatible with all your existing JavaScript code (including libraries like jQuery and plugins). But how does this work if it is a different language? Simple – CoffeeScript compiles down to JavaScript, so it works in any browser that supports it.

Before you start following this tutorial, I would suggest that you read through the examples on the CoffeeScript website (be sure to check out the “Try CoffeeScript” tab), and The Little Book on CoffeeScript for an introduction to the language.

iOS -like Home Screen with CoffeeScript

The HTML

Lets start with the HTML markup of our iOS-like home screen. As usual, this is a regular HTML5 document with stylehseets in the head and JS includes before the closing body tag.

index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>iOS Home Screen with CoffeeScript | Tutorialzine Demo</title> <!-- Our CSS stylesheet file --> <link rel="stylesheet" href="assets/css/styles.css" /> <!--[if lt IE 9]> <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> </head> <body> <section id="homeScreen"> <div id="mask"> <div id="allScreens"> <!-- The .screen divs will go here --> </div> </div> <ul id="indicators"> <!-- A LI element for every screen --> </ul> <div id="dock"> <!-- The three dock icons will go here --> </div> </section> <!-- JavaScript includes --> <script src="http://code.jquery.com/jquery-1.6.3.min.js"></script> <script src="assets/js/touchable.js"></script> <script src="assets/js/coffee-script.js"></script> <script type="text/coffeescript"> # Our Code Goes Here </script> </body> </html>

We have the #homeScreen section, which is the main container of our experiment. Inside it is the #mask, which uses overflow:hidden to show only one screen at the time. The #allScreens div inside it, as the name suggests, contains all the dynamically generated .screen divs with icons.

The #mask div shows only one screen at a time with overflow:hidden.

Following is the #indicators UL, which shows the little dots with the currently shown screen, and the #dock div.

As mentioned previously, CoffeeScript requires an extra compilation step, which will convert the source code to JavaScript. You can do this with the coffeescript package for node.js (as explained on their website), or with coffeescript.exe for windows, which is standalone and ready for use executable. For small scripts, you can also include the compiler directly in your page and write your code inline in a <script> tag – which we will be using today.

At the bottom of the page, you can see our script includes. These are the jQuery library, the Touchable plugin, which will help us work with touch events, and the CoffeeScript compiler – coffee-script.js. The compiler will look for <script type="text/coffeescript"> tags on the page, which is where we will be writing our code.

The CoffeScript Code

As we are writing the code inline, we do not need to compile it before deploying the web page. This is great for small web pages and during development. However, if you plan on writing larger applications, it would be a better idea to compile your code using one of the tools described above.

Now lets start with writing a simple class – Icon.

# The Icon class. class Icon # The constructor. The -> arrow signifies # a function definition. constructor: (@id, @title) -> # @ is synonymous for "this". The id and title parameters # of the constructor are automatically added as this.id and this.title # @markup holds the HTML of the icon. It is # transformed to this.markup behind the scenes. @markup = "<div class='icon' style='background-image:url(assets/img/icons/#{@id}.png)' title='#{@title}'></div>"

Objects of this class are going to represent the icons in the home screen. Each icon has a markup property which contains the HTML code needed to display it. You can see that functions in CoffeeScript are defined as arrows (->), with the parameters to the function given on the left in braces. Notice that comments here start with the # symbol. You can use three ### to denote multiline comments.

Now lets define a class for the dock icons. It will be pretty similar to the Icon class, so we are going to extend it:

# The DockIcon class inherits from Icon class DockIcon extends Icon constructor: (id, title)-> # This calls the constructor if Icon super(id, title) # Changing the class name of the generated HTML @markup = @markup.replace("class='icon'","class='dockicon'")

Using super() will call Icon’s constructor and initialize the markup property. We only need to replace the class name.

We will divide the home screen in individual .screen divs, each holding their own set of icons. Here is the class for that:

# The Screen Class class Screen # Function arguments can have default values constructor: (icons = [])-> @icons = icons attachIcons: (icons = [])-> Array.prototype.push.apply(@icons, icons) generate: -> markup = [] # Looping through the @icons array markup.push(icon.markup) for icon in @icons # The last line of every function is implicitly returned "<div class='screen'>#{markup.join('')}</div>"

Instead of a markup property, here we are using a generate() method that will return the HTML. Notice how we are looping over the array – this is called a comprehension. The part before the for keyword is executed on every element in the icons array.

The iOS Dock

We now need a class that pulls everything together, and controls the transitions between the screens. Here is what it looks like:

class Stage # The width of our "device" screen. This is # basically the width of the #mask div. screenWidth: 332 constructor: (icons)-> @currentScreen = 0 @screens = [] # Calculating the number of screens # necessary to display all the icons num = Math.ceil(icons.length / 9) i = 0 while num-- # we pass a slice of the icons array s = new Screen(icons[i...i+9]) # adding the screen to the local screens array @screens.push(s) i+=9 # This method populates the passed element with HTML addScreensTo: (element)-> # We are using the jQuery library from within CS: @element = $(element) @element.width(@screens.length*@screenWidth) for screen in @screens @element.append(screen.generate()) addIndicatorsTo: (elem)-> # This method creates the small circular # indicators. Also using jQuery @ul = $(elem) for screen in @screens @ul.append('<li>') @ul.find('li:first').addClass('active'); # ... More methods go here ...

The Stage takes an array of icons in the constructor. It then calculates how many screens will be needed, and creates an object for each one, passing it a slice of the icons array.

We now have the markup of all these elements on the page, but we are still missing the methods that control the transition between the slides. You can see them below (still part of the Stage class):

goTo: (screenNum)-> # This method animates the allScreen div in # order to expose the needed screen in #mask if @element.is(':animated') return false # if this is the first or last screen, # run the end of scroll animation if @currentScreen == screenNum # Parallel assignment: [from, to] = ['+=15','-=15'] if @currentScreen != 0 [from, to] = [to, from] # Tell the user there aren't any more screens: @element.animate( { marginLeft : from }, 150 ) .animate( { marginLeft : to }, 150 ) else # If everything is ok, animate the transition between the screens. # The fat arrow => is a function that preserves the context of "this" @element.animate( { marginLeft:-screenNum*@screenWidth }, => @currentScreen = screenNum ) @ul.find('li').removeClass('active').eq(screenNum).addClass('active'); next: -> toShow = @currentScreen+1 # If there is no next screen, show # the last one if toShow == @screens.length toShow = @screens.length - 1 @goTo(toShow) previous: -> toShow = @currentScreen-1 # If there is no previous screen, # show the first one if toShow == -1 toShow = 0 @goTo(toShow)

Both the next() and previous() methods call goTo() internally, passing a screen number (starting from zero). The goTo() method animates the #allScreen div to show the needed screen.

All we need to do now is bind a function to the document.ready event. For this we will use jQuery .

# This is equivalent to $(function(){}): $ -> # You can skip the comma if it's on the end of a line: allIcons = [ new Icon('Photos', 'Photo Gallery'), new Icon('Maps', 'Google Maps') new Icon('Chuzzle', 'Chuzzle'), new Icon('Safari', 'Safari') new Icon('Weather', 'Weather'), new Icon('nes', 'NES Emulator') new Icon('Calendar', 'Calendar'), new Icon('Clock', 'Clock') new Icon('BossPrefs', 'Boss Prefs'), new Icon('Chess', 'Chess') new Icon('Mail', 'Mail'), new Icon('Phone', 'Phone') new Icon('SMS', 'SMS Center'), new Icon('Camera', 'Camera') new Icon('iPod', 'iPod'), new Icon('Calculator', 'Calculator') new Icon('Music', 'Music'), new Icon('Poof', 'Poof') new Icon('Settings', 'Settings'), new Icon('YouTube', 'Youtube') new Icon('psx4all', 'PSx4All'), new Icon('VideoRecorder', 'Record Video') new Icon('Installer', 'Installer'), new Icon('Notes', 'Notes') new Icon('RagingThunder', 'RagingThunder'), new Icon('Stocks', 'Stocks') new Icon('genesis4iphone', 'Genesis'), new Icon('snes4iphone', 'SNES Emulator') new Icon('Calendar', 'Calendar'), new Icon('Clock', 'Clock') new Icon('Photos', 'Photo Gallery'), new Icon('Maps', 'Google Maps') ] dockIcons = [ new DockIcon('Camera', 'Camera') new DockIcon('iPod', 'iPod') new DockIcon('Calculator', 'Calculator') ] allScreens = $('#allScreens') # Using the Touchable plugin to listen for # touch based events: allScreens.Touchable(); # Creating a new stage object stage = new Stage(allIcons) stage.addScreensTo(allScreens) stage.addIndicatorsTo('#indicators') # Listening for the touchablemove event. # Notice the callback function. Braces on # function calls are optional allScreens.bind 'touchablemove', (e,touch)-> stage.next() if touch.currentDelta.x < -5 stage.previous() if touch.currentDelta.x > 5 # Adding the dock icons: dock = $('#dock') for icon in dockIcons dock.append(icon.markup)

By calling the Touchable method we are extending the element to support several touch based events. Among them is touchablemove, which is executed when the user moves his finger across the screen. It is also called when we drag with the mouse. Further down, when we bind for that event, we get a touch object as the second argument of the callback function. It holds the delta, or difference, from the beginning of the movement.

With this our iOS-like Home Screen is complete!

Conclusion

CoffeeScript is an interesting language that can make developing in the browser easier. You can expect to write up to 50% less code comparing to pure JavaScript.

But don’t fall pray to the hype surrounding it just yet – CoffeeScript isn’t going to replace JavaScript any time soon, as it sacrifices some of the agility that JS provides in attempt to make development easier. The CS way might not be the best fit for your project.

CoffeeScript also introduces an extra compilation step that separates you from deploying your code, but this can be solved by web frameworks that compile the code for you as is the case with Rails, where CS became a default.