Posts Tagged 'Coding'

March 7, 2013

Script Clip: HTML5 Audio Player with jQuery Controls

HTML5 and jQuery provide mind-blowing functionality. Projects that would have taken hours of development and hundreds of lines of code a few years ago can now be completed in about the time it'll take you to read this paragraph. If you wanted to add your own audio player on a web page in the past, what would it have involved? Complicated elements? Flash (*shudders*)? It was so complicated that most developers just linked to the audio file, and the user just downloaded the file to play it locally. With HTML5, an embedded, cross-browser audio player can be added to a page with five lines of code, and if you want to get really fancy, you can easily use jQuery to add some custom controls.

If you've read any of my previous blogs, you know that I love when I find little code snippets that make life as a web developer easier. My go-to tools in that pursuit are HTML5 and jQuery, so when I came across this audio player, I knew I had to share. There are some great jQuery plugins to play music files on a web page, but they can be major overkill for a simple application if you have to include comprehensive controls and themes. Sometimes you just want something simple without all of that overhead:

Oooh... Ahhh...

That song — Pop Bounce by SoftLayer's very own Chris Interrante — is written in five simple lines of HTML5 code:

<audio style="width:550px; margin: 0 auto; display:block;" controls>
  <source src="http://cdn.softlayer.com/innerlayer/Interrante-PopBounce.ogg" type="audio/ogg">
  <source src="http://cdn.softlayer.com/innerlayer/Interrante-PopBounce.mp3" type="audio/mpeg">
Your browser does not support the audio element.
</audio>

If IE 9+, Chrome 6+, Firefox 3.6+, Safari 5+ and Opera 10+ would all agree on supported file formats for the <audio> tag, the code snippet would be even smaller. I completely geek out over it every time I look at it and remember the days of yore. As you can see, the HTML5 application has some simple default controls: Play, Pause, Scan to Time, etc. As a developers, I couldn't help but look for a to spice it up a little ... What if we want to fire an event when the user plays, pauses, stops or takes any other action with the audio file? jQuery!

Make sure your jQuery include is in the <head> of your page:

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

Now let's use jQuery to script separate "Play" and "Pause" links ... And let's have those links fire off an alert when they are pressed:

$(document).ready(function(){
  $("#play-button").click(function(){
   $("#audioplayer")[0].play();
   alert('You have played the audio file!');
  })    
 
  $("#pause-button").click(function(){
   $("#audioplayer")[0].pause();
   alert('You have paused the audio file!');
  })    
})

With that script in the <head> as well, the HTML on our page will look like this:

<div class=:"audioplayer">
  <audio id="audioplayer" name="audioplayer" controls loop>
    <source src="http://cdn.softlayer.com/innerlayer/Interrante-PopBounce.ogg" type="audio/ogg">
    <source src="http://cdn.softlayer.com/innerlayer/Interrante-PopBounce.mp3" type="audio/mpeg">
  Your browser does not support the audio element.
  </audio>
 
  <a id="play-button" href="#">Play!</a>
  <a id="pause-button" href="#">Pause!</a>
</div>

Want proof that it works that simply? Boom.

You can theme it any way you like; you can add icons instead of the text ... The world is your oyster. The bonus is that you're using one of the lightest media players on the Internet! If you decide to get brave (or just more awesome), you can explore additional features. You're using jQuery, so your possibilities are nearly limitless. If you want to implement a "Stop" feature (which returns the audio back to the beginning when "Stop" is pressed), you can get creative:

