Posts Tagged 'Update'

October 1, 2014

Virtual Server Update

Good morning, afternoon, evening, or night, SoftLayer nation.

We want to give you an update and some more information on maintenance taking place right now with SoftLayer public and private node virtual servers.

As the world is becoming aware today, over the past week a security risk associated with Xen was identified by the Xen community and published as Xen Security Advisory 108 (XSA-108).

And as many are aware, Xen plays a role in our delivery of SoftLayer virtual servers.

Eliminating the vulnerability requires updating software on host nodes, and that requires downtime for the virtual servers running on those nodes.

Yeah, that’s not something anyone likes to hear. But customer security is of the utmost importance to us, so not doing it was not an option.

As soon as the risk was identified, our systems engineers and technology partners have been working nonstop to prepare the update.

On Sunday we notified every customer account that would be affected that we would have emergency maintenance in the middle of this week, and updated that notice each day.

And then yesterday we published that the maintenance would begin today at 3pm UTC, with a preliminary order of how the maintenance would roll out across all of our data centers.

We are updating host nodes data center by data center to complete the emergency maintenance as quickly as possible. This approach will minimize disruption for customers with failover infrastructure in multiple data centers.

The maintenance is under way and SoftLayer customers can follow it, live, on our forum at http://sftlyr.com/xs101.

-@SoftLayer

May 10, 2013

Understanding and Implementing Coding Standards

Coding standards provide a consistent framework for development within a project and across projects in an organization. A dozen programmers can complete a simple project in a dozen different ways by using unique coding methodologies and styles, so I like to think of coding standards as the "rules of the road" for developers.

When you're driving in a car, traffic is controlled by "standards" such as lanes, stoplights, yield signs and laws that set expectations around how you should drive. When you take a road trip to a different state, the stoplights might be hung horizontally instead of vertically or you'll see subtle variations in signage, but because you're familiar with the rules of the road, you're comfortable with the mechanics of driving in this new place. Coding standards help control development traffic and provide the consistency programmers need to work comfortably with a team across projects. The problem with allowing developers to apply their own unique coding styles to a project is the same as allowing drivers to drive as they wish ... Confusion about lane usage, safe passage through intersections and speed would result in collisions and bottlenecks.

Coding standards often seem restrictive or laborious when a development team starts considering their adoption, but they don't have to be ... They can be implemented methodically to improve the team's efficiency and consistency over time, and they can be as simple as establishing that all instantiations of an object must be referenced with a variable name that begins with a capital letter:

$User = new User();

While that example may seem overly simplistic, it actually makes life a lot easier for all of the developers on a given project. Regardless of who created that variable, every other developer can see the difference between a variable that holds data and one that are instantiates an object. Think about the shapes of signs you encounter while driving ... You know what a stop sign looks like without reading the word "STOP" on it, so when you see a red octagon (in the United States, at least), you know what to do when you approach it in your car. Seeing a capitalized variable name would tell us about its function.

The example I gave of capitalizing instantiated objects is just an example. When it comes to coding standards, the most effective rules your team can incorporate are the ones that make the most sense to you. While there are a few best practices in terms of formatting and commenting in code, the most important characteristics of coding standards for a given team is consistency and clarity.

So how do you go about creating a coding standard? Most developers dislike doing unnecessary work, so the easiest way to create a coding standard is to use an already-existing one. Take a look at any libraries or frameworks you are using in your current project. Do they use any coding standards? Are those coding standards something you can live with or use as a starting point? You are free to make any changes to it you wish in order to best facilitate your team's needs, and you can even set how strict specific coding standards must be adhered to. Take for example left-hand comparisons:

if ( $a == 12 ) {} // right-hand comparison
if ( 12 == $a ) {} // left-hand comparison

Both of these statements are valid but one may be preferred over the other. Consider the following statements:

if ( $a = 12 ) {} // supposed to be a right-hand comparison but is now an assignment
if ( 12 = $a ) {} // supposed to be a left-hand comparison but is now an assignment

The first statement will now evaluate to true due to $a being assigned the value of 12 which will then cause the code within the if-statement to execute (which is not the desired result). The second statement will cause an error, therefore making it obvious a mistake in the code has occurred. Because our team couldn't come to a consensus, we decided to allow both of these standards ... Either of these two formats are acceptable and they'll both pass code review, but they are the only two acceptable variants. Code that deviates from those two formats would fail code review and would not be allowed in the code base.

Coding standards play an important role in efficient development of a project when you have several programmers working on the same code. By adopting coding standards and following them, you'll avoid a free-for-all in your code base, and you'll be able to look at every line of code and know more about what that line is telling you than what the literal code is telling you ... just like seeing a red octagon posted on the side of the road at an intersection.

