//Getting an absolute URL from a relative one.
function qualifyURL(url) {
        var a = document.createElement('a');
        a.href = url;
        return a.href;
}


function textareaMaxlength(element, maxlength){
  var errorElementId = element.attr('id') + '-error';

  $(element).keyup(function() {
    if (this.val().length > maxlength) {
      // Display an error if you type more than maxlength characters.
      if (!$("p#" + errorElementId).length) {
        $(this).before('<p id="' + errorElementId + '" class="txtlength-error">You have exceeded ' + maxlength + ' characters.</p>');
        $(this).parents('form').find('input[type=submit]').attr('disabled', 'disabled');
      }
    } else {
      // Remove the error (if exists) when the number of chars is less then maxlength.
      if ($("p#" + errorElementId).length) {
        $("p#" +errorElementId).remove();
        $(this).parents('form').find('input[type=submit]').removeAttr('disabled');
      }
    }
  });
}





if (window.GFR == undefined) {
  GFR = {};
}

GFR.FormFeatures = {};

GFR.FormFeatures.Validate = function(formName, validateFields) {
  this.formName = formName
  this.validateFields = validateFields;

  this.submitForm = function() {
    var thisObj = this;
    var formName = this.formName;
    $('form' + formName).submit(function(){
      return thisObj.emptyFields();
    });
  }
  this.emptyFields = function() {
    var formName = this.formName;
    var formSubmit = true;
    var thisObj = this;
    $(validateFields, formName).each(function(){
      var $this = $(this);
      var parentElm = $this.parent();
      if ($.trim($this.val()) == '' || $this.val() == 'invalid') {
        thisObj.invalidField(parentElm, 'This field is required');
        if (formName == '#user-profile-form') {
          $('html, body').animate({
            scrollTop: ($('fieldset:not(.fieldset-editable) div.messages-inline').offset().top - 50)
          }, 600);
        }
        formSubmit = false;
      }
    });
    if ($(formName + ' div.messages-inline').length) {
      if ($('div.messages-inline').length == 1 && $('fieldset.penname-fieldset div.messages-inline').length) {
        formSubmit = true;
      } else {
        formSubmit = false;
      }
    }
    return formSubmit;
  }
  this.checkFields = function() {
    var thisObj = this;
    $(validateFields, formName).each(function(){
      var $this = $(this);
      var parentElm = $this.parent();

      $this.keypress(function(){
        var errorBox =  parentElm.next('div.messages-inline');
        if ($.trim($this.val()) == '') {
          parentElm.removeClass('valid')
        }
        if (errorBox.length){
          parentElm.removeClass('form-item-error');
          errorBox.remove();
        }
      });
      $this.change(function(){
        if ($this.val() == 'invalid') {
          thisObj.invalidField(parentElm, 'This field is required');
        }
      });
      $this.blur(function(){
        switch($this.attr('type')){
          case 'text':
            // Browser that don't recognize HTML5 types
            if ($this.hasClass('form-email')) {
              thisObj.testEmail($this, parentElm, 'E-mail address not valid');
            } else if ($this.hasClass('form-email') || $this.attr('id') == 'edit-conf-mail' && $('#edit-conf-mail').length)  {
              thisObj.verifyMatch('#edit-mail','#edit-conf-mail', 'E-mail addresses');
            }else {
              thisObj.validField(parentElm);
            }
          break;
          case 'email':
             if ($.trim($this.val())) {
              thisObj.testEmail($this, parentElm, 'E-mail address not valid');
              thisObj.verifyMatch('#edit-mail','#edit-conf-mail', 'E-mail addresses');
            } else {
              thisObj.validField(parentElm);
            }
          break;
          case 'password':
            var formid = thisObj.formName;
            if (formid != '#user-login' && formid != '#user-login-block') {
              thisObj.verifyPassword($this, parentElm);
            } else {
              thisObj.validField(parentElm);
            }
            if ($('input.password-confirm').length) {
              thisObj.verifyMatch('.password-field', '.password-confirm', 'Passwords')
            }

          break;
          case 'select-one':
            if ($this.val() != 'invalid') {
              thisObj.validField(parentElm);
            }
          break;
          default: thisObj.validField(parentElm);
        }
        if ($.trim($this.val()) == '' && parentElm.hasClass('valid')){
          parentElm.removeClass('valid');
        }
      });
    });
  }
  this.validField = function(parentElm){
    parentElm.removeClass('form-item-error').addClass('valid');
    parentElm.next('div.messages-inline').remove();
  }
  this.invalidField = function(parentElm, error){
    parentElm.parents('form').removeClass('error-default');
    parentElm.addClass('form-item-error');
    if (!parentElm.next('div.messages-inline').length){
      parentElm.removeClass('valid').after('<div class="messages-inline">' + error  +'</div>');
    }
  }
  this.verifyMatch = function(idA, idB, type) {
    var elmA = $(idA).val();
    var elmB = $(idB).val();
    var parent = $(idB).parent();
    if (elmA.length && elmB.length) {
      if (elmA == elmB) {
        this.validField(parent);
      } else {
        this.invalidField(parent, type + ' don\'t match');
      }
    }
  }
  this.testEmail = function(field, parent, error) {
    var email_regex = field.val();
    var checkAt = email_regex.indexOf('@');
    var checkDot = email_regex.indexOf('.');
    if ($.trim(field.val())) {
      if(checkAt > 0 && checkDot > 0) {
        this.validField(parent)
      } else {
        this.invalidField(parent, error);
        return false;
      }
    }
    return true;
  }
  this.verifyPassword = function(field, parent) {
    var passwordInput = field.val();
    if (passwordInput.length > 0 && passwordInput.length < 8) {
      this.invalidField(parent, 'Please enter at least 8 characters.')
    } else {
      this.validField(parent);
    }
  }
  this.checkFields();
  this.submitForm();
}



