
/*
 * Facebox (for jQuery)
 * version: 1.2 (05/05/2008)
 * @requires jQuery v1.2 or later
 *
 * Examples at http://famspam.com/facebox/
 *
 * Licensed under the MIT:
 *   http://www.opensource.org/licenses/mit-license.php
 *
 * Copyright 2007, 2008 Chris Wanstrath [ chris@ozmm.org ]
 *
 * Usage:
 *
 *  jQuery(document).ready(function() {
 *    jQuery('a[rel*=facebox]').facebox()
 *  })
 *
 *  <a href="#terms" rel="facebox">Terms</a>
 *    Loads the #terms div in the box
 *
 *  <a href="terms.html" rel="facebox">Terms</a>
 *    Loads the terms.html page in the box
 *
 *  <a href="terms.png" rel="facebox">Terms</a>
 *    Loads the terms.png image in the box
 *
 *
 *  You can also use it programmatically:
 *
 *    jQuery.facebox('some html')
 *    jQuery.facebox('some html', 'my-groovy-style')
 *
 *  The above will open a facebox with "some html" as the content.
 *
 *    jQuery.facebox(function($) {
 *      $.get('blah.html', function(data) { $.facebox(data) })
 *    })
 *
 *  The above will show a loading screen before the passed function is called,
 *  allowing for a better ajaxy experience.
 *
 *  The facebox function can also display an ajax page, an image, or the contents of a div:
 *
 *    jQuery.facebox({ ajax: 'remote.html' })
 *    jQuery.facebox({ ajax: 'remote.html' }, 'my-groovy-style')
 *    jQuery.facebox({ image: 'stairs.jpg' })
 *    jQuery.facebox({ image: 'stairs.jpg' }, 'my-groovy-style')
 *    jQuery.facebox({ div: '#box' })
 *    jQuery.facebox({ div: '#box' }, 'my-groovy-style')
 *
 *  Want to close the facebox?  Trigger the 'close.facebox' document event:
 *
 *    jQuery(document).trigger('close.facebox')
 *
 *  Facebox also has a bunch of other hooks:
 *
 *    loading.facebox
 *    beforeReveal.facebox
 *    reveal.facebox (aliased as 'afterReveal.facebox')
 *    init.facebox
 *
 *  Simply bind a function to any of these hooks:
 *
 *   $(document).bind('reveal.facebox', function() { ...stuff to do after the facebox and contents are revealed... })
 *
 */