-@SoftLayerDevs

August 8, 2012

No iFrames! Dynamically Resize Divs with jQuery.

It's no secret that iframes are one of the most hated methods of web page layouts in the web development world — they are horrible for SEO, user experience and (usually) design. I was recently charged with creating a page that needed functionality similar to what iframes would normally provide, and I thought I'd share the non-iframe way I went about completing that project.

Before I get into the nitty-gritty of the project, I should probably unpack a few of the reasons why iframes are shunned. When a search engine indexes a page with iframes, each iframe is accurately recorded as a separate page — iframes embed the content of one we page inside of another, so it makes sense. Because each of those "pages" is represented in a single layout, if a user wanted to bookmark your site, they'd probably have a frustrating experience when they try to return to your site, only to find that they are sent directly to the content in one of the frames instead of seeing the entire layout. Most often, I see when when someone has a navigation bar in one frame and the main content in the other ... The user will bookmark the content frame, and when they return to the site, they have no way to navigate the pages. So what's a developer to do?

The project I was tasked with required the ability to resize only certain sections of a page, while asynchronously shrinking another section so that the entire page would always stay the same size, with only the two sections inside changing size.

Let's look at an example with two divs, side by side on a web page:

iFrame Tutorial

One div will contain a navigation menu to jump to different pages of the website (#sidebar), and the second div will contain all the content for that page (#content). If some of the elements in #sidebar are too long to read with the default width of the div, we want to let the user freely resize the two divs without changing the width of the page.

Our task is straightforward: When #sidebar expands in width, also expand the navigation and shrink #content along with the main content inside #content. If #sidebar shrinks, the navigation, #content and main content would respond accordingly as well:

iFrame Tutorial

It's a relatively easy concept to do with iFrames ... But then you remember that iframes are no longer cool (yes, there was a time long ago when iframes were cool). I decided to turn to my favorite alternative — jQuery — and the fix was actually a lot easier than I expected, and it worked beautifully. Let's run through a step-by-step tutorial.

1. HTML

Lay out your two divs:

<div id="sidebar"> 
<div class="sidebar-menu">
<!-- all your sidebar/navigational items go here -->
</div>
</div>
<div id="content">
<!-- all your main content goes here -->
</div>

2. CSS

Style your divs:

#sidebar {
       width: 49%;
}
#content {
width: 49%;
        float: left;
}

3. jQuery

Now that we have our two divs side by side, let's apply some jQuery magic. To do that, Let's include our jQuery files in the <HEAD> of our document:

<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" rel="stylesheet" type="text/css"/>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>

Now that we have the necessary scripts, we can write our function:

