JavaScript Array Max and Equal Height Columns

February 12th, 2009

JavaScript has a Math.max function that allows you get the maximum between two numbers. That is cool, and all, but I rarely want to compare two numbers. More often, I’m looking for the maximum number of an array. For example, on a recent project, I wanted all children of an elements to be the same height. I didn’t want to deal with Faux columns and I was ok with relying on JavaScript this time.

The best way to set columns to an equal height is to just grab all the heights, get the max, and then set each element height to the max. I did a bit of search around and found an example of adding max to Array’s prototype. I wrapped that in an if statement that checks if max is currently defined, that way if max gets added to Array in the future, my version won’t conflict.

if (typeof Array.prototype['max'] == 'undefined') {
  Array.prototype.max = function() {
    return Math.max.apply({},this);
  }
}

The trick in the code above is that using apply on the built in function allows max to receive an unlimited number of arguments. This allows me to do the following:

[1,2,3].max() // => 3

In this instance (making equal height columns), I ended up with the following solution.

$.fn.equalHeightChildren = function() {
  return this.each(function() {
    var children = $(this).children();

    var tallest  = $.map(children, function(child) {
      return $(child).height();
    }).max();

    children.each(function() {
      var padding = parseInt($(this).css('padding-top')) +
                    parseInt($(this).css('padding-bottom'));
      $(this).height(tallest - padding);
    });
  });
}

I use $.map to loop through the children and return an array of their heights. At the end of map, I call max() to return the greatest height. The nice thing about this solution is that it even takes into account padding and the box model.

Logging for the Lazy

February 11th, 2009

They say that laziness is a virtue in programmers. That is a good sign for me as I am the laziest of them all. When debugging JavaScript in Firefox or Safari, I use console.log all the time. There are two things about console.log that bother me.

Firstly, it is 11 characters. When I just want to output something really quick, it really annoys me that it takes 11 characters just for the function name, not including whatever it is that I want to print out.

Secondly, console.log only takes one argument at a time. More often than not, I’m outputting the values of a few things, which means I have to type (or copy and paste) those 11 characters a lot. What I’ve started doing recently, is adding this simple log function to my projects.

function log() {
  if (window && window.console && window.console.log)
    for(var i=0, len = arguments.length; i < len; i++)
      console.log(arguments[i]);
}

This simple function allows me to do the following:

log(some_var)
log(one_var, two_var, three_var)

It is only 3 characters and allows me to print out as many objects to the console as my heart desires. Nothing fancy, but it gets the job done and saves me some time and thought.

Creating a Network Bar with jQuery

January 23rd, 2009

Network bars are making the rounds on a lot of sites. If you aren’t familiar with the term, it is usually a bar at the top of a site with links to other sites that are in the same network. Brandon, one of my friends, has a network bar on Open Soul that has links to his two other co-workers and to a few products and services they provide. Another great example is all of the sites created by Sidebar, such as My Mile Marker, Overheard.it, and Django Pluggables.

Not too long ago, I created my second tips site, BlawgTips. I wanted to drive traffic back and forth between BlawgTips and RailsTips, so I created a network bar that sits at the top of each of those. I was shocked at how easy it was. I only wanted it to be one request, so I included the styles inline in a style tag instead of calling another external stylesheet. Below is the code.

jQuery(document).ready(function($) {
  var styles = '<style type="text/css">' +
    "#network_bar                 {float:left; display:inline; width:100%; margin:0; padding:0; background:#222; color:#ccc;}" +
    "#network_bar ul              {float:left; display:inline; margin:0; padding:0;}" +
    "#network_bar ul li           {float:left; display:inline; margin:0; padding:0; border-right:1px solid #333; list-style-type:none;}" +
    "#network_bar ul li a         {float:left; display:block; margin:0; padding:6px 10px; color:#aaa; font:11px/11px helvetica, arial, sans-serif !important; text-decoration:none; text-align:center;}" +
    "#network_bar ul li a:hover   {color:#fff;}" +
    "#network_bar ul li a.current {color:#fff;}" +
  '</style>';

  var html = '<div id="network_bar">' +
    '<ul>' +
      '<li><a href="http://blawgtips.com" title="Over-analyzing the simple art of blogging">BlawgTips</a></li>' +
      '<li><a href="http://railstips.org" title="One man feverishly posting everything he learns">RailsTips</a></li>' +
    '</ul>' +
  '</div>';

  $('head').append(styles);
  $('body').prepend(html);

  // to ensure that there is clearage after network bar
  $('#network_bar').next().css({clear: 'both'});

  $('#network_bar a').each(function() {
    var link = $(this);
    var is_current = new RegExp(link.attr('href')).match(window.location.href);
    if (is_current) {
      link.addClass('current');
    }
  });
});