(function($) {
  $.facebox = function(data, klass) {
    $.facebox.loading()

    if (data.ajax) fillFaceboxFromAjax(data.ajax, klass)
    else if (data.image) fillFaceboxFromImage(data.image, klass)
    else if (data.div) fillFaceboxFromHref(data.div, klass)
    else if ($.isFunction(data)) data.call($)
    else $.facebox.reveal(data, klass)
  }

  /*
   * Public, $.facebox methods
   */

  $.extend($.facebox, {
    settings: {
      opacity      : 0,
      overlay      : true,
      loadingImage : '/images/facebox/loading.gif',
      closeImage   : '/images/facebox/close.png',
      imageTypes   : [ 'png', 'jpg', 'jpeg', 'gif' ],
      faceboxHtml  : '\
    <div id="facebox" style="display:none;"> \
      <div class="popup"> \
        <table> \
          <tbody> \
            <tr> \
              <td class="tl"/><td class="b"/><td class="tr"/> \
            </tr> \
            <tr> \
              <td class="b"/> \
              <td class="body"> \
                <div class="header clearfix"> \
                  <div class="flickr"> \
                    <a href="http://www.flickr.com" title="powered by flickr API" target="_blank">www<span class="dot">.</span><strong class="flickr_logo">flick<span class="flickr_pink">r</span></strong><span class="dot">.</span><span class="com">com</span></a> \
                  </div> \
                  <div class="close_button"> \
                    <a href="#" class="close"> \
                      <img src="/images/facebox/close.png" title="close" class="close_image" /> \
                    </a> \
                  </div> \
                </div> \
                <div class="content"> \
                </div> \
              </td> \
              <td class="b"/> \
            </tr> \
            <tr> \
              <td class="bl"/><td class="b"/><td class="br"/> \
            </tr> \
          </tbody> \
        </table> \
      </div> \
    </div>'
    },

    loading: function() {
      init()
      if ($('#facebox .loading').length == 1) return true
      showOverlay()

      $('#facebox .content').empty()
      $('#facebox .body').children().hide().end().
        append('<div class="loading"><img src="'+$.facebox.settings.loadingImage+'"/></div>')

      $('#facebox').css({
        top:	getPageScroll()[1] + (getPageHeight() / 10),
        left:	$(window).width() / 2 - 205
      }).show()

      $(document).bind('keydown.facebox', function(e) {
        if (e.keyCode == 27) $.facebox.close()
        return true
      })
      $(document).trigger('loading.facebox')
    },

    reveal: function(data, klass) {
      $(document).trigger('beforeReveal.facebox')
      if (klass) $('#facebox .content').addClass(klass)
      $('#facebox .content').append(data)
      $('#facebox .loading').remove()
      $('#facebox .body').children().fadeIn('normal')
      $('#facebox').css('left', $(window).width() / 2 - ($('#facebox table').width() / 2))
      $(document).trigger('reveal.facebox').trigger('afterReveal.facebox')
    },

    close: function() {
      $(document).trigger('close.facebox')
      return false
    }
  })

  /*
   * Public, $.fn methods
   */

  $.fn.facebox = function(settings) {
    if ($(this).length == 0) return

    init(settings)

    function clickHandler() {
      $.facebox.loading(true)

      // support for rel="facebox.inline_popup" syntax, to add a class
      // also supports deprecated "facebox[.inline_popup]" syntax
      var klass = this.rel.match(/facebox\[?\.(\w+)\]?/)
      if (klass) klass = klass[1]

      fillFaceboxFromHref(this.href, klass)
      return false
    }

    return this.bind('click.facebox', clickHandler)
  }

  /*
   * Private methods
   */

  // called one time to setup facebox on this page
  function init(settings) {
    if ($.facebox.settings.inited) return true
    else $.facebox.settings.inited = true

    $(document).trigger('init.facebox')
    makeCompatible()

    var imageTypes = $.facebox.settings.imageTypes.join('|')
    $.facebox.settings.imageTypesRegexp = new RegExp('\.(' + imageTypes + ')$', 'i')

    if (settings) $.extend($.facebox.settings, settings)
    $('body').append($.facebox.settings.faceboxHtml)

    var preload = [ new Image(), new Image() ]
    preload[0].src = $.facebox.settings.closeImage
    preload[1].src = $.facebox.settings.loadingImage

    $('#facebox').find('.b:first, .bl, .br, .tl, .tr').each(function() {
      preload.push(new Image())
      preload.slice(-1).src = $(this).css('background-image').replace(/url\((.+)\)/, '$1')
    })

    $('#facebox .close').click($.facebox.close)
    $('#facebox .close_image').attr('src', $.facebox.settings.closeImage)
  }

  // getPageScroll() by quirksmode.com
  function getPageScroll() {
    var xScroll, yScroll;
    if (self.pageYOffset) {
      yScroll = self.pageYOffset;
      xScroll = self.pageXOffset;
    } else if (document.documentElement && document.documentElement.scrollTop) {	 // Explorer 6 Strict
      yScroll = document.documentElement.scrollTop;
      xScroll = document.documentElement.scrollLeft;
    } else if (document.body) {// all other Explorers
      yScroll = document.body.scrollTop;
      xScroll = document.body.scrollLeft;
    }
    return new Array(xScroll,yScroll)
  }

  // Adapted from getPageSize() by quirksmode.com
  function getPageHeight() {
    var windowHeight
    if (self.innerHeight) {	// all except Explorer
      windowHeight = self.innerHeight;
    } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
      windowHeight = document.documentElement.clientHeight;
    } else if (document.body) { // other Explorers
      windowHeight = document.body.clientHeight;
    }
    return windowHeight
  }

  // Backwards compatibility
  function makeCompatible() {
    var $s = $.facebox.settings

    $s.loadingImage = $s.loading_image || $s.loadingImage
    $s.closeImage = $s.close_image || $s.closeImage
    $s.imageTypes = $s.image_types || $s.imageTypes
    $s.faceboxHtml = $s.facebox_html || $s.faceboxHtml
  }

  // Figures out what you want to display and displays it
  // formats are:
  //     div: #id
  //   image: blah.extension
  //    ajax: anything else
  function fillFaceboxFromHref(href, klass) {
    // div
    if (href.match(/#/)) {
      var url    = window.location.href.split('#')[0]
      var target = href.replace(url,'')
      if (target == '#') return
      $.facebox.reveal($(target).html(), klass)

    // image
    } else if (href.match($.facebox.settings.imageTypesRegexp)) {
      fillFaceboxFromImage(href, klass)
    // ajax
    } else {
      fillFaceboxFromAjax(href, klass)
    }
  }

  function fillFaceboxFromImage(href, klass) {
    var image = new Image()
    image.onload = function() {
      $.facebox.reveal('<div class="image"><img src="' + image.src + '" /></div>', klass)
    }
    image.src = href
  }

  function fillFaceboxFromAjax(href, klass) {
    $.get(href, function(data) { $.facebox.reveal(data, klass) })
  }

  function skipOverlay() {
    return $.facebox.settings.overlay == false || $.facebox.settings.opacity === null
  }

  function showOverlay() {
    if (skipOverlay()) return

    if ($('#facebox_overlay').length == 0)
      $("body").append('<div id="facebox_overlay" class="facebox_hide"></div>')

    $('#facebox_overlay').hide().addClass("facebox_overlayBG")
      .css('opacity', $.facebox.settings.opacity)
      .click(function() { $(document).trigger('close.facebox') })
      .fadeIn(200)
    return false
  }

  function hideOverlay() {
    if (skipOverlay()) return

    $('#facebox_overlay').fadeOut(200, function(){
      $("#facebox_overlay").removeClass("facebox_overlayBG")
      $("#facebox_overlay").addClass("facebox_hide")
      $("#facebox_overlay").remove()
    })

    return false
  }

  /*
   * Bindings
   */

  $(document).bind('close.facebox', function() {
    $(document).unbind('keydown.facebox')
    $('#facebox').fadeOut(function() {
      $('#facebox .content').removeClass().addClass('content')
      hideOverlay()
      $('#facebox .loading').remove()
    })
  })

})(jQuery);