<script type="text/javascript">
  $(document).ready(function() {
    $( "#sidebar" ).resizable({      
    });
    $("#sidebar ").bind("resize", function (event, ui) {
            var setWidth = $("#sidebar").width();
            $('#content).width(1224-setWidth);
            $('.menu).width(setWidth-6);
        });
  });
</script>

I know that might seem like an intimidating amount of information, so let's break it down:

   $( "#sidebar" ).resizable({      
   });

This portion simply makes the div with the ID of "sidebar" resizable (which accomplishes 33% of what we want it to do).

   $("#sidebar ").bind("resize", function (event, ui) {

By using the .bind, we are able to trigger other events when #sidebar is called.

            var setWidth = $("#sidebar").width();
            $('#content).width(1224-setWidth);

This is where the magic happens. We're grabbing the current width of #sidebar and subtracting it from the width you want your site to be. This code is what keeps your page stays the same width with only the divs changing sizes.

            $('.menu).width(setWidth-6);

This part of the code that expands the contents in the navigation along with #sidebar.

You can see a working example of iframe-like functionality with jQuery here: http://jqueryui.com/demos/resizable/

The only part you won't find there is the trick to adjust a corresponding div's size to make it grow/shrink with the first ... I had a heck of a time searching that on the web, so hopefully this quick tutorial will help other developers who might be searching for this kind of functionality!

- Cassandra

June 5, 2012

New SoftLayer.com Design: Build the Future

If you've been reading the SoftLayer Blog via an RSS feed or if you find yourself navigating directly to the portal to manage your SoftLayer account, you might not have noticed that the our main website has been updated again — and in dramatic fashion. Last fall we gave the site a slight refresh ... This time, we did a total rework.

We took the site in a new visual direction, with graphics and messaging to complement our mantra of customers using our platform to create their vision — to build the future.

SoftLayer Homepage

The new look — referred to as "SoftLayer at Night" by my fellow SoftLayer developer friend, Seth Thornberry — was designed to reflect our core identity, and it retires the faithful red, white and grey theme that has served us well for more than three years. The new style has received rave reviews from customers, partners and employees, and even if there has been some criticism — everyone has an opinion nowadays — we can generally chalk it up to people simply not liking change.

Highlights of the Redesign:

  • A dramatic new home page design, including visually rich "hero images" (where you see "The InnerLayer" heading if you're reading this on the SoftLayer Blog)
    SoftLayer Homepage Hero Image
  • Expanded main navigation menus at the top of each page
    SoftLayer Homepage Top Nav
  • A new lower-order navigation system on the left of all content pages
  • SoftLayer Homepage Side Nav

  • [For typographically inclined] The new design also leverages web fonts functionality to incorporate "Benton Sans," the corporate font used in print, interactive and other marketing communications.
    SoftLayer Homepage Side Nav

The new design was executed in-house, and our workflow was pretty traditional ... We like to roll up our sleeves. Page templates were created as PSD files and then hand-coded in HTML, PHP, JavaScript and CSS on top of the same framework we use for the SoftLayer Customer Portal.

During the development process, we used our new GIT code repository to facilitate the merging of all of our code onto our staging server. Since it was our first time to use GIT in a major way, there was a bit of a learning curve. The first few merges had to be reworked after finding a few errors in commit messages, but after we got a little practice, the subsequent merges went off without a hitch. The final staging merge was a breeze, and given the struggles we've had with SVN in past projects, this was a huge relief.

When it came time for the design's official launch, we ran into a hiccup related to our automatic regression testing system and problems with cached CSS files, but these issues were quickly resolved, and the new-look SoftLayer.com went live.

It took a lot of hard work from (and a lot of caffeine for) a number of people to get the new site out the door, so I'd like to make sure credit goes where it's due. Our lead designer Carlos ("Los") Ruiz did a majority of the design work, and the implementation of that design fell to Dennis Dolliver (Website Developer), Charles King (SEO Manager) and me. I should also send a shout-out to the entire marketing team who jumped in to help to proof content, test pages and keep everyone sane.

What do you think of the new design? Stay tuned for more website improvements and additions!

-Brad

March 28, 2012

SoftLayer Mobile on WP7 - Live Tiles and Notifications

In the past couple of months we've added some really cool Windows Phone 7.1 (Mango) features to the Softlayer Mobile application, including Lives Tiles and Notifications. While a basic Live Tile implementation is relatively easy, there's a fair amount of coding and architecture requirements to facilitate cooler Live Tile functionality and Notifications ... And we're all about doing things cooler.

Live Tiles is a such great feature of Windows Phone 7 largely because it gives the developer much more control over the device's user experience when compared to other mobile OSes. Live Tile functionality in its simplest form can be just 'Pinning' the Tile to the Start Menu with a deep link to a specific location within the application so that when clicked the user is taken to that location within the app. This can save the user a lot of time in having to navigate deep into an app if they know where they want to go. More advanced features of Live Tiles include programmatically giving the Tile a custom background image and displaying a notification message on the background when the Tile flips.

Adding a Live Tile

To add a Live Tile, a user simply clicks and holds the module they'd like to pin to the start menu. When the context menu appears, the user can select 'pin as tile,' and he or she will be taken to the Start page where the new Tile is displayed:

SoftLayer on Windows Phone 7

The Magic Behind Sending Notifications

We really wanted to be able to notify a user when a notable event happens on his or her account (new ticket is created/updated, when a bill is overdue, etc.), and Windows Phone 7 provides some pretty phenomenal functionality in that area ... I wouldn't be surprised if other big mobile OSes copy Windows Phone 7's notifications in the future. When it comes to implementing notifications in SoftLayer Mobile, we needed to handle a few things:

  1. Get a Unique App+User Channel URI from Windows Push Notification Server
  2. Register URI & Channel Name with the Softlayer Registration Service (WCF we created)
  3. Store this URI, Channel Name and the user's Account in a DB
  4. Periodically poll for new tickets or updates (since we don't have a mechanism yet that can 'push' this alert when any notification event is triggered)
  5. Send Notification (whether it's a Toast or Tile notification) to device via the unique URI & Channel name.

I was going to include the architecture diagram here showing this relationship and process, but the designer sitting next to me told that nobody wants to see that.

What do the Numbers on the Tiles Mean?

We wanted to make our Tiles show information that the user would find useful, so we send the account's total unread ticket count to the main app's Tile, and we display the account's unread ticket update count on the "Ticket" Tile we pinned to the Start screen:

SoftLayer on Windows Phone 7

Why is the Tile Flipping?

We also have the ability to have the Tiles flip over and show an image or text on the TileBack, so we use that to explain the number shown on the Tile (so you don't have to remember):

SoftLayer on Windows Phone 7

What is a Toast Notification?

A Toast Notification is a message that pops up on the screen for 10 seconds. If the user clicks on it, he or she is taken to the application, but if the notification is not clicked, it will disappear. Here is the Toast Notification that is sent to a user when a ticket is updated if they subscribe to Toast Notifications:

SoftLayer on Windows Phone 7

How do I Enable Notifications in SoftLayer Mobile?

To enable Live Tiles, all you have to do is turn on the 'Use Push Notifications' option on the Settings view.

SoftLayer on Windows Phone 7

You'll be asked if you'd like to receive Toast Notifications, and if you click 'OK,' you'll start getting them:

SoftLayer on Windows Phone 7

We Love Feedback and Requests!

Now that you have Live Tiles & Notifications in Softlayer Mobile for WP7 (and coming soon for iPhone & Android), what else would you like to see in the mobile clients?

-Erik

January 24, 2012

SOPA + PIPA: "Stopped" Now. What's Next?

The Internet community's rallying cry has been heard by the United States Congress and Senate. Last week, we reported that SOPA was temporarily being put on the shelf, but now Congressman Lamar Smith has pulled the bill altogether, stating that "until there is wider agreement on a solution," the bill will not be reintroduced.

On the Protect IP Act (PIPA) front, Senator Harry Reid also announced late last week that he's postponed the schedule vote on the legislation that was originally slated for today. In a statement released on Friday, Senator Reid went on to say:

"There is no reason that the legitimate issues raised by many about this bill cannot be resolved. Counterfeiting and piracy cost the American economy billions of dollars and thousands of jobs each year, with the movie industry alone supporting over 2.2 million jobs. We must take action to stop these illegal practices. We live in a country where people rightfully expect to be fairly compensated for a day’s work, whether that person is a miner in the high desert of Nevada, an independent band in New York City, or a union worker on the back lots of a California movie studio."

As a hosting provider, we wholeheartedly agree that counterfeiting and piracy are a primary focus, and our opposition to the bills drafted to protect copyright holders and intellectual property owners is in response to the verbiage in the legislation and the potential dangers in the proposed means of enforcement. Having SOPA pulled and PIPA put on the shelf is an important step, but it's not exactly a time to celebrate. The Internet community needs to remain vigilant and engaged with Congress to help create legislation that reinforces the freedom of the Internet and protects the rights of intellectual property owners.

These bills have not been forgotten by the members who introduced them for consideration and vote, and they will likely evolve into new proposals with the same intent.

Our legal team and management team will maintain our steadfast opposition to these two bills in their current form, and as similar legislation is proposed, we will fill you in on what's being considered. In the meantime, take a few minutes to visit http://savehosting.org/ and TechAmerica to learn more about what our industry is concerned about.

-@toddmitchell

January 10, 2012

Web Development - HTML5 - Custom Data Attributes

I recently worked on a project that involved creating promotion codes for our clients. I wanted to make this tool as simple as possible to use and because this involved dealing with thousands of our products in dozens of categories with custom pricing for each of these products, I had to find a generic way to deal with client-side form validation. I didn't want to write custom JavaScript functions for each of the required inputs, so I decided to use custom data attributes.

Last month, we started a series focusing on web development tips and tricks with a post about JavaScript optimization. In this installment, we're cover how to use HTML5 custom data attributes to assist you in validating forms.

Custom data attributes for elements are "[attributes] in no namespace whose name starts with the string 'data-', has at least one character after the hyphen, is XML-compatible, and contains no characters in the range U+0041 to U+005A (LATIN CAPITAL LETTER A to LATIN CAPITAL LETTER Z)." Thanks W3C. That definition is bookish, so let's break it down and look at some examples.

Valid:

<div data-name="Philip">Mr. Thompson is an okay guy.</div>
<a href="softlayer.com" data-company-name="SoftLayer" data-company-state="TX">SoftLayer</a>
<li data-color="blue">Smurfs</li>

Invalid:

// This attribute is not prefixed with 'data-'
    <h2 database-id="244">Food</h2>
 
// These 2 attributes contain capital letters in the attribute names
    <p data-firstName="Ashley" data-lastName="Thompson">...</p>
 
// This attribute does not have any valid characters following 'data-'
    <img src="/images/pizza.png" data-="Sausage" />

Now that you know what custom data attributes are, why would we use them? Custom attributes allow us to relate specific information to particular elements. This information is hidden to the end user, so we don't have to worry about the data cluttering screen space and we don't have to create separate hidden elements whose purpose is to hold custom data (which is just bad practice). This data can be used by a JavaScript programmer to many different ends. Among the most common use cases are to manipulate elements, provide custom styles (using CSS) and perform form validation. In this post, we'll focus on form validation.

Let's start out with a simple form with two radio inputs. Since I like food, our labels will be food items!

<input type="radio" name="food" value="pizza" data-sl-required="food" data-sl-show=".pizza" /> Pizza
<input type="radio" name="food" value="sandwich" data-sl-required="food" data-sl-show="#sandwich" /> Sandwich
<div class="hidden required" data-sl-error-food="1">A food item must be selected</div>

Here we have two standard radio inputs with some custom data attributes and a hidden div (using CSS) that contains our error message. The first input has a name of food and a value of pizza – these will be used on the server side once our form is submitted. There are two custom data attributes for this input: data-sl-required and data-sl-show. I am defining the data attribute data-sl-required to indicate that this radio button is required in the form and one of them must be selected to pass validation. Note that I have prefixed required with sl- to namespace my data attribute. required is generic and I don't want to have any conflicts with any other attributes – especially ones written for other projects! The value of data-sl-required is food, which I have tied to the div with the attribute data-sl-error-food (more on this later).

The second custom attribute is data-sl-show with a selector of .pizza. (To review selectors, jump back to the JavaScript optimization post.) This data attribute will be used to show a hidden div that contains the class pizza when the radio button is clicked. The sandwich radio input has the same data attributes but with slightly different values.

Now we can move on to our HTML with the hidden text inputs:

<div class="hidden pizza">
    Pizza type: <input type="text" name="pizza" data-sl-required="pizza" data-sl-depends="{&quot;type&quot;:&quot;radio&quot;,&quot;name&quot;:&quot;food&quot;,&quot;value&quot;:&quot;sandwich&quot;}" />
    <div class="hidden required" data-sl-error-pizza="1">The pizza type must not be empty</div>
</div>
 
<div class="hidden" id="sandwich">
    Sandwich: <input type="text" name="sandwich" data-sl-required="sandwich" data-sl-depends="{&quot;type&quot;:&quot;radio&quot;,&quot;name&quot;:&quot;food&quot;,&quot;value&quot;:&quot;sandwich&quot;}" />
    <div class="hidden required" data-sl-error-sandwich="1">The sandwich must not be empty</div>
</div>

These are hidden divs that contain text inputs that will be used to input more data depending on the radio input selected. Notice that the first outer div has a class of pizza and the second outer div has an id of sandwich. These values tie back to the data-sl-show selectors for the radio inputs. These text inputs also contain the data-sl-required attribute like the previous radio inputs. The data-sl-depends data attribute is a fun attribute that contains a JSON-encoded object that's been run through PHP's htmlentities() function. For readability, the data-sl-depends values contain:

{"type":"radio","name":"food","value":"pizza"}
{"type":"radio","name":"food","value":"sandwich"}

This first attribute says that our text input “depends” on the radio input with the name food and value pizza to be visible and selected in order to be processed as required. You can just imagine the possibilities of combinations you can create to make very custom functionality with very generic JavaScript.

Now we can examine our JavaScript to make sense of all these custom data attributes. Note that I'll be using Mootools' syntax, but the same can fairly easily be accomplished using jQuery or your favorite JavaScript framework. I'm going to start by creating a DataForm class. This will be generic enough so that you can use it in multiple forms and it's not tied to this specific instance. Reuse is good! To have it fit our needs, we're going to pass some options when instantiating it.

new DataForm({
    ...,
    dataAttributes: {
        required: 'data-sl-required',
        errorPrefix: 'data-sl-error',
        depends: 'data-sl-depends',
        show: 'data-sl-show'
    }
});

As you can see, I'm using the data attribute names from our form as the options – this will allow you to create your own data attribute names depending on your uses. We first need to make our hidden divs visible whenever our radio buttons are clicked – we'll use our initData() method for that.

initData: function() {
    var attrs = this.options.dataAttributes,
        divs = [];
 
    $$('input[type=radio]['+attrs.show+']').each(function(input) {
        var div = $$(input.get(attrs.show));
        divs.push(div);
        input.addEvent('change', function(e) {
            divs.each(function(div) { div.hide(); });
            div.show();
        });
    });
}

This method grabs all the radio inputs with the show attribute (data-sl-show) and adds an onchange event to each of them. When a radio input is checked, it first hides all the divs, and then shows the div that's associated with that radio input.

Great! Now we have our text inputs showing and hiding depending on which radio button is selected. Now onto the actual validation. First, we'll make sure our required radio inputs are checked:

$$('input[type=radio]['+attrs.required+']:not(:checked)').each(function(input) {
    var name = input.get('name');
    checkError(name, isRadioWithNameSelected(name))
});

This grabs all the unchecked radio inputs with the required attribute (data-sl-required) and checks to see if any radio with that same name is selected using the function isRadioWithNameSelected(). The checkError() function will show or hide the error div (data-sl-error-*) depending if the radio is checked or not. Don't worry - you'll see how these functions are implemented in the JSFiddle below.

Now we can check our text inputs:

$$('input[type=text]['+attrs.required+']:visible').each(function(input) {
    var name = input.get('name'),
        depends = input.get(attrs.depends),
        value = input.get('value').trim();
 
    if (depends) {
        depends = JSON.encode(depends);
        switch (depends.type) {
            case 'radio':
                if (depends.name &amp;&amp; depends.value) {
                    var radio = $$('input[type=radio][name="'+depends.name+'"][value="'+depends.value+'"]:checked');
                    if (!radio) {
                        checkError(input.get(attrs.required), true);
                        return;
                    }
                }
                break;
        }
    }
 
    checkError(name, value!='');
});

This obtains the required and visible text inputs and determines if they are empty or not. Here we look at our depends object to grab the associated radio inputs. If that radio is checked and the text input is empty, the error message appears. If that radio is not checked, it doesn't even evaluate that text input. The depends.type is in a switch statement to allow for easy expansion of types. There are other cases for evaluating relationships ... I'll let you come up with more for yourself.

That concludes our usage of custom data attributes in form validation. This really only touched upon the very tip of the iceberg. Data attributes allow you – the creative developer – to interact in a new, HTML-valid way with your web pages.

Check out the working example of the above code at jsfiddle.net. To read more on custom data attributes, see what Google has to say. If you want to see really cool functionality that uses data attributes plus so much more, check out Aaron Newton's Behavior module over at clientcide.com.

Happy coding!

-Philip

December 12, 2011

Web Development - JavaScript Optimization

So you have a fast website. You've optimized your database queries and you're using the most efficient page caching mechanisms. The users of your site are pretty satisfied, but you want just a little bit more. How can you push your site to the next level by making sure you've included all the optimizations you can to get the fastest speed possible?

Optimize your JavaScript.

You might not be concerned with optimizing you code because newer browsers have gotten significantly faster at processing JavaScript. But like all other programming languages, there are minor tweaks you can make that provide a significant performance gain. Let's take a look at a few of the ways you can be certain that you're getting the most out of your client-side JavaScript code.

JavaScript in External Files
The first optimization is to write your JavaScript in external files. By using external files, your browser is able to cache your code. This prevents users from needing to re-download your JavaScript during every page load and potentially during every AJAX request. When a browser visits any website, it checks the src attribute in the <script> tags and then determines if it already has a copy of that file on your computer. If it does, it won't spend wasteful time re-downloading the exact same code. If you include your code directly in your HTML within <script> tags, it will download that same code each time so that it can be processed. Save those precious bytes!

Minification
Now that you're putting your code in external files, your next goal is to reduce the amount of time it takes to initially download that code so that it can be cached by the browser. This is where minification comes into play. Minification (or minimization) is the process of removing all unnecessary characters from source code (without changing its functionality). Essentially this means you'll remove whitespace characters and comments.

Unless you like to torture yourself (and those who follow your work), you probably write code that's pretty readable. This includes splitting code up between multiple lines, indenting your code with spaces or tabs, and writing comments that explain some esoteric portion of code. All these items are not important to the JavaScript engine because it will just ignore them, but it still takes time to download these extra bytes that will never get used.

Luckily for you, you don't have to spend time creating the tool that will remove these unneeded characters. There are several good tools out there that will minify your code, and I recommend YUI Compressor. This tool can reduce your code by up to 60% (depending upon how efficiently you write your code). In addition to removing all the unnecessary characters, YUI Compressor will rewrite your code to use smaller variable names. If you have a local variable in a function called var myDescriptiveVariable, the compressor will rename it to var a. We just took our 21-character variable name down to 1 character! If this variable is used in 10 places, we've trimmed 200 characters with this one variable, and this happens for every local variable in your script! That's a lot of bytes saved.

If you're paying close attention, the key takeaway you'll notice is that using local variables (compared to global variable that don't get minified) is one great way to reduce the size of your code after minification occurs.

Initial Page Load Operations
Now that your code has been minified, let's take a look at initial page load operations. Since some JavaScript operations are synchronous and will halt other browser processing, we want to make sure we don't slow down the page when the user is trying to perform an action. There are two things we can do to improve initial page loading performance. First, reduce the amount of code you actually invoke on page load (or when the DOM is ready for interaction using Mootools' domready event, jQuery's document ready event or your favorite framework's equivalent). Second, implement lazy-loading techniques. For example, instead of adding all your events to all the elements on the page initially, wait for user interaction or some other process to add the events. Let's look at a few specific examples so you can see what I mean. Note: the code samples are using Mootools syntax.

Before:

var comments = $('.articles > div.comments');
$('showComments').addEvent('click', function() { comments.show(); });

After:

$('showComments').addEvent('click', function() { $('.articles > div.comments').show(); });

While this may improve initial page load, each time we click on showComments, we have to parse the DOM (Document Object Model) to find all the comments, and this is not a cheap operation. The key here is test your own code and determine with each scenario which way is faster and which will keep your users the happiest. Just realize that on demand operations may be more acceptable to users than having to wait for the page to load. You be the judge!

Code Caching
We discussed file caching before, but what about code caching? We need to determine which operations will benefit the most from caching. The two items I will focus on are loops and DOM interactions. Loops can be costly because you may be performing unnecessary actions within each iteration.

Before:

for (var i=0; i<$$('.toggle').length; i++) {
 var el = new Element('div.something', {
 html: $$('.toggle')[i].get('text')
 });
 el.inject($('content'));
}

After:

var i = 0,
 els = $$('.toggle'),
 length = els.length,
 container = new Element('div');
 
for (i=0; i<length; i++) {
 new Element('div.something', {
 html: els[i].get('text')
 }).inject(container);
}
 
container.inject($('content'));

The "Before" loop is inefficient because we are querying the DOM three separate times to get the elements we need (twice for .toggle elements and once for the #content element), and we are having to determine the length property of that collection of elements during each iteration. In our case, the length won't change, so we only need to find it one time. Finally, during each iteration, we add a new element to the #content div, and this causes a redraw of the page. DOM manipulation and redrawing can be expensive, so let's look at how the second method is so much more efficient.

We start by caching our DOM elements so we only have to pull them once and get the length property of those elements only once. We've also created an element which will be used to contain all our new elements. Since the container has not been added to the DOM yet, we can add and remove from it without having to worry about the expensive redraw of the page. Once all our elements have been added to the container, we then inject the container into the #content div. Since this is only happening once, we have significantly improved performance.

Selector Efficiency
The last optimization technique I'll review is selector efficiency. Selectors are used to grab specific elements from the document in order to interact with them in your code. It's very possible to write poor-performing selectors. Some selectors to avoid:

$$('*')

This will grab all the elements in your document. If you have a huge document, this could take a while. You better not be using this selector in a loop!

$$('[data-some-attribute]')

This selector is inefficient because it has to look for this data attribute within every element in the document. If there are thousands of elements and each has several data attributes, you should just go get some coffee.

$$('body .person:nth-child(3n+1) .category p span.title')

This selector is fairly complicated. The reason this can be inefficient is because it may have to unnecessarily inspect many elements to get to the one(s) it needs. Determine if you can simplify the selector by being more specific and using an id to get to elements or even consider slightly modifying your HTML so that it's easier to create efficient selectors.

There are plenty of other techniques that will help improve the speed and efficiency of your JavaScript, but these are a good start and should help make you and your users happy. Remember that DOM interactions are slow and expensive, so do what you can to reduce chatting back and forth with the document. Check your loops and minify your code, and your users will surely return.

Happy coding!

-Philip

November 27, 2011

Change is Good

We are closing down 2011 and beginning to prepare for a new year that is bound to be full of exciting changes and growth for our company, and in the midst of the calendar change, I'm reminded that my two-year anniversary of becoming a SLayer will be here soon too. Has time flown?! So many things have changed in the past two years, so I thought it would be fun to think about some things that have changed since my first day on the job.

To give you an idea of how things have changed in our office alone:

  • Our last office had two kitchens and two microwaves. At our Alpha headquarters, we have six kitchens with twelve microwaves. It's so nice that I don't have to wait in line to heat up my lunches anymore.
  • In the Alpha office's main kitchen, we have a Sonic ice machine ... if you aren't from the southern part of the US, you might not know why this is so cool, but if you've had a Cherry Limeade delivered to your car, you'll know exactly what I'm talking about.
  • Previously, we had to share a bathroom with a few other companies. Now we're the only company in our building, and there are three sets bathrooms just for us.
  • When I started we had four conference rooms. Now we have sixteen ... Not even counting the conference rooms in our other locations!

Speaking of "other locations," it'd probably be worthwhile to talk about about a few of bigger changes that happened outside of the walls of the Dallas office.

  • When I started, SoftLayer was run by around 160 SLayers. Now we're over 650!
  • In January 2010, we were on one continent. Now we've added Asia and Europe presences to our foundation in North America.
  • Those international presences have helped us expand our data center footprint. We had three data centers (Dallas, Seattle and Washington, D.C.) when I started. Now we have thirteen data centers around the world, and in addition to those three markets, we now have SLayers in Houston, San Jose, Singapore and Amsterdam!
  • On my first day, our marketing team consisted of three people. Now we have more than fifteen people ... and looking to hire more.
  • Two years ago, we had around 6,000 customers. Today we have more than 25,000 customers located in over 110 countries!

I've been through a headquarter move, a merger, a huge network expansion and multiple product additions, but one thing that remains the same is our dedication to providing our customers with the best on-demand hosting solution in the world... and of course having fun while we are at it!

-Summer

Categories: 
September 28, 2011

A Whole New World: SoftLayer on Windows Phone 7

As SLayers, our goal is always to bring creativity in every aspect of work we do at SoftLayer. It was not too long ago when the Interface Development team was presented with a new and exciting challenge: To develop a Windows Phone 7 Series app. Like me, many questioned whether we should tap into the market of Windows Phone OS ... What was the scope of this OS? What is the future of Windows Phone OS smartphones? The business relationship that NOKIA and Microsoft signed to produce smartphones with Windows Phone 7 OS will provide consumers with a new interface and unique features, so smartphone users are paying attention ... And we are too.

The SoftLayer Mobile world had already made huge strides with iPhone and Android based apps, so our work was cut out for us as we entered the Windows Phone 7 world. We put together a small, energetic and skilled group of SLayers who wanted to make SoftLayer proud, and I am proud to be a member of that team!

Our focus was to design and develop an application that would not only provide the portal functionality on mobile phone but also incorporate the awesome features of Windows Phone 7. Keeping all that in consideration, the choice of using an enterprise quality framework was essential. After a lot of research, we put our finger on the Microsoft's Patterns and Practices-backed Prism Framework for Windows Phone 7. The Prism Framework is a well-known and recognized name among Silverlight and Windows Presentation Framework developers, and since Windows Phone 7 is built upon the Silverlight and XNA Framework, our choice was clearly justified.

After selecting the framework, we wanted to make the whole asynchronous experience smooth while talking to SoftLayer's mobile API. That' where we met the cool kid on the block: Reactive Extensions for .NET (also known as Rx). The Rx is a library used to compose asynchronous and event-based programs. The learning curve was pretty intense for the team, but we operate under the mantra of CBNO (Challenging-But-Not-Overwhelming), so it was learning we knew would bear fruits.

The team's plan was to create an app that had the most frequently used features from the portal. The features to be showcased in the first release were to be basic but at the same time essential. The features we pinpointed were ticket management, hardware management, bandwidth and account management. Bringing these features to the phone posed a challenge, though ... How do we add a little more spice to what cold be a rather plain and basic app?

Windows Phone 7 controls came to our rescue and we utilized the Pivot and Panorama controls to design the Ticket Lists and Ticket Details. The pivot control works like a tabbed-style control that is viewable by sliding left or right. This lets us put the ticket-based-categories in a single view so users don't have to navigate back-and-forth to see different types of tickets. It also provides context-menu style navigation by holding onto the ticket item, giving an option to view or edit ticket with one tap. Here is a screen shot of pivot control in use to view tickets by categories and device list:

Win7 Phone Screen

Another achievement was made by using the panorama control. The control works like a long page with different relevant sections of similar content. This control was used to show a snap shot of a ticket, and the view displays basic ticket details, updates, attachments and any hardware attached to a ticket. This makes editing a ticket as easy as a tap! This is a screenshot of panorama control in use to view ticket detail:

Win7 Phone Screen

The device list view will help people see the dedicated and virtual devices in a pivot control giving a visual distinction. The list can be searched by tapping on the filter icon at the application bar. The filtering is search-as-you-type style and can be turned off by tapping the icon again. This screenshot shows the device list with a filtering option:

Win7 Phone Screen

To perform further hardware operations like pinging, rebooting and power cycling the server, you can use the hardware detail view as well. The bandwidth view may not be as flashy, but it's a very useful representation of a server's bandwidth information. Charting is not available with this release but will be available in the upcoming releases.

If you own a Windows Phone 7 device, go ahead and download "SoftLayer Mobile" and send us the feedback on what features you would like to see next and most importantly whether you love this app or not. We have and will always strive for excellence, and we know there's always room to improve!

-Imran

Subscribe to update