I define a style tag and some html. I then append the styles to the head and prepend the html to the body. I also add a clear:both to the element following the html added just to ensure things get cleared. I probably could switch that to css. Finally, I loop through the a tags in the network bar and add a class of current to the link that represents the current site a visitor is on.

That is it. The jQuery that actually does the work is less than 10 lines. Now I can put this in an external script and include it on multiple sites to get the exact same network bar on each of those sites. When I add a new site to the network, I simply update this one script and all the sites update with it. Pretty cool.

New Blog about Blogging

January 12th, 2009

I have spent a lot of time over the past few months growing RailsTips, one of my other blogs. From October to December, I doubled my traffic and almost doubled my feed subscribers (16k to 30k and 2.5k to 4k).

All the tweaks and changes I have been doing over there has left me wanting an outlet to share them. Last week, I whipped the site together (with the same simple theme as RailsTips) and invited my friend Chas Grundy to co-author it with me.

Blawgtips Screenshot

We both enjoy sharing the things we learn and really hope this project will be useful to those interested in blogging for more professional reasons (make money, project leads, make a name for yourself, etc.). We’ve kicked it off with a few articles, that I’ll list here, so you can get an idea of the content going forward.

Head on over and subscribe if you want to stay in the loop. Also, we are sure there are other bloggers out there with stuff to say, so if you would like to guest author a post, let me know.

Refactoring Tip: Move Functions into Objects

December 16th, 2008

On the last project that I worked on, we were spending a lot of time learning and the code started to get out of control. Towards the end, I made a few passes through and started moving stuff around. Take the following two functions for example.

function addChat(name, room_jid, person_jid) {
  // add chat stuff
}

function showChat(room) {
  // show chat stuff
}

There is nothing wrong with the functions above but you can see the similarities. Both have chat in the name and both are operating on chat based stuff. What I did on the project is move them into a simple Chat object like this.

var Chat = {
  add: function(name, room_jid, person_jid) {
    // add chat stuff
  },

  show: function(room) {
    // show chat stuff
  }
}

Now I don’t have to remember whether I named the function addChat or chatAdd. It is much easier to remember that we have a Chat object and that it has add and show methods. I’m obviously not going to have an Add object with a chat method. Catch my drift? I think this is one of the reasons I got so frustrated with PHP back in the day. The function names were a pain to remember and the parameter order was even worse.

Moving things to an object like this makes them easier to remember and allows your code to grow. If, for example, I wanted to keep track of the current chat with a variable or the number of active chats, I could simply add those to the Chat object. Using functions, your only option would be to have a global variable of sorts, and trust me, those lead to the path of ruin. :)

Refactoring Tip: Introduce Explaning Variables

November 24th, 2008

I am not one to latch on to fancily named patterns, nor have I read the book on it (I did give it a skim). That said, I have managed to learn a few and today I’ll share one of my favorites. You often hear people say that comments are code smell. “You should be able to tell what code is doing by just looking at the code,” they say from their perch on high. Well, I hate to break it to you, but they are kind of right. Your code should be the comments. Take the following snippet of JavaScript code:

// if google.com or www.google.com add http:// to the href
if (typeof(scheme) == 'undefined' || scheme == 'www.') { url = 'http://' + url; }

This code is from some JavaScript I’m working on that performs auto-linking of urls and email addresses. Note that there is a comment and if you read the comment you get an idea of what the code is doing. Now I just stated that comments possibly smell, so what can we do to remove the comment and yet retain the intent of the code?

var no_scheme  = typeof(scheme) == 'undefined',
    www_scheme = scheme == 'www.';
if (no_scheme || www_scheme) { url = 'http://' + url; }

We just used a pattern, namely that of introducing explaining variables. The pattern probably seems obvious now that you see it, but how often do we code like the first example. In the example above, the explaining variables are introduced with the act of replacing the, not so obvious, conditions in the if statement, with variables that are named based on the intent of the condition. Our two lines of code are now three, but I guarantee the next programmer (which might even be yourself a few months later) in our code will appreciate that extra line. Everyone knows code gets changed quite often and comments rarely do which leads to confusing and out of date comments.