var flickr = function(json) {
  $('#flickr').html('');
  var photos = json.photos.photo;
  for (var i = 0; i < photos.length; i++) {
    var photo = photos[i];
    var a = $('<a />').attr("href", photo.medium).attr("title", photo.title).attr("rel", "facebox");
    var img = $('<img />').attr("src", photo.square);
    a.append(img);
    a.appendTo('#flickr');
  }
  $('a[rel*=facebox]').facebox();
};

/*
 * Gritter for jQuery
 * http://www.boedesign.com/
 *
 * Copyright (c) 2009 Jordan Boesch
 * Dual licensed under the MIT and GPL licenses.
 *
 * Date: June 26, 2009
 * Version: 1.0
 */

jQuery(document).ready(function($){
 	
 	/********************************************
	 * First, we'll define our object
	 */
 	
	Gritter = {
	    
	    // PUBLIC - touch all you want
		fade_speed: 2000, // how fast the notices fade out
	    timer_stay: 6000, // how long you want the message to hang on screen for
	    
	    // PRIVATE - no touchy the private parts
		_custom_timer: 0,
	    _item_count: 0,
		_tpl_close: '<div class="gritter-close"></div>',
		_tpl_item: '<div id="gritter-item-[[number]]" class="gritter-item-wrapper" style="display:none"><div class="gritter-top"></div><div class="gritter-item">[[image]]<div class="[[class_name]]"><span class="gritter-title">[[username]]</span><p>[[text]]</p></div><div style="clear:both"></div></div><div class="gritter-bottom"></div></div>',
	    _tpl_wrap: '<div id="gritter-notice-wrapper"></div>',
	    
	    // Add a notification to the screen
	    add: function(user, text, image, sticky, time_alive){
	        
	        // This is also called from init, we just added it here because
	        // some people might just call the "add" method
	        this.verifyWrapper();
	        
	        var tmp = this._tpl_item;
	        this._item_count++;
			
			// reset
			this._custom_timer = 0;
			
			// a custom fade time set
			if(time_alive){
				this._custom_timer = time_alive;
			}
			
			var image_str = (image != '') ? '<img src="' + image + '" class="gritter-image" />' : '';
			var class_name = (image != '') ? 'gritter-with-image' : 'gritter-without-image';
			
	        tmp = this.str_replace(
	            ['[[username]]', '[[text]]', '[[image]]', '[[number]]', '[[class_name]]'],
	            [user, text, image_str, this._item_count, class_name], tmp
	        );
	        
	        $('#gritter-notice-wrapper').append(tmp);
	        var item = $('#gritter-item-' + this._item_count);
	        var number = this._item_count;
	        item.fadeIn();
	        
			if(!sticky){
				this.setFadeTimer(item, number);
			}
			
			$(item).hover(function(){
				if(!sticky){ 
					Gritter.restoreItemIfFading(this, number);
				}
				Gritter.hoveringItem(this);
			},
			function(){
				if(!sticky){
					Gritter.setFadeTimer(this, number);
				}
				Gritter.unhoveringItem(this);
			});
			
			return number;
	    
	    },
		
		// If we don't have any more gritter notifications, get rid of the wrapper
	    countRemoveWrapper: function(){
	        
	        if($('.gritter-item-wrapper').length == 0){
	            $('#gritter-notice-wrapper').remove();
	        }
	    
	    },
		
		// Fade the item and slide it up nicely... once its completely faded, remove it
	    fade: function(e){
	
	        $(e).animate({
	            opacity:0
	        }, Gritter.fade_speed, function(){
	            $(e).animate({ height: 0 }, 300, function(){
	                $(e).remove();
	                Gritter.countRemoveWrapper();
	            })
	        })
	        
	    },
		
		 // Change the border styles and add the (X) close button when you hover
	    hoveringItem: function(e){
	    	
	    	$(e).addClass('hover');
	    	
			if($(e).find('img').length){
				$(e).find('img').before(this._tpl_close);
			}
			else {
				$(e).find('span').before(this._tpl_close);
			}
			$(e).find('.gritter-close').click(function(){
				Gritter.remove(this);
			});
	        
	    },
	    
	    // Remove a notification, this is called from the inline "onclick" event
	    remove: function(e){
	        
	        $(e).parents('.gritter-item-wrapper').fadeOut('medium', function(){ $(this).remove();  });
	        this.countRemoveWrapper();
	        
	    },
		
		// Remove a specific notification based on an id (int)
		removeSpecific: function(id, params){
			
			var e = $('#gritter-item-' + id);
			
			if(typeof(params) === 'object'){
				if(params.fade){
					var speed = this.fade_speed;
					if(params.speed){
						speed = params.speed;
					}
					e.fadeOut(speed);
				}
			}
			else {
				e.remove();
			}
			
			this.countRemoveWrapper();
			
		},
		
		 // If the item is fading out and we hover over it, restore it!
	    restoreItemIfFading: function(e, number){
			
			window.clearTimeout(Gritter['_int_id_' + number]);
	        $(e).stop().css({ opacity: 1 });
	        
	    },
	    
	    // Set the notification to fade out after a certain amount of time
	    setFadeTimer: function(item, number){
			
			var timer_str = (this._custom_timer) ? this._custom_timer : this.timer_stay;
	        Gritter['_int_id_' + number] = window.setTimeout(function(){ Gritter.fade(item); }, timer_str);
	
	    },
		
		// Bring everything to a halt!    
		stop: function(){
	
			$('#gritter-notice-wrapper').fadeOut(function(){
				$(this).remove();
			});
	
		},
		
		// A handy PHP function ported to js!
	    str_replace: function(search, replace, subject, count) {
	    
	        var i = 0, j = 0, temp = '', repl = '', sl = 0, fl = 0,
	            f = [].concat(search),
	            r = [].concat(replace),
	            s = subject,
	            ra = r instanceof Array, sa = s instanceof Array;
	        s = [].concat(s);
	        if (count) {
	            this.window[count] = 0;
	            }
	 
	        for (i=0, sl=s.length; i < sl; i++) {
	            if (s[i] === '') {
	                continue;
	            }
	            for (j=0, fl=f.length; j < fl; j++) {
	                temp = s[i]+'';
	                repl = ra ? (r[j] !== undefined ? r[j] : '') : r[0];
	                s[i] = (temp).split(f[j]).join(repl);
	                if (count && s[i] !== temp) {
	                    this.window[count] += (temp.length-s[i].length)/f[j].length;}
	            }
	        }
	        return sa ? s : s[0];
	        
	    },
	    
	    // Remove the border styles and (X) close button when you mouse out
	    unhoveringItem: function(e){
	        
	        $(e).removeClass('hover');
	        $(e).find('.gritter-close').remove();
	        
	    },
		
		// Make sure we have something to wrap our notices with
		verifyWrapper: function(){
	      
			if($('#gritter-notice-wrapper').length == 0){
				$('body').append(this._tpl_wrap);
			}
	 
		}
	    
	}
	
	/********************************************
	 * Now lets turn it into some jQuery Magic!
	 */
	
	// Set it up as an object
	$.gritter = {};
	
	// Add a gritter notification
	$.gritter.add = function(params){

		try {
			if(!params.title || !params.text){
				throw "Missing_Fields"; 
			}
		} catch(e) {
			if(e == "Missing_Fields"){
				alert('Gritter Error: You need to fill out the first 2 params: "title" and "text"');
			}
		}
		
		var id = Gritter.add(
			params.title,
			params.text,
			params.image || '',
			params.sticky || false,
			params.time || ''
		);
		
		return id;

	}
	
	// Remove a specific notification
	$.gritter.remove = function(id, params){
		Gritter.removeSpecific(id, params || '');
	}
	
	// Remove all gritter notifications
	$.gritter.removeAll = function(){
		Gritter.stop();
	}
	
});