function edit(editableForm){
  var editBlock = $('.edit-block');

  editBlock.click(function(){
    var parentFieldset = $(this).parents('fieldset');
    // Remove the edit block;
    $(this).remove();

    // Remove the edit state form all the other fieldsets (if any exists) and
    // reset the form values. This use the form reset default functionality.
    $('input.form-reset').trigger('click');
    // Show the form elements for editing.
    parentFieldset.addClass('fieldset-editable').find('span.label').hide();
    // Create the reset button and append to the current fildset.
    $('input.form-reset').appendTo(parentFieldset);
    // Append the form submit button to the current fieldset.
    $('input#edit-submit', editableForm).appendTo(parentFieldset);
    // Disable checkboxed.
    $('input[type="checkbox"], input[type="text"], select', parentFieldset).attr('disabled', '');
  });
}

function checkEmpty(jsFormValidation) {
  var formsubmit = true;
  $('form' + jsFormValidation + ' input[required="required"], form' + jsFormValidation + ' input.required, form' + jsFormValidation + ' select.required').each(function(){
    var $this = $(this);
    var parentElm = $this.parent('div.form-item').attr('id');

    var label = $('#' + jsFormValidation + ' #' + parentElm + ' label').text().toLowerCase();
    label = label.replace('*', '').replace(':', '');
    var error = 'This field is required';

    if ($.trim($this.val()) == '' || $this.val() == 'invalid'){
      invalidField(parentElm, error);
      formsubmit = false;
    }
  });
  return formsubmit;
}

