;(function($) {
  var cache = [];
  
  $.fn.extend({
    getID: function() {
      return parseInt($(this).attr("id").match(/\d+/)[0]);
    },
    setInputHint: function() {
      if ($(this).length > 1) {
        $(this).each(function() { 
          $(this).setInputHint(); 
        });
      } else {
        var el = $(this);
        el._default = el.val();

        el.focus(function() {
          if(el._default != el.val()) return;
          el.removeClass('hint').val('');
        })
        .blur(function() {
          if($.trim(el.val()) != '') return;
          el.addClass('hint').val(el._default);
        })
        .addClass('hint');
      }
    },
    addSelector: function(selector) {
      var classes = selector.split('.'), 
          $this = $(this);
      $.each(classes, function(i, c) {
        if (c.match(/^#/)) {
          $this.attr('id', c.replace('#',''));
        } else {
          $this.addClass(c);
        }
      });
      return $this;
    },
    findOrAppend: function(selector, element) {
      var $this = $(this), 
          $el = $this.find(selector);
      if ($el.length > 0) return $el; 
      // el doesnt exist so lets make it
      if (typeof element == 'undefined') {
        // figure out how to build the element from the selector
        var parts = selector.split(' ');
        $el = $("<div>");
        if (parts.length == 1) {
          // single selector so just added
          $el.addSelector(selector);
        } else {
          // selector with multiple depth so we just want the last selector
          $el.addSelector(parts.pop());
          // find this down the parts
          $this = $this.findOrAppend(parts.join(' '));
        }
      } else {
        // we provided a specific element
        $el = $(element);
      }
      // append it
      $this.append($el);
      // return it
      return $el;
    },
    soon: function(callback, when) {
      var context = this, wrapped_callback = function() {
        callback.apply(context);
      };
      setTimeout(wrapped_callback, when || 200);
      return context;
    },
    when: function(test, callback) {
      var context = this, ret = false;
      if (typeof test == "string") {
        ret = $(this).is(test);
      } else {
        ret = test;
      }
      if (ret) {
        callback.apply(this);
      }
      return context;
    },
    slideTo: function(speed) {
      var top = $(this).offset().top;
      $('body,html').animate({'scrollTop': top + 'px'}, speed);
    },
    preloadImages: function() {
      var urls = $(this).find('img').map(function() { return $(this).attr('src'); });
      $.preloadImages.apply(this, $.makeArray(urls));
      return this;
    }
  });

  $.extend({
    // is val blank?
    blank: function(val) {
      return !val || val === '' || !val.match(/\w+/);
    },

    timestamp: function() {
      return Math.floor(new Date().getTime()/1000);
    },
    
    togglePush: function(first, second) {
      var index = $.inArray(second, first);
      index != -1 ? 
        first.splice(index, 1) :
        first.push(second)
      return first;
    },
    
    // Arguments are image paths relative to the current page.
    preloadImages: function() {
      var args_len = arguments.length;
      for (var i = args_len; i--;) {
        var cacheImage = $('<img>');
        cacheImage.attr('src', arguments[i]);
        cache.push(cacheImage);
      }
    }
  });
  
})(jQuery);