Next time you start busting out conditional statements or chaining methods together, consider how you could introduce an explaning variable that might make the code intent more clear.

Creating A jQuery Plugin From Scratch

November 20th, 2008

The first few jQuery plugins I created were basically my attempt at doing prototype in jQuery. They were not idiomatic jQuery. I did a bit of googling and found some good examples and decided to write a really basic jQuery plugin just to cement the format in my head. I figured I would post it here both to further cement it and as a way for you to learn if you want. If you only want to see the end result, you can find it on GitHub

Cross Library Safety

The first thing I do is create a wrapper function which allows me to use $ and not cause conflicts with other JavaScript frameworks that may be included. It is simple and looks like this:

(function($) {
  // safe to use $ here and not cause conflicts
})(jQuery);

Create and Name Your Plugin Function

Next, I created the function inside which my plugin will reside. Whatever you name this function will be how you and others use your plugin.

(function($) {
  $.fn.toggler = function() {
    // the plugin functionality goes in here
  }
})(jQuery);

I have emboldened the function name in the code above to make it obvious. This means that to use the plugin I am creating, someone would have to do $('#some_selector').toggler().

Allow chainability

The next thing to keep in mind is that because jQuery takes any selector, you could be dealing with one or more objects. This means you need to be sure that your plugin loops through each element matched by the selector and applies the plugin functionality.

(function($) {
  $.fn.toggler = function() {
    return this.each(function() {
      // apply plugin functionality to each element
    });
  }
})(jQuery);

The other thing you will notice about the addition above is that I use return. One of the cool things about jQuery is the chainability (ie: $('#some_div').hide().remove()). Returning the this.each iteration allows your plugin to be chained with other jQuery operations and plugins.

Start Building Plugin Functionality

The goal of the plugin I was creating was to allow saying that a particular link is a toggler. So what is a toggler you ask? A toggler is a link that toggles the visibility of another element on the page. The connection of the link to the element is by using the href. By setting the link’s href to anchor to the id of another element, we get two things for free. First, if JavaScript is not enabled, the link will still anchor to the element on the page. Second, we know which element the link is suppose to toggle display for. Take the following html for example:

<p><a href="#foo" class="toggler">Toggler</a></p>
<div id="foo">Togglee</div>

The default behavior of the toggler link is to anchor to the Togglee div wherever it is on the page. We will then use the jQuery plugin we are making to hide the togglee div on page load and then toggle its display each time the toggler link is clicked. First, let’s hide the togglee div and add the click observer to the toggler link.

(function($) {
  $.fn.toggler = function() {
    return this.each(function() {
      this.togglee = $($(this).attr('href')).hide();
      $(this).click(onClick);
    });
  }
})(jQuery);

The first bold line sets a togglee attribute on the toggler that is equal to the togglee jQuery element. Note the $(this).attr('href'). Using the html from above, this would return #foo. $('#foo') is equivalent to a jQuery object of the togglee div. We call hide() to hide the div by default. Because jQuery allows chaining, the hide() call returns the togglee jQuery object and we save a line of code. The long hand way of writing that line would be something like this:

this.togglee = $($(this).attr('href'));
this.togglee.hide();

Because jQuery allows chaining, lines like the ones above can be combined and in my opinion remain readable. Chaining too many things together can lower readability and the obviousness of intent though, so always practice safe chaining.

Observing Clicks

The $(this).click(onClick); line above tells the toggler (which is $(this)) to run the function onClick whenever it gets clicked. We haven’t yet created the onClick function so let’s do that now.

(function($) {
  $.fn.toggler = function() {
    return this.each(function() {
      this.togglee = $($(this).attr('href')).hide();
      $(this).click(onClick);
    });

    function onClick() {
      this.togglee.toggle()
      return false;
    }
  }
})(jQuery);

this is automatically set to the element that fired the onClick, by jQuery, which is our toggler link. Because we assigned the togglee attribute to the toggler link, we can simple call this.togglee.toggle() and it will toggle the display of the togglee div. The return false tells the togglee link to not actually fire the normal event, which would append #foo to the window location.

Allowing For Options

At this point, we could be done but why not allow some options for our plugin. In this case, we’ll add the option to make the togglee div animate with a slide instead of simply showing and hiding. Check out the bold lines in the cold sample below to see what is needed to add options.