function submitEditable(editableForm, storedData) {
  $('input#edit-submit', editableForm).live('click', function(e){
    var parentFieldset = $(this).parents('fieldset');
    var $this = $(this);
    var empty = checkEmpty(editableForm);
    var submitBtn = $('<input type="submit" class="form-submit  editable-submit ec-button" value="Save changes" id="edit-submit" name="op">');
    var resetBtn = $('<input type="reset" class="form-reset" value="Cancel">');
    if (empty == false) {
      return false;
    }
    e.preventDefault();
    var form = $("form" + editableForm);
    var parentFieldsetClass = parentFieldset.attr('class');
    parentFieldsetClass = parentFieldsetClass.replace(' fieldset-editable', '');
    $this.attr('disabled', 'disabled');
    $('input.form-reset').attr('disabled', 'disabled');
    $('fieldset[name="editable"] input[type="checkbox"]').attr('disabled', '');
    var data = form.serialize();
    $.ajax({
      type: "POST",
      data: data,
      beforeSend: function(){
        $this.after('<span class="ajax-working"></span>');
      },
      success: function(html){
        var htmlContent = $("form" + editableForm + " fieldset." + parentFieldsetClass, html).html();
        $("fieldset." + parentFieldsetClass, form).html(htmlContent);
        $("fieldset." + parentFieldsetClass).attr('name');
        // The form has no error.
        if (!$('div.form-item-error').length) {
          parentFieldset.removeClass('fieldset-editable');
          $('select').each(function() {
            var valueSelected = $(this).attr('id');
            $('label[for=' + valueSelected + '] span.label').text(': ' + $('#' + valueSelected + " :selected").text()).show();
          });
          $('div.form-item').removeClass('valid');
          // Re-add the edit block.
          if ($("fieldset." + parentFieldsetClass, html).attr('name') == 'editable') {
            parentFieldset.prepend('<span class="edit-block">Edit</span>');
          }
          resetBtn.appendTo(form);
          submitBtn.appendTo(form);
          $('fieldset.' + parentFieldsetClass + ' legend').after('<div class="messages messages-status fieldset-message">Your personal information has successfully been updated.</div>')
          if ($('div.fieldset-message').length) {
          // After 4 seconds, slowly fadeout and then remove the confirmation.
            setTimeout(function() {
              $('div.fieldset-message').fadeOut('slow', function() {
                $("div.fieldset-message").remove();
              });
            }, 4000);
          }
          $('fieldset[name="editable"] input[type="checkbox"]').attr('disabled', 'disabled');
        }
        // The form has errors.
        else {
          $("fieldset." + parentFieldsetClass + " div.description").appendTo($("fieldset." + parentFieldsetClass));
          $('input.form-reset').appendTo(parentFieldset);
          $('input#edit-name').keypress(function(){
            var errorBox = $('div.messages-inline');
            if (errorBox.length){
              $('div.form-item-error').removeClass('form-item-error');
              errorBox.remove();
            }
          });
          resetBtn.appendTo(parentFieldset);
          submitBtn.appendTo(parentFieldset);
        }
        edit(editableForm);
      }
    });
  });
}
function resetForm(editableForm, storedData){
 $(editableForm + ' input.form-reset').live('click', function(e){
    var parentFieldset = $(this).parents('fieldset');
    var pennameFieldset = parentFieldset.hasClass('penname-fieldset');
    if (pennameFieldset){
      e.preventDefault();
      $('input#edit-name').remove();
      $('label[for=edit-name]').after('<input type="text" class="form-text error" value="' + storedData + '" size="60" id="edit-name" name="name" maxlength="60">');
    }
    parentFieldset.removeClass('fieldset-editable')
    $('div.form-item')
    $('span.label').show();

    $('div.messages-inline').remove();
    $('div.form-item').removeClass('form-item-error').removeClass('valid');
    if(!parentFieldset.children('span.edit-block').length) {
      parentFieldset.prepend('<span class="edit-block">Edit</span>');
    }
    edit(editableForm);
    $('fieldset[name="editable"] input[type="checkbox"]').attr('disabled', 'disabled');
  });
}

function invalidField(parentElm, error){
  var parentElm = $('#' + parentElm);
  parentElm.addClass('form-item-error');
  if (!parentElm.next('div.messages-inline').length){
    parentElm.removeClass('valid').after('<div class="messages-inline">' + error  +'</div>');
  }
};



function launchPage(theURL)
{
  $.cookie("popupState", -1, {expires: 1});
  window.location = theURL;
};
var iPhone = false;
var iPad = false;

//MLE
jQuery(window).load(function(){  });


window.onorientationchange = function() {
  	$(".overlay_blackout").css("height",$(document).height());
	$(".overlay_blackout").css("width",$(document).width());
};

var random_ad_nr = generateRandomNumber();

function generateRandomNumber(){
  var random_num=Math.floor(Math.random()*999999999);
  return random_num;
}