/*
  @author: remy sharp / http://remysharp.com
  @params:
    feedback - the selector for the element that gives the user feedback. Note that this will be relative to the form the plugin is run against.
    hardLimit - whether to stop the user being able to keep adding characters. Defaults to true.
    useInput - whether to look for a hidden input named 'maxlength' instead of the maxlength attribute. Defaults to false.
    words - limit by characters or words, set this to true to limit by words. Defaults to false.
  @license: Creative Commons License - ShareAlike http://creativecommons.org/licenses/by-sa/3.0/
  @version: 1.2
  @changes: code tidy via Ariel Flesler and fix when pasting over limit and including \t or \n
*/

(function ($) {

$.fn.maxlength = function (settings) {

    if (typeof settings == 'string') {
        settings = { feedback : settings };
    }

    settings = $.extend({}, $.fn.maxlength.defaults, settings);

    function length(el) {
    	var parts = el.value;
    	if ( settings.words )
    		parts = el.value.length ? parts.split(/\s+/) : { length : 0 };
    	return parts.length;
    }
    
    return this.each(function () {
        var field = this,
        	$field = $(field),
        	$form = $(field.form),
        	limit = settings.useInput ? $form.find('input[name=maxlength]').val() : $field.attr('maxlength'),
        	$charsLeft = $form.find(settings.feedback);

    	function limitCheck(event) {
        	var len = length(this),
        	    exceeded = len >= limit,
        		code = event.keyCode;

        	if ( !exceeded )
        		return;

            switch (code) {
                case 8:  // allow delete
                case 9:
                case 17:
                case 36: // and cursor keys
                case 35:
                case 37: 
                case 38:
                case 39:
                case 40:
                case 46:
                case 65:
                    return;

                default:
                    return settings.words && code != 32 && code != 13 && len == limit;
            }
        }


        var updateCount = function () {
            var len = length(field),
            	diff = limit - len;

            $charsLeft.html( diff || "0" );

            // truncation code
            if (settings.hardLimit && diff < 0) {
            	field.value = settings.words ? 
            	    // split by white space, capturing it in the result, then glue them back
            		field.value.split(/(\s+)/, (limit*2)-1).join('') :
            		field.value.substr(0, limit);

                updateCount();
            }
        };

        $field.keyup(updateCount).change(updateCount);
        if (settings.hardLimit) {
            $field.keydown(limitCheck);
        }

        updateCount();
    });
};

$.fn.maxlength.defaults = {
    useInput : false,
    hardLimit : true,
    feedback : '.charsLeft',
    words : false
};

})(jQuery);