$("#stop-button").click(function(){
    $("#audioplayer")[0].currentTime = 0; // return the audio file back to the beginning
}

If you want to include some volume controls, those can be added in a snap as well:

$("#volumeUp").click(function(){
    $("#audioplayer")[0].volume +=0.1;
}
 
$("#volumeDown").click(function(){
    $("#audioplayer")[0].volume -=0.1;
}

Try it out and let me know what you think. Your homework is to come up with some unique audio player functionality and share it here!

-Cassandra

February 14, 2013

Tips and Tricks – Building a jQuery Plugin (Part 2)

jQuery plugins don't have to be complicated to create. If you've stumbled upon this blog in pursuit of a guide to show you how to make a jQuery plugin, you might not believe me ... It seems like there's a chasm between the "haves" of jQuery plugin developers and the "have nots" of future jQuery developers, and there aren't very many bridges to get from one side to the other. In Part 1 of our "Building a jQuery Plugin" series, we broke down how to build the basic structure of a plugin, and in this installment, we'll be adding some usable functionality to our plugin.

Let's start with the jQuery code block we created in Part 1:

(function($) {
    $.fn.slPlugin = function(options) {
            var defaults = {
                myVar: "This is", // this will be the default value of this var
                anotherVar: "our awesome",
                coolVar: "plugin!",
            };
            var options = $.extend(defaults, options);
            this.each(function() {
                ourString = myVar + " " + anotherVar + " " + coolVar;
            });
            return ourString;
    };
}) (jQuery);

We want our plugin to do a little more than return, "This is our awesome plugin!" so let's come up with some functionality to build. For this exercise, let's create a simple plugin that allows truncates a blob of text to a specified length while providing the user an option show/hide the rest of the text. Since the most common character length limitation on the Internet these days is Twitter's 140 characters, we'll use that mark in our example.

Taking what we know about the basic jQuery plugin structure, let's create the foundation for our new plugin — slPlugin2:

(function($) {
    $.fn.slPlugin2 = function(options) {
 
        var defaults = {
            length: 140,
            moreLink: "read more",
            lessLink: "collapse",
            trailingText: "..."
        };
 
        var options = $.extend(defaults, options);
    };
})(jQuery);

As you can see, we've established four default variables:

  • length: The length of the paragraph we want before we truncate the rest.
  • moreLength: What we append to the paragraph when it is truncated. This will be the link the user clicks to expand the rest of the text.
  • lessLink: What we append to the paragraph when it is expanded. This will be the link the user clicks to collapse the rest of the text.
  • trailingText: The typical ellipses to append to the truncation.

In our jQuery plugin example from Part 1, we started our function with this.each(function() {, and for this example, we're going to add a return for this to maintain chainability. By doing so, we're able to manipulate the segment with methods. For example, if we started our function with this.each(function() {, we'd call it with this line:

$('#ourParagraph').slPlugin2();

If we start the function with return this.each(function() {, we have the freedom to add further manipulation:

$('#ourParagraph').slPlugin2().bind();

With such a simple change, we're able to add method calls to make one massive dynamic function.

Let's flesh out the actual function a little more. We'll add a substantial bit of code in this step, but you should be able to follow along with the changes via the comments:

(function($) {
    $.fn.slPlugin2 = function(options) {
 
        var defaults = {
            length: 140, 
            moreLink: "read more",
            lessLink: "collapse",
            trailingText: "..."
        };
 
        var options = $.extend(defaults, options);
 
        // return this keyword for chainability
        return this.each(function() {
            var ourText = $(this);  // the element we want to manipulate
            var ourHtml = ourText.html(); //get the contents of ourText!
            // let's check if the contents are longer than we want
            if (ourHtml.length > options.length) {
                var truncSpot = ourHtml.indexOf(' ', options.length); // the location of the first space (so we don't truncate mid-word) where we will end our truncation.
 
   // make sure to ignore the first space IF the text starts with a space
   if (truncSpot != -1){
       // the part of the text that will not be truncated, starting from the beginning
       var firstText = ourHtml.substring(0, truncSpot);
 
       // the part of the text that will be truncated, minus the trailing space
       var secondText = ourHtml.substring(truncSpot, ourHtml.legnth -1);
                }
            }
        })
    };
})(jQuery);

Are you still with us? I know it seems like a lot to take in, but each piece is very straightforward. The firstText is the chunk of text that will be shown: The first 140 characters (or whatever length you define). The secondText is what will be truncated. We have two blobs of text, and now we need to make them work together:

(function($) {
    $.fn.slPlugin2 = function(options) {
 
        var defaults = {
            length: 140, 
            moreLink: "read more",
            lessLink: "read less",
            trailingText: "..."
        };
 
        var options = $.extend(defaults, options);
 
        // return this keyword for chainability
        return this.each(function() {
            var ourText = $(this);  // the element we want to manipulate
            var ourHtml = ourText.html(); //get the contents of ourText!
            // let's check if the contents are longer than we want
            if (ourHtml.length > options.length) {
                var truncSpot = ourHtml.indexOf(' ', options.length); // the location of the first space (so we don't truncate mid-word) where we will end our truncation.
 
   // make sure to ignore the first space IF the text starts with a space
   if (truncSpot != -1){
       // the part of the text that will not be truncated, starting from the beginning
       var firstText = ourHtml.substring(0, truncSpot);
 
       // the part of the text that will be truncated, minus the trailing space
       var secondText = ourHtml.substring(truncSpot, ourHtml.legnth -1);
 
       // perform our truncation on our container ourText, which is technically more of a "rewrite" of our paragraph, to our liking so we can modify how we please. It's basically saying: display the first blob then add our trailing text, then add our truncated part wrapped in span tags (to further modify)
       ourText.html(firstText + options.trailingText + '<span class="slPlugin2">' + secondText + '</span>');
 
       // but wait! The secondText isn't supposed to show until the user clicks "read more", right? Right! Hide it using the span tags we wrapped it in above.
       ourText.find('.slPlugin2').css("display", "none");
                }
            }
        })
    };
})(jQuery);

Our function now truncates text to the specified length, and we can call it from our page simply:

<script src="jquery.min.js"></script>
<script src="jquery.slPlugin2.js"></script>
<script type="text/javascript">
$(document).ready(function() {  
    $('#slText').slPlugin2();  
});
</script>

Out of all the ways to truncate text via jQuery, this has to be my favorite. It's feature-rich while still being fairly easy to understand. As you might have noticed, we haven't touched on the "read more" and "read less" links or the expanding/collapsing animations yet, but we'll be covering those in Part 3 of this series. Between now and when Part 3 is published, I challenge you to think up how you'd add those features to this plugin as homework.

-Cassandra

February 12, 2013

From the Startup Trenches to the Catalyst War Room

Before joining SoftLayer, I was locked in a dark, cold room for two years. Sustained by a diet of sugar and caffeine and basking in the glow of a 27" iMac, I was tasked with making servers dance to the tune of Ruby. The first few months were the toughest. The hours were long, and we worked through holidays. And I loved it.

If that work environment seems like torture, you probably haven't been on the front lines of a development team. I was a member of a band of brothers at war with poorly documented vendor APIs, trying to emerge victorious from the Battle of Version 1.0. We operated (and suffered) like a startup in its early stages, so I've had firsthand experience with the ups and downs of creating and innovating in technology. Little did I know that those long hours and challenges were actually preparing me to help hundreds of other developers facing similar circumstances ... I was training to be a Catalyst SLayer:

Catalyst Team

You probably know a lot about Catalyst by now, but one of the perks of the program that often gets overshadowed by "free hosting" is the mentorship and feedback the SoftLayer team provides every Catalyst participant. Entrepreneurs bounce ideas off of guys like Paul Ford and George Karidis to benefit from the years of experience and success we've experienced, and the more technical folks can enlist our help in figuring out more efficient ways to tie their platforms to their infrastructure.

When I was forging through the startup waters, I was fortunate to have been supported by financially reinforced walls and the skilled engineers of a well-established hosting company in Tokyo. Unfortunately, that kind of support is relatively uncommon. That's where Catalyst swoops in. SoftLayer's roots were planted in the founders' living rooms and garages, so we're particularly fond of other companies who are bootstrapping, learning from failure and doing whatever it takes to succeed. In my role with Catalyst, I've effectively become a resource for hundreds of startups around the world ... and that feels good.

Five days before my official start date, I receive a call from Josh telling me that we'd be spending my first official week on the job in Seattle with Surf Incubator and Portland with Portland Incubator Experiment (PIE). While the trip did not involve carving waves or stuffing our faces with baked goods (bummer), we did get to hear passionate people explain what keeps them up at night. We got to share a little bit about SoftLayer and how we can help them sleep better (or fuel them with more energy when they're up at night ... depending on which they preferred), and as I headed back to Los Angeles, I knew I made the right choice to become a SLayer. I'm surrounded by energy, creativity, passion, innovation and collaboration on a daily basis. It's intoxicating.

TL;DR: I love my job.

-@andy_mui

January 10, 2013

Web Development - JavaScript Packaging

If you think of JavaScript as the ugly duckling of programming languages, think again! It got a bad rap in the earlier days of the web because developers knew enough just to get by but didn't really respect it like they did Java, PHP or .Net. Like other well-known and heavily used languages, JavaScript contains various data types (String, Boolean, Number, etc.), objects and functions, and it is even capable of inheritance. Unfortunately, that functionality is often overlooked, and many developers seem to implement it as an afterthought: "Oh, we need to add some neat jQuery effects over there? I'll just throw some inline JavaScript here." That kind of implementation perpetuates a stereotype that JavaScript code is unorganized and difficult to maintain, but it doesn't have to be! I'm going to show you how easy it is to maintain and organize your code base by packaging your JavaScript classes into a single file to be included with your website.

There are a few things to cover before we jump into code:

  1. JavaScript Framework - Mootools is my framework of choice, but you can use whatever JavaScript framework you'd like.
  2. Classes - Because I see JavaScript as another programming language that I respect (and is capable of object-oriented-like design), I write classes for EVERYTHING. Don't think of your JavaScript code as something you use once and throw away. Write your code to be generic enough to be reused wherever it's placed. Object-oriented design is great for this! Mootools makes object-oriented design easy to do, so this point reinforces the point above.
  3. Class Files - Just like you'd organize your PHP to contain one class per file, I do the exact same thing with JavaScript. Note: Each of the class files in the example below uses the class name appended with .js.
  4. Namespacing - I will be organizing my classes in a way that will only add a single property — PT — to the global namespace. I won't get into the details of namespacing in this blog because I'm sure you're already thinking, "The code! The code! Get on with it!" You can namespace whatever is right for your situation.

For this example, our classes will be food-themed because ... well ... I enjoy food. Let's get started by creating our base object:

/*
---
name: PT
description: The base class for all the custom classes
authors: [Philip Thompson]
provides: [PT]
...
*/
var PT = {};

We now have an empty object from which we'll build all of our classes. We'll go I will go into more details later about the comment section, but let's build our first class: PT.Ham.

/*
---
name: PT.Ham
description: The ham class
authors: [Philip Thompson]
requires: [/PT]
provides: [PT.Ham]
...
*/
 
(function() {
    PT.Ham = new Class({
        // Custom code here...
    });
}());

As I mentioned in point three (above), PT.Ham should be saved in the file named PT.Ham.js. When we create second class, PT.Pineapple, we'll store it in PT.Pineapple.js:

/*
---
name: PT.Pineapple
description: The pineapple class
authors: [Philip Thompson]
requires: [/PT]
provides: [PT.Pineapple]
...
*/
 
(function() {
    PT.Pineapple = new Class({
        // Custom code here...
    });
}());

Our final class for this example will be PT.Pizza (I'll let you guess the name of the file where PT.Pizza lives). Our PT.Pizza class will require that PT, PT.Ham and PT.Pineapple be present.

/*
---
name: PT.Pizza
description: The pizza class
authors: [Philip Thompson]
requires: [/PT, /PT.Ham, /PT.Pineapple]
provides: [PT.Pizza]
...
*/
 
(function() {
    PT.Pizza = new Class({
        // Custom code here that uses PT.Ham and PT.Pineapple...
    });
}());

Before we go any further, let's check out the comments we include above each of the classes. The comments are formatted for YAML — YAML Ain't Markup Language (you gotta love recursive acronyms). These comments allow our parser to determine how our classes are related, and they help resolve dependencies. YAML's pretty easy to learn and you only need to know a few basic features to use it. The YAML comments in this example are essential for our JavaScript package-manager — Packager. I won't go into all the details about Packager, but simply mention a few commands that we'll need to build our single JavaScript file.

In addition to the YAML comments in each of the class files, we also need to create a YAML file that will organize our code. This file — package.yml for this example — is used to load our separate JavaScript classes:

name: "PT"
description: "Provides our fancy PT classes"
authors: "[Philip Thompson]"
version: "1.0.0"
sources:
    - js/PT.js
    - js/PT.Ham.js
    - js/PT.Pineapple.js
    - js/PT.Pizza.js

package.yml shows that all of our PT* files are located in the js directory, one directory up from the package.yml file. Some of the properties in the YAML file are optional, and you can add much more detail if you'd like, but this will get the job done for our purposes.

Now we're ready to turn back to Packager to build our packaged file. Packager includes an option to use PHP, but we're just going to do it command-line. First, we need to register the new package (package.yml) we created for PT. If our JavaScript files are located in /path/to/web/directory/js, the package.yml file is in /path/to/web/directory:

./packager register /path/to/web/directory

This finds our package.yml file and registers our PT package. Now that we have our package registered, we can build it:

./packager build * > /path/to/web/directory/js/PT.all.js

The Packager sees that our PT package is registered, so it looks at each of the individual class files to build a single large file. In the comments of each of the class files, it determines if there are dependencies and warns you if any are not found.

It might seem like a lot of work when it's written out like this, but I can assure you that when you go through the process, it takes no time at all. The huge benefit of packaging our JavaScript is evident as soon as you start incorporating those JavaScript classes into your website ... Because we have built all of our class files into a single file, we don't need to include each of the individual JavaScript files into our website (much less include the inline JavaScript declarations that make you cringe). To streamline your implementation even further if you're using your JavaScript package in a production deployment, I recommend that you "minify" your code as well.

See ... Organized code is no longer just for server-side only languages. Treat your JavaScript kindly, and it will be your friend!

Happy coding!

-Philip

December 27, 2012

Using SoftLayer Object Storage to Back Up Your Server

Before I came to my senses and moved my personal servers to SoftLayer, I was one of many victims of a SolusVM exploit that resulted in the wide-scale attack of many nodes in my previous host's Chicago data center. While I'm a firm believer in backing up my data, I could not have foreseen the situation I was faced with: Not only was my server in one data center compromised with all of its data deleted, but my backup server in one of the host's other data centers was also attacked ... This left me with old, stale backups on my local computer and not much else. I quickly relocated my data and decided that I should use SoftLayer Object Storage to supplement and improve upon my backup and disaster recovery plans.

With SoftLayer Object Storage Python Client set up and the SoftLayer Object Storage Backup script — slbackup.py — in hand, I had the tools I needed to build a solid backup infrastructure easily. On Linux.org, I contributed an article about how to perform MySQL backups with those resources, so the database piece is handled, but I also need to back up my web files, so I whipped up another quick bash script to run:

#!/bin/bash
 
# The path the backups will be dumped to
DUMP_DIR="/home/backups/"
 
# Path to the web files to be backed up
BACKUP_PATH="/var/www/sites /"
 
# Back up folder name (mmddyyyy)
BACKUP_DIR="`date +%m%d%Y`"
 
# Backup File Name
DUMP_FILE="`date +%m_%d_%Y_%H_%M_%S`_site_files"
 
# SL container name
CONTAINER="site_backups"
 
# Create backup dir if doesn't exist
if [ ! -d $DUMP_DIR$BACKUP_DIR ]; then
        mkdir -p $DUMP_DIR$BACKUP_DIR
fi
 
tar -zcvpf $DUMP_DIR$BACKUP_DIR/$DUMP_FILE.tar.gz $BACKUP_PATH
 
# Make sure the archive exists
if [ -f $DUMP_DIR$BACKUP_DIR/$DUMP_FILE.tar.gz ]; then
        /root/slbackup.py -s $DUMP_DIR$BACKUP_DIR/ -o "$CONTAINER" -r 30
 
        # Remove the backup stored locally
        rm -rf $DUMP_DIR$BACKUP_DIR
 
        # Success
        exit 0
else
        echo "$DUMP_DIR$BACKUP_DIR/$DUMP_FILE.tar.gz does not exist."
        exit 1
fi

It's not the prettiest bash script, but it gets the job done. By tweaking a few variables, you can easily generate backups for any important directory of files and push them to your SoftLayer Object Storage account. If you want to change the retention time of your backups to be longer or shorter, you can change the 30 after the –r in the line below to the number of days you want to keep each backup:

/root/slbackup.py -s $DUMP_DIR$BACKUP_DIR/ -o "$CONTAINER" -r 30

I created a script for each website on my server, and I set a CRON (crontab –e) entry to run each one on Sundays staggered by 5 minutes:

5 1 * * 0  /root/bin/cron/CRON-site1.com_web_files > /dev/null
10 1 * * 0  /root/bin/cron/CRON-site2.com_web_files > /dev/null
15 1 * * 0  /root/bin/cron/CRON-site3.com_web_files > /dev/null 

If you're looking for an easy way to automate and solidify your backups, this little bit of code could make life easier on you. Had I taken the few minutes to put this script together prior to the attack I experienced at my previous host, I wouldn't have lost any of my data. It's easy to get lulled into "backup apathy" when you don't need your backups, but just because nothing *has* happened to your data doesn't mean nothing *can* happen to your data.

Take it from me ... Be over-prepared and save yourself a lot of trouble.

-Ronald

December 19, 2012

SoftLayer API: Streamline. Simplify.

Building an API is a bit of a balancing act. You want your API to be simple and easy to use, and you want it to be feature-rich and completely customizable. Because those two desires happen to live on opposite ends of the spectrum, every API finds a different stasis in terms of how complex and customizable they are. The SoftLayer API was designed to provide customers with granular control of every action associated with any product or service on our platform; anything you can do in our customer portal can be done via our API. That depth of functionality might be intimidating to developers looking to dive in quickly and incorporate the SoftLayer platform into their applications, so our development team has been working to streamline and simplify some of the most common API services to make them even more accessible.

SoftLayer API

To get an idea of what their efforts look like in practice, Phil posted an SLDN blog with a perfect example of how they simplified cloud computing instance (CCI) creation via the API. The traditional CCI ordering process required developers to define nineteen data points:

Hostname
Domain name
complexType
Package Id
Location Id
Quantity to order
Number of cores
Amount of RAM
Remote management options
Port speeds
Public bandwidth allotment
Primary subnet size
Disk size
Operating system
Monitoring
Notification
Response
VPN Management - Private Network
Vulnerability Assessments & Management

While each of those data points is straightforward, you still have to define nineteen of them. You have all of those options when you check out through our shopping cart, so it makes sense that you'd have them in the API, but when it comes to ordering through the API, you don't necessarily need all of those options. Our development team observed our customers' API usage patterns, and they created the slimmed-down and efficient SoftLayer_Virtual_Guest::createObject — a method that only requires seven data points:

Hostname
Domain name
Number of cores
Amount of RAM
Hourly/monthly billing
Local vs SAN disk
Operating System

Without showing you a single line of code, you see the improvement. Default values were established for options like Port speeds and Monitoring based on customer usage patterns, and as a result, developers only have to provide half the data to place a new CCI order. Because each data point might require multiple lines of code, the volume of API code required to place an order is slimmed down even more. The best part is that if you find yourself needing to modify one of the now-default options like Port speeds or Monitoring, you still can!

As the development team finds other API services and methods that can be streamlined and simplified like this one, they'll ninja new solutions to make the API even more accessible. Have you tried coding to the SoftLayer API yet? If not, what's the biggest roadblock for you? If you're already a SLAPI coder, what other methods do you use often that could be streamlined?

-@khazard

November 27, 2012

Tips and Tricks - Building a jQuery Plugin (Part 1)

I've written several blogs detailing the use of different jQuery plugins (like Select2, LazyLoad and equalHeights), and in the process, I've noticed an increasing frustration among the development community when it comes to building jQuery plugins. The resources and documentation I've found online have not as clear and easy as they could be, so in my next few posts, I'll break down the process to make jQuery plugin creation simple and straightforward. In this post, we'll cover the basic structure of a plugin and where to insert your own functionality, and in Part 2, we'll pick a simple task and add on to our already-made structure.

Before I go any further, it's probably important to address a question you might be asking yourself: "Why would I want to make my own plugin?" The best reason that comes to my mind is portability. If you've ever created a large-scale project, take a look back into your source code and note how many of the hundreds of lines of jQuery code you could put into a plugin to reuse on a different project. You probably invested a lot of time and energy into that code, so it doesn't make sense to reinvent the wheel if you ever need that functionality again. If that's not enough of a reason for you, I can also tell you that if you develop your own jQuery plugin, you'll level-up in cool points, and the jQuery community will love you.

For this post, let's create a jQuery plugin that simply returns, "This is our awesome plugin!" Our first step involves putting together the basic skeleton used by every plugin:

(function($) {
    $.fn.slPlugin = function() {
 
            // Awesome plugin stuff goes here
    };
}) (jQuery);

This is your template — your starting point. Practice it. Remember it. Love it. The "slPlugin" piece is what I chose to name this plugin. It's best to name your plugin something unique ... I always run a quick Google search to ensure I don't duplicate the name of a plugin I (or someone else) might need to use in a project alongside my plugin. In this case, we're calling the example plugin slPlugin because SoftLayer is awesome, and I like naming my plugins after awesome things. I'll save this code in a file called jquery.slPlugin.js.

Now that we have our plugin's skeleton, let's add some default values for variables:

(function($) {
    $.fn.slPlugin = function(options) {
            var defaults = {
                myVar: "default", // this will be the default value of this var
                anotherVar: 0,
                coolVar: "this is cool",                
            };
            var options = $.extend(defaults, options);
    };
}) (jQuery);

Let's look at the changes we made between the first example and this one. You'll notice that in our second line we added "options" to become $.fn.slPlugin = function(options) {. We do this because our function is now accepting arguments, and we need to let the function know that. The next difference you come across is the var defaults blurb. In this section, we're providing default values for our variables. If you don't define values for a given variable when you call the plugin, these default values will be used.

Now let's have our plugin return the message we want to send:

(function($) {
    $.fn.slPlugin = function(options) {
            var defaults = {
                myVar: "This is", // this will be the default value of this var
                anotherVar: "our awesome",
                coolVar: "plugin!",
            };
            var options = $.extend(defaults, options);
            this.each(function() {
                ourString = myVar + " " + anotherVar + " " + coolVar;
            });
            return ourString;
    };
}) (jQuery);

We've defined our default values for our variables, concatenated our variables and we've added a return under our variable declaration. If our jQuery plugin is included in a project and no values are provided for our variables, slPlugin will return, "This is our awesome plugin!"

It seems rather rudimentary at this point, but we have to crawl before we walk. This introductory post is laying the groundwork of coding a jQuery plugin, and we'll continue building on this example in the next installment of this series. As you've seen with the LazyLoad, equalHeights and Select2, there are much more complicated things we can do with our plugin, and we'll get there. Sneak Preview: In the next installment, we'll be creating and implementing a truncation function for our plugin ... Get excited!

-Cassandra

November 6, 2012

Tips and Tricks - Pure CSS Sticky Footers

By now, if you've seen my other blog posts, you know that I'm fascinated with how much JavaScript has evolved and how much you can do with jQuery these days. I'm an advocate of working smarter, not harder, and that maxim knows no coding language limits. In this post, I want to share a pure CSS solution that allows for "sticky" footers on a web page. In comparing several different techniques to present this functionality, I found that all of the other routes were overkill when it came to processing time and resource usage.

Our objective is simple: Make the footer of our web page stay at the bottom even if the page's content area is shorter than the user's browser window.

This, by far, is one of my *favorite* things to do. It makes the web layout so much more appealing and creates a very professional feel. I ended up kicking myself the very first time I tried to add this functionality to a project early in my career (ten years ago ... already!?) when I found out just how easy it was. I take solace in knowing that I'm not alone, though ... A quick search for "footer stick bottom" still yields quite a few results from fellow developers who are wrestling with the same frustrating experience I did. If you're in that boat, fear no more! We're going to your footers in shape in a snap.

Here's a diagram of the problem:

CSS Footer

Unfortunately, a lot of people try to handle it with setting a fixed height to the content which would push the footer down. This may work when YOU view it, but there are several different browser window heights, resolutions and variables that make this an *extremely* unreliable solution (notice the emphasis on the word "extremely" ... this basically means "don't do it").

We need a dynamic solution that is able to adapt on the fly to the height of a user's browser window regardless if the resize it, have Firebug open, use a unique resolution or just have a really, really weird browser!

Let's take a look at what the end results should look like:

CSS Footer

To make this happen, let's get our HTML structure in place first:

<div id="page">
 
      <div id="header"> </div>
 
      <div id="main"> </div>
 
      <div id="footer"> </div>
 
</div>

It's pretty simple so far ... Just a skeleton of a web page. The page div contains ALL elements and is immediately below the

tags in the page code hierarchy. The header div is going to be our top content, the main div will include all of our content, and the footer div is all of our copyrights and footer links.

Let's start by coding the CSS for the full page:

Html, body {
      Padding: 0;
      Margin: 0;
      Height: 100%;
}

Adding a 100% height allows us to set the height of the main div later. The height of a div can only be as tall as the parent element encasing it. Now let's see how the rest of our ids are styled:

#page {
      Min-height: 100%;
      position:relative;
}
 
#main {
      Padding-bottom: 75px;   /* This value is the height of your footer */
}
 
#footer {
      Position: absolute;
      Width: 100%;
      Bottom: 0;
      Height: 75px;  /* This value is the height of your footer */
}

These rules position the footer "absolutely" at the bottom of the page, and because we set #page to min-height: 100%, it ensures that #main is exactly the height of the browser's viewing space. One of the best things about this little trick is that it's compliant with all major current browsers — including Firefox, Chrome, Safari *AND* Internet Explorer (after a little tweak). For Internet Explorer to not throw a fit, we need concede that IE doesn't recognize min-height as a valid property, so we have to add Height: 100%; to #page:

#page {
      Min-height: 100%;  /* for all other browsers */
      height: 100%;  /* for IE */
      position:relative;
}

If the user does not have a modern, popular browser, it's still okay! Though their old browser won't detect the magic we've done here, it'll fail gracefully, and the footer will be positioned directly under the content, as it would have been without our little CSS trick.

I can't finish this blog without mentioning my FAVORITE perk of this trick: Should you not have a specially designed mobile version of your site, this trick even works on smart phones!

-Cassandra

October 17, 2012

Tips and Tricks - jQuery Select2 Plugin

Web developers have the unique challenge of marrying coding logic and visual presentation to create an amazing user experience. Trying to find a balance between those two is pretty difficult, and it's easy to follow one or the other down the rabbit hole. What's a web developer to do?

I've always tried to go the "work smarter, not harder" route, and when it comes to balancing functionality and aesthetics, that usually means that I look around for plugins and open source projects that meet my needs. In the process of sprucing up an form, I came across jQuery Select2, and it quickly became one of my favorite plugins for form formatting. With minimal scripting and little modification, you get some pretty phenomenal results.

We've all encountered drop-down selection menus on web forms, and they usually look like this:

Option Select

Those basic drop-downs meet a developer's need for functionality, but they aren't winning any beauty pageants. Beyond the pure aesthetic concerns, when a menu contains dozens (or hundreds) of selectable options, it becomes a little unwieldy. That's why I was so excited to find Select2.

With Select2, you can turn the old, plain, boring-looking select boxes into beautiful, graceful and more-than-functional select widgets:

Pretty Option Select

Not only is the overall presentation of the data improved, Select2 also includes an auto-complete box. A user can narrow down the results quickly ad easily, and if you've got some of those endlessly scrolling select boxes of country names or currencies, your users will absolutely notice the change (and love you for it).

What's even sexier than the form facelift is that you can add the plugin to your form in a matter of minutes.

After we download Select2 and upload it to our box, we add our the jQuery library and scripts to the <head> of our document:

<script src="jquery.js" type="text/javascript"></script> 
<script src="select2.js" type="text/javascript"></script>

For the gorgeous styling, we'll also add Select2's included style sheet:

<link href="select2.css" rel="stylesheet"/>

Before we close our <head> tag, we invoke the Select2 function:

<script>
$(document).ready(function() { $("#selectPretty").select2(); });
</script>

At this point, Select2 is locked and load, and we just have to add the #selectPretty ID to the select element we want to improve:

<select id="selectPretty">
<option value="Option1">Option 1</option>
<option value="Option2">Option 2</option>
<option value="Option3">Option 3</option>
<option value="Option4">Option 4</option>
</select>

Notice: the selectPretty ID is what we defined when we invoked the Select2 function in our <head> tag.

With miniscule coding effort, we've made huge improvements to the presentation of our usually-boring select menu. It's so easy to implement that even the most black-and-white coding-minded web developers can add some pizzazz to their next form without having to get wrapped up in styling!

-Cassandra

September 26, 2012

Tips and Tricks - jQuery Lazy Load Plugin

In the late 90's, web pages presented their information in a relatively structured fashion, with little concern on how "pretty" the content looked. To a certain extent, that was a result of available technology and resources being a little more limited, but much of the reason was probably because we had no idea what was possible. We've come a long way, my friend. These days, it's tough to spend an hour online without coming across a gorgeous web site with huge animations, a pallet of every color possible, full-width backgrounds and high definition detail.

Those sites may be aesthetically pleasing, but they can be a big pain from a developer's perspective.

How much load does all of that stuff put on the server every time that web page is visited? As developers, it's our job to think about both what the visitor sees AND the visitor's experience in seeing it. Even the most beautiful sites will be ignored if a page takes too long to load. We spend hours optimizing every detail so users can fluidly browse without having to wait. It was in one of these optimization sessions that I discovered "lazy load."

To be honest, I wasn't too fond of the word "lazy" in the name, and I especially wasn't fond of having to explain to my boss that *I* wasn't being lazy ... The jQuery plugin is *named* "Lazy Load." Lazy Load effectively allows large pieces of content to stay in the backlog until they're needed. To give you an example of what that looks like, let's say you have a website with three humungous images, but they're all in different locations. Instead of pushing the entire load onto the user when they first land on your page, we can break them up and have them load only when the user goes to view them. We're not reducing the size of the web page; we're merely helping it work smarter.

Without Lazy Load, a normal web page loads each item when its page is visited. If a website has videos, music, images and some neat user interactivity applications, each of those items will load at the same time:

Lazy Load Illustration

If you take into consideration how large each of those items are, you can sense the problem. The user only has so much bandwidth to load these items, and something's gotta give. Usually, it means long loading times. We can't control how fast each user's ISP is, but we can reorder our items and let Lazy Load help us prioritize items and load the page more efficiently.

After we snag Lazy Load on Github (jquery.lazyload.js), we put our jQuery scripts in the <head> of our page:

<script src="jquery.js" type="text/javascript"></script> 
<script src="jquery.lazyload.js" type="text/javascript"></script>

Now that the plugin is available to us, we need to determine what we want to load lazily. Images are probably one of the most bothersome page elements, so let's apply Lazy Load to the images we load in the belazy class. In the <head> of your page (or in the footer if you prefer your JavaScript entries there), you'll add:

<script type="text/javascript">$("img.belazy").lazyload();</script>

As a result of that function, all image tags with a class of belazy will have Lazy Load run on them. This helps us ensure that we're not loading ALL of our images lazily. Now we need to choose which images we want to apply Lazy Load to.

Let's say the image tag of the largest image on one of our page looks like this:

<img src="bighonkingimage.png"/>

To have the lazyload function apply to it, we just have to make a couple tweaks:

<img class="belazy" src="bighonkingimage.png" data-original="bighonkingimage.png"/>

We added class="belazy" to trigger the lazyload function, and we added data-original="bighonkingimage.png" to line up with the formatting required by the newest version of Lazy Load (it's simply a repeat of the source).

When a user visits our page, bighonkingimage.png will load only when it's needed!

Pretty neat, eh?

-Cassandra

Subscribe to coding