//MLE 20110512
$(document).ready(function() {

    function toggleSubNavOn() {
        /* Close any active subnavs before opening a new one. */
        $('#header-navigation-main li.highlighted').children('ul').hide();
        $('#header-navigation-main li.highlighted').removeClass('highlighted');

//MLE - COMMENTED OUT THE !active test in these two sections; I still want drop-downs for nav available on "active" page for now.
//    if (!$(this).hasClass('active')) {
        $(this).children('ul').show();
        $(this).addClass('highlighted');
    }

//  }

    function toggleSubNavOff() {
//    if (!$(this).hasClass('active')) {
        $(this).children('ul').hide();
        $(this).removeClass('highlighted');
//    }
    }

    /* Configuration options for hoverIntent - used to set our hover behavior on nav-menus in next step. */
    var config = {
        over: toggleSubNavOn,
        timeout: 400,
        out: toggleSubNavOff
    };

    /* IMPORTANT: This sets our top-level menu-nav items. */
    $('body.recipes-menu li.recipes, body.prodrevs-menu li.product-reviews, body.ingredients-menu li.ingredients, body.diet-menu li.diet').hoverIntent(config);
});
;


$(document).ready(function(){

  // POLL VOTE: Add ajax functionality to any voting implemented
  $("#node-poll-article input#edit-vote").click(function(e){
    e.preventDefault();

    // create the set of data to be sent on form submission
	  var data="choice=" + $('input[name=choice]:checked').val();
	  data += "&op=Submit+and+see+results";
	  data += "&form_build_id=" +  $('input[name="form_build_id"]').val();
	  data += "&form_token=" +  $('input[name="form_token"]').val();
	  data += "&ajax=true&form_id=poll_view_voting";

    var url_poll = $("form#poll-view-voting").attr("action");

    if ($('input[name=choice]:checked').val()){
	    $.ajax({
	    type: "POST",
	    data: data,
	    url: url_poll,
	    beforeSend: function(){
	      $("input#edit-vote").after("<span class='ajax-working'>Working...</span>");
	    },
	    success: function(html, XMLHttpRequest){
 	      $("div#node-poll-article div.content").remove();
	      $("div#node-poll-article").append(html)
	      $("p.poll-feedback-link").append('<a href="javascript:O_LC()">Please leave additional feedback</a>');
	    }
		 });
	  }
  });
});


;
$(document).ready(function(){
  $("div.views-field-editor-intro div.field-content span.continue").click(
    function() {
      $("div.views-field-editor-intro div.field-content span.part2").addClass('expand');
      $(this).remove();
    }
  );
})

;

/**
 * Returns the value(s) of the element in the matched set.  For example, consider the following form:
 *
 *  <form><fieldset>
 *      <input name="A" type="text" />
 *      <input name="A" type="text" />
 *      <input name="B" type="checkbox" value="B1" />
 *      <input name="B" type="checkbox" value="B2"/>
 *      <input name="C" type="radio" value="C1" />
 *      <input name="C" type="radio" value="C2" />
 *  </fieldset></form>
 *
 *  var v = $(':text').fieldValue();
 *  // if no values are entered into the text inputs
 *  v == ['','']
 *  // if values entered into the text inputs are 'foo' and 'bar'
 *  v == ['foo','bar']
 *
 *  var v = $(':checkbox').fieldValue();
 *  // if neither checkbox is checked
 *  v === undefined
 *  // if both checkboxes are checked
 *  v == ['B1', 'B2']
 *
 *  var v = $(':radio').fieldValue();
 *  // if neither radio is checked
 *  v === undefined
 *  // if first radio is checked
 *  v == ['C1']
 *
 * The successful argument controls whether or not the field element must be 'successful'
 * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
 * The default value of the successful argument is true.  If this value is false the value(s)
 * for each element is returned.
 *
 * Note: This method *always* returns an array.  If no valid value can be determined the
 *       array will be empty, otherwise it will contain one or more values.
 */
$.fn.fieldValue = function(successful) {
    for (var val=[], i=0, max=this.length; i < max; i++) {
        var el = this[i];
        var v = $.fieldValue(el, successful);
        if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length))
            continue;
        v.constructor == Array ? $.merge(val, v) : val.push(v);
    }
    return val;
};