var twitbackr = twitbackr || {};

twitbackr.jsonp = function (url) {
  $('<script type="text/javascript" />').attr('src', url).appendTo('head');
}

twitbackr.search = function (keywords) {
  twitbackr.jsonp("http://search.twitter.com/search.json?q=" + encodeURIComponent(keywords) + "&callback=twitbackr.search_callback");
  setTimeout(function () {
    $('#timeline .loading').hide();
  }, 3500);
}

twitbackr.search_callback = function (json) {
  $('#timeline .loading').hide();
  $.each(json.results, function () {
    $('<li class="hentry status" />').attr('id', 'status_' + this.id).append(
      $('<span class="thumb vcard author" />').append(
        $('<a target="_blank" class="url">').attr('href', 'http://twitter.com/' + this.from_user).append(
          $('<img height="48" width="48" class="photo fn" />').attr('alt', this.from_user).attr('src', this.profile_image_url)
        )
      )
    ).append(
      $('<span class="status-body" />').append(
        $('<strong />').append(
          $('<a target="_blank" class="screen-name" />').attr('title', this.from_user).attr('href', 'http://twitter.com/' + this.from_user).append(this.from_user)
        )
      ).append(
        $('<span class="entry-content" />').append(
          this.text
          .replace(/https?:\/\/[\S]+(\b|$)/gim, '<a target="_blank" href="$&">$&</a>')
          .replace(/#twitbacke?r/, '<a target="_blank" href="http://twitter.com/search?q=%23twitbackr"><strong>#twitbackr</strong></a>')
          .replace(/@([\S]+)(\b|$)/gim, '<a target="_blank" href="http://twitter.com/$1">$&</a>')
        )
      ).append(
        $('<span class="meta entry-meta" />').append(
          $('<a target="_blank" class="entry-date" rel="bookmark" />').attr('href', 'http://twitter.com/' + this.from_user + '/status/' + this.id).append(
            $('<span class="published" />').append(twitbackr.relative_time(this.created_at))
          )
        )
      )
    ).append(
      $('<span class="actions">').append(
        $('<a target="_blank" class="reply" title="reply" />').attr('href', 'http://twitter.com/home?status=@' + this.from_user + '%20&amp;in_reply_to_status_id=' + this.id + '&amp;in_reply_to=' + this.from_user).append(' &nbsp; ')
      ).append(
        $('<a target="_blank" class="retweet" title="retweet" />').attr('href', 'http://twitter.com/home?status=RT @' + this.from_user + ':%20' + encodeURIComponent(this.text) + '&amp;in_reply_to_status_id=' + this.id + '&amp;in_reply_to=' + this.from_user).append(' &nbsp; ')
      )
    ).appendTo("#timeline");
  });
  if (json.next_page) {
    $("#timeline").after(
      $('<div id="pagination" />').append(
        $('<a target="_blank" class="round more" />').attr('href', 'http://twitter.com/search?q=' + json.query).append('more')
      )
    );
  }
  twitbackr.adjust_height();
}

twitbackr.relative_time = function (time) {
  var timestamp = Date.parse(time);
  var current_timestamp = new Date().getTime();
  var delta = parseInt(current_timestamp - timestamp);
  if (delta < 60 * 1000) {
    return 'less than a minute ago';
  } else if(delta < 120 * 1000) {
    return 'about a minute ago';
  } else if(delta < (3660 * 1000)) {
    return 'about ' + parseInt(delta / (60 * 1000)).toString() + ' minutes ago';
  } else if(delta < (1.5 * 3660 * 1000)) {
    return 'about an hour ago';
  } else if(delta < (18 * 3660 * 1000)) {
    return 'about ' + parseInt(delta / (3660 * 1000) + 1).toString() + ' hours ago';
  } else if(delta < (36 * 3660 * 1000)) {
    return 'yesterday';
  } else if(delta < (7 * 36 * 3660 * 1000)) {
    return parseInt(delta / (24 * 3660 * 1000) + 1).toString() + ' days ago';
  } else {
    return time;
  }
}

twitbackr.adjust_height = function () {
  var side_base_height = $('#side_base').height();
  var content_height = $('#content').height();
  if (side_base_height > content_height) {
    $('#content').height(side_base_height);
  } else {
    $('#side_base').height(content_height);
  };
}