(function($) {
  $.fn.toggler = function(options) {

    var opts = $.extend({}, $.fn.toggler.defaults, options);

    return this.each(function() {
      this.togglee = $($(this).attr('href')).hide();
      $(this).click(onClick);
    });

    function onClick() {
      this.togglee[opts.animate ? 'slideToggle' : 'toggle']();
      return false;
    }
  }

  $.fn.toggler.defaults = {animate: false}
})(jQuery);

The first bold line sets the opts variable and uses jQuery’s extend function to do so. Basically, $.extend is a merge tool. In plain english here is what happens: it merges $.fn.toggler.defaults on top of {} and then merges options on top of the first merge. It guarantees that our opts variable will be a hash ({}), will have some defaults ($.fn.toggler.defaults) and yet can be overridden on a per case basis with options passed in by you, the developer (options).

In the second bold line, we tell togglee to call slideToggle if opts.animate is true, otherwise just call toggle. This uses the ternary operator and some cool JavaScript functionality. If opts.animate is true, it returns 'slideToggle', otherwise it returns 'toggle'. This means if opts.animate is true, you would end up with this.togglee['slideToggle'](), which is the sweet functionality I referenced above that JavaScript natively provides. this.togglee['slideToggle'] is a reference to the slideToggle function and when you apply the parenthesis it will invoke the slideToggle function. I feel this way is more succinct, is still readable and again, it saves you a few lines and an if/else statement. Not a big deal, but worth it in this case.

The third and final emboldened line just sets the defaults that get used in the first line if no options are provided by you when you call toggler on some elements.

Example Uses With/Without Options

Now that we have options, you can call the toggler function any of the following ways and it will work.

// will do simple toggle on click
$('a.toggler').toggler();

// will use slideToggle instead of simple toggle on click
$('a.toggler.animate').toggler({animate:true});

That is pretty much it. You can now create a jQuery plugin that is jQuery-ish and has the ability to have options that can be adjusted on the fly, by you and the people who use your amazing plugin. The only other thing I would mention is most people seem to name their plugins jquery.{plugin name}.js. For example, I named this plugin jquery.toggler.js.

Overall, I am intrigued with jQuery. It doesn’t come with everything that Prototype does out of the box, but it is probably enough for most. Even if you do not switch to jQuery, I think it is important to give it a good run as it will help you think through JavaScript in a bit different light. As always, if I missed anything or I was unclear or wrong anywhere in the post, feel free to let me know and I will update.

An Idea Idea

November 11th, 2008

I have a lot of ideas lately. I think the main reason I have had so many is because I have been trying to come up with ideas. Contrary to popular belief, ideas do not spring out of nowhere. Idea generation is like exercising. The more you exercise, the stronger you get. Likewise, the more you sit there and think of ideas, the more ideas you generate. Be prepared. When your idea muscle grows strong, it will create an overwhelming flood.

Track Your Ideas

If you are going to try to generate more ideas, you have to get them out of your brain as they happen. The more ideas you keep in your brain the less ideas you will have. Carry a Moleskine, sign up for a note app, create a list or buy a voice recorder. Whatever you do, as soon as you get an idea, get it out of your head. You do not have to instantly go do the idea, just record it.

Develop Your Ideas

As you become more disciplined at tracking your ideas, more ideas will come to. Some of those ideas will be improvements to original ideas. Over time you will start to see certain a really cool transformation of some ideas. You will create ideas that you would have never been capable of originally, but due to increased attention and thought, they have developed into something great.

Share Your Ideas

Share your ideas. Do not just track your ideas and forcefully try to come up with new ones. Also bring others into the fold. Share your ideas with them and you will be surprised at how differently they think through them, which will in turn help you think differently. Sharing an idea with someone is one of the best ways to really develop it. 

Pick One and Do It

So now you are tracking your ideas, generating more ideas, and sharing them with people which in turn is generating more ideas and mutating previous ones. Pick one. Pick the idea that meets at the crossroads of interesting and profitable. Design it. Build it. Market it. Do not stop there though. Keep generating more ideas. It is possible that the idea you pick will not be successful. If that is the case, you only need to worry if you have at some point stopped your creative process.

The Idea Idea

Today I had an idea on how to better share ideas. You will never have time to build all your ideas, but that does not mean that the ones you do not pick are not solid. Try to get someone else to work on the solid idea and consult with them. Sharing ownership and seeing an idea take shape is better than letting it rot.