/**
 * Returns the value of the field element.
 */
$.fieldValue = function(el, successful) {
    var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
    if (typeof successful == 'undefined') successful = true;

    if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
        (t == 'checkbox' || t == 'radio') && !el.checked ||
        (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
        tag == 'select' && el.selectedIndex == -1))
            return null;

    if (tag == 'select') {
        var index = el.selectedIndex;
        if (index < 0) return null;
        var a = [], ops = el.options;
        var one = (t == 'select-one');
        var max = (one ? index+1 : ops.length);
        for(var i=(one ? index : 0); i < max; i++) {
            var op = ops[i];
            if (op.selected) {
				var v = op.value;
				if (!v) // extra pain for IE...
                	v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
                if (one) return v;
                a.push(v);
            }
        }
        return a;
    }
    return el.value;
};

/**
 * Clears the form data.  Takes the following actions on the form's input fields:
 *  - input text fields will have their 'value' property set to the empty string
 *  - select elements will have their 'selectedIndex' property set to -1
 *  - checkbox and radio inputs will have their 'checked' property set to false
 *  - inputs of type submit, button, reset, and hidden will *not* be effected
 *  - button elements will *not* be effected
 */
$.fn.clearForm = function() {
    return this.each(function() {
        $('input,select,textarea', this).clearFields();
    });
};

/**
 * Clears the selected form elements.
 */
$.fn.clearFields = $.fn.clearInputs = function() {
    return this.each(function() {
        var t = this.type, tag = this.tagName.toLowerCase();
        if (t == 'text' || t == 'password' || tag == 'textarea')
            this.value = '';
        else if (t == 'checkbox' || t == 'radio')
            this.checked = false;
        else if (tag == 'select')
            this.selectedIndex = -1;
    });
};

/**
 * Resets the form data.  Causes all form elements to be reset to their original value.
 */
$.fn.resetForm = function() {
    return this.each(function() {
        // guard against an input with the name of 'reset'
        // note that IE reports the reset function as an 'object'
        if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType))
            this.reset();
    });
};

/**
 * Enables or disables any matching elements.
 */
$.fn.enable = function(b) {
    if (b == undefined) b = true;
    return this.each(function() {
        this.disabled = !b;
    });
};

/**
 * Checks/unchecks any matching checkboxes or radio buttons and
 * selects/deselects and matching option elements.
 */
$.fn.selected = function(select) {
    if (select == undefined) select = true;
    return this.each(function() {
        var t = this.type;
        if (t == 'checkbox' || t == 'radio')
            this.checked = select;
        else if (this.tagName.toLowerCase() == 'option') {
            var $sel = $(this).parent('select');
            if (select && $sel[0] && $sel[0].type == 'select-one') {
                // deselect all other options
                $sel.find('option').selected(false);
            }
            this.selected = select;
        }
    });
};



/*
 * jQuery Timer Plugin
 * http://www.evanbot.com/article/jquery-timer-plugin/23
 *
 * @version      1.0
 * @copyright    2009 Evan Byrne (http://www.evanbot.com)
 */

jQuery.timer = function(time,func,callback){
	var a = {timer:setTimeout(func,time),callback:null}
	if(typeof(callback) == 'function'){a.callback = callback;}
	return a;
};

jQuery.clearTimer = function(a){
	clearTimeout(a.timer);
	if(typeof(a.callback) == 'function'){a.callback();};
	return this;
};;


/**
 * Cookie plugin
 *
 * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 */

/**
 * Create a cookie with the given name and value and other optional parameters.
 *
 * @example $.cookie('the_cookie', 'the_value');
 * @desc Set the value of a cookie.
 * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
 * @desc Create a cookie with all available options.
 * @example $.cookie('the_cookie', 'the_value');
 * @desc Create a session cookie.
 * @example $.cookie('the_cookie', null);
 * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
 *       used when the cookie was set.
 *
 * @param String name The name of the cookie.
 * @param String value The value of the cookie.
 * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
 * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
 *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
 *                             If set to null or omitted, the cookie will be a session cookie and will not be retained
 *                             when the the browser exits.
 * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
 * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
 * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
 *                        require a secure protocol (like HTTPS).
 * @type undefined
 *
 * @name $.cookie
 * @cat Plugins/Cookie
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */

/**
 * Get the value of a cookie with the given name.
 *
 * @example $.cookie('the_cookie');
 * @desc Get the value of a cookie.
 *
 * @param String name The name of the cookie.
 * @return The value of the cookie.
 * @type String
 *
 * @name $.cookie
 * @cat Plugins/Cookie
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */
jQuery.cookie = function(name, value, options) {
    if (typeof value != 'undefined') { // name and value given, set cookie
        options = options || {};
        if (value === null) {
            value = '';
            options.expires = -1;
        }
        var expires = '';
        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
            var date;
            if (typeof options.expires == 'number') {
                date = new Date();
                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
            } else {
                date = options.expires;
            }
            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
        }
        // CAUTION: Needed to parenthesize options.path and options.domain
        // in the following expressions, otherwise they evaluate to undefined
        // in the packed version for some reason...
        var path = options.path ? '; path=' + (options.path) : '';
        var domain = options.domain ? '; domain=' + (options.domain) : '';
        var secure = options.secure ? '; secure' : '';
        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
    } else { // only name given, get cookie
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
};
;

/**
 * jQuery plugin to convert ISO 8601 timestamps to a human readable form.  All timestamps
 * are assumed to be UTC.
 *
 * Usage:
 * <span class="ec_timeago" title="2010-08-06T13:43:46-00:00">anything here (it will be replaced)</span>
 *
 * $(".ec_timeago").ec_timeago({ ... settings ... });
 *
 * Output:
 * <span class="ec_timeago" title="2010-08-06T13:43:46-00:00">3 hours 15 minutes ago</span>
 *
 * --------------------------------------------------------------------------------
 * | Condition                    | Syntax               | Example                |
 * --------------------------------------------------------------------------------
 * | TIME < 1 hr                  | xx mins ago          | 5 mins ago             |
 * | 1 hr < TIME < 4 hrs          | xx hrs xx mins ago   | 2 hrs 24 mins ago      |
 * | TIME > 4 hrs                 | MMM DDth, hh:mm      | July 24th, 23:11       |
 * | TIME > this year             | MMM DDth YYYY, hh:mm | July 24th 2009, 23:11  |
 * --------------------------------------------------------------------------------
*/
(function($) {

  var MINUTE = 60;
  var HOUR = 60 * 60;
  var DAY = HOUR * 24;
  var DAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
  var MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];

  /**
   * Convert a Date object into a human readable representation.
   */
  var timeago = function(then, settings) {
    var now = new Date(),
        nowUTC = now - (now.getTimezoneOffset() * 60000),
        today = new Date(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()),
        yesterday = new Date(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() - 1),
        sunday = new Date(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() - now.getUTCDay()),
        diff = parseInt((now - then) / 1000),
        hours = Math.floor(diff / HOUR),
        minutes = Math.floor((diff - (hours * HOUR)) / MINUTE);

    // X mins ago
    if (diff < HOUR)
      return settings.strings.minutesAgo
        .replace("mm", minutes)
        .replace("mins", (minutes == 1 ? "min" : "mins"));

    // X hours X mins ago
    else if (diff < (4 * HOUR))
      return settings.strings.hoursAgo
        .replace("hh", hours)
        .replace("mm", minutes)
        .replace("hours", (hours == 1 ? "hour" : "hours"))
        .replace("mins", (minutes == 1 ? "min" : "mins"));

    // Month Day, hh:mm
    else if (then.getUTCFullYear() == now.getUTCFullYear())
      return substitute(then, settings.strings.monthsAgo);

    // Month Day Year, hh:mm
    else
      return substitute(then, settings.strings.date);
  };

  /**
   * Returns the appropriate numerical suffix for a given number
   */
  function suffix(d) {
    d = String(d);
    return d.substr(-(Math.min(d.length, 2))) > 3 && d.substr(-(Math.min(d.length, 2))) < 21 ? "th" : ["th", "st", "nd", "rd", "th"][Math.min(Number(d) % 10, 4)];
  }

  /**
   * Convert a time format string into a time string
   */
  var substitute = function(date, string) {
    string = string.replace("mm", date.getUTCMinutes() > 9 ? date.getUTCMinutes() : "0" + date.getUTCMinutes());
    string = string.replace("hh", date.getUTCHours() > 9 ? date.getUTCHours() : "0" + date.getUTCHours());
    string = string.replace("MMM", MONTHS[date.getUTCMonth()]);
    string = string.replace("ddd", DAYS[date.getUTCDay()]);
    string = string.replace("dd", date.getUTCDate() + suffix(date.getUTCDate()));
    string = string.replace("YYYY", date.getUTCFullYear());
    return string;
  };

  // From http://github.com/rmm5t/jquery-timeago/blob/master/jquery.timeago.js
  var parse = function(iso8601) {
    var s = $.trim(iso8601);
    s = s.replace(/\.\d\d\d/,""); // remove milliseconds
    s = s.replace(/-/,"/").replace(/-/,"/");
    s = s.replace(/T/," ").replace(/Z/," UTC");
    s = s.replace(/([\+-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
    return new Date(s);
  };

  /**
   * jQuery ec_timeago plugin
   */
  $.fn.ec_timeago = function(settings) {
    var defaults = {
      refresh: 60000,
      prefix: "",
      suffix: "",
      strings: {
        minutesAgo: "mm mins ago",
        hoursAgo:   "hh hours mm mins ago",
        time:       "hh:mm",
        yesterday:  "Yesterday, hh:mm",
        thisWeek:   "ddd, hh:mm",
        monthsAgo:  "MMM dd, hh:mm",
        date:       "MMM dd YYYY, hh:mm"
      }
    };

    settings = $.extend(defaults, settings);

    this.each(function() {
      var $this = $(this);
      $this.text(settings.prefix + timeago(parse($this.attr("title")), settings) + settings.suffix);

      if (settings.refresh) {
        setInterval(function() {
          $this.text(settings.prefix + timeago(parse($this.attr("title")), settings) + settings.suffix);
        }, settings.refresh);
      }
    });

    return this;
  };

})(jQuery);
;


/**
* hoverIntent r6 // 2011.02.26 // jQuery 1.5.1+
* <http://cherne.net/brian/resources/jquery.hoverIntent.html>
*
* @param  f  onMouseOver function || An object with configuration options
* @param  g  onMouseOut function  || Nothing (use configuration options object)
* @author    Brian Cherne brian(at)cherne(dot)net
*/
(function($){$.fn.hoverIntent=function(f,g){var cfg={sensitivity:7,interval:100,timeout:0};cfg=$.extend(cfg,g?{over:f,out:g}:f);var cX,cY,pX,pY;var track=function(ev){cX=ev.pageX;cY=ev.pageY};var compare=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);if((Math.abs(pX-cX)+Math.abs(pY-cY))<cfg.sensitivity){$(ob).unbind("mousemove",track);ob.hoverIntent_s=1;return cfg.over.apply(ob,[ev])}else{pX=cX;pY=cY;ob.hoverIntent_t=setTimeout(function(){compare(ev,ob)},cfg.interval)}};var delay=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);ob.hoverIntent_s=0;return cfg.out.apply(ob,[ev])};var handleHover=function(e){var ev=jQuery.extend({},e);var ob=this;if(ob.hoverIntent_t){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t)}if(e.type=="mouseenter"){pX=ev.pageX;pY=ev.pageY;$(ob).bind("mousemove",track);if(ob.hoverIntent_s!=1){ob.hoverIntent_t=setTimeout(function(){compare(ev,ob)},cfg.interval)}}else{$(ob).unbind("mousemove",track);if(ob.hoverIntent_s==1){ob.hoverIntent_t=setTimeout(function(){delay(ev,ob)},cfg.timeout)}}};return this.bind('mouseenter',handleHover).bind('mouseleave',handleHover)}})(jQuery);