My idea was a blog where I share ideas that I do not have time to fully own, but that I would still like to see created. Each time I decide I do not want to focus on an idea, I could release it as a blog post. Anyone else would then be free to take the idea and run. All I would ask for is the opportunity to help with the idea at some point because chances are I would want to use it and I believe I could be helpful along the way.

The blog idea almost immediately morphed into something else. I think it would be cool to have a site online where you could store your ideas and annotate them with thoughts, links, screenshots and scribbles. If you decide you do not want to devote time to the idea, you can make it public and allow someone else to work on it. That person can take the idea and run with it, and even more wisely, involve you in the process.

That is the idea. It’s an idea idea. Anyone who stumbles across this can feel free to take that idea and run with it. I cannot guarantee profitability but I think it is cool. I would love to help bring this into fruition, but I have already chosen an idea to run with, leaving me with no time.

How to you store your ideas? What are some good ones that you will never do?

4 Weight Lifting Tips

November 1st, 2008

I started lifting weights again and it feels great. I have lifted weights off and on since college and have picked up a few things that I thought I would share. 

1. Negative Can Be Positive

In order to present my tips I first have to explain one thing. In weight lifting, each exercise has a positive and negative motion. The positive motion is when you exert. On bench press, the positive motion would be when you push the bar off your chest. The opposite of positive motion is obviously negative motion. Negative motion, on bench press, would be when you lower the bar to your chest. 

Positive motion always seems the most difficult but negative can actually work your muscles more. Sometimes when you hit a wall at a certain weight level a purely negative workout (with a good spotter) can help you break through.

2. Breathe!!!

Breathing is really important in weight lifting. Grunting, contrary to popular belief is not, but rather it is the fact that grunting is kind of a way of exhaling, which is similar to breathing and thus is more helpful than not grunting but less helpful than actually exhaling. Anyway, always exhale during positive motion (when you exert effort) and inhale during negative motion. You don’t have to inhale and exhale each time but never inhale during positive and never exhale during negative. 

3. Vary Your Speed

Related to the motions and breathing is timing. Typically, positive motions should be half the time of their negative counter parts. On bench press, this would mean slowly lowering the bar to your chest (3-4 seconds, negative motion), followed by a burst of power to raise it back up (1-2 seconds, positive motion). 

To sum up the first three, inhale during negative motions, and do them slowly (think balance) and exhale during positive motions and do them quickly (think power). 

4. Bigger to Smaller

Always, always, always work larger muscles first and work your way down to smaller muscles. Take your legs for example: first work out your quadriceps and hamstrings, then work out your calf muscles. If you work out your calf muscles first, you will not be able to properly work out your upper legs. The same is true with ams vs. chest/back. Do your chest or back first, before working out your biceps or triceps. 

My Workout Schedule

I do not have set days or set exercises that I do, but rather have set muscle groups that I rotate through on whatever days I end up working out. I always work out chest with triceps, back with biceps and legs with shoulders. In each workout I start with the larger muscle group and work to the smaller ones. I also try to do abs 3 to 4 days a week. Abs can take a beating, typically.

So why am I not ripped and a physical specimen? I believe I just dished some good advice, but I am pretty undisciplined at following it for more than 3 months in a given year. The other 9 months? I use them to make up for all the hard work during the 3 good months. :)

Do It For Mom

October 31st, 2008

Mom. Mom. Mom. Moooom. Mooooooooom. Mom, mom, mom. Remember those days? Remember when you only cared what mom thought of what you were doing? Those were the good days. Then, out of nowhere, you are no longer doing it for mom. You are doing it for your boss or your co-worker or your client. Make the logo bigger. Get this done ASAP.  

I might be weird but I still do stuff for my mom. Heck, I even have a tumblr account dedicated to her, aptly named “For John’s Mom.” Anytime I post to one of my many blogs (or blawgs as she pronounces it, yes you do mom, don’t deny it), tweet or find something funny on the internet my mom knows about it.

Often times when I am working on something I will send her an email or give her a call and tell her about it. She could tell you my favorite programming language (and my favorite framework for said language). She knows that each Friday I spend time on an app I am building, and that its name is Harmony

The next work project you do, do it for your mom. Put everything you have into it and show it to your mom when you are done. Explain to her why it is cool and how hard you worked at it. She will be proud. You will be proud.

About This Site

Addicted to New is the personal website of John Nunemaker (Noo-neh-maker), a Web Developer enamored of Ruby on Rails and a wide-eyed fan of all things new and cool.