//CVS:       $Id: plugins.js,v 1.13 2012/02/22 17:19:13 cvsdevel Exp $
//Title:     plugins.js
//Version:   1.01
//Copyright: Copyright (c) 2012
//Author:    Donovan Mueller
//Company:   Rhino Internet

/**
 * Collected plugins for the main Rhino Internet website.
 *
 * <p>
 * <b>Changelog:</b><pre>
 *  1.00  DDM 2012/01/12  Created.
 *  1.01  DDM 2012/02/22  Added donutScroll jQuery plugin.
 * </pre>
 *
 * @author  DDM
 * @version 1.01
 */

jQuery.noConflict();

// usage: log('inside coolFunc', this, arguments);
window.log = function(){
  log.history = log.history || [];   // store logs to an array for reference
  log.history.push(arguments);
  if(this.console) {
      arguments.callee = arguments.callee.caller;
      console.log( Array.prototype.slice.call(arguments) );
  }
};
(function(b){function c(){}for(var d="assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profileEnd,time,timeEnd,trace,warn".split(","),a;a=d.pop();)b[a]=b[a]||c})(window.console=window.console||{});

/*
 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
 *
 * Uses the built in easing capabilities added In jQuery 1.1
 * to offer multiple easing options
*/

// t: current time, b: begInnIng value, c: change In value, d: duration
jQuery.easing['jswing'] = jQuery.easing['swing'];

jQuery.extend( jQuery.easing,
{
	def: 'easeOutQuad',
	swing: function (x, t, b, c, d) {
		return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
	},
	easeInQuad: function (x, t, b, c, d) {
		return c*(t/=d)*t + b;
	},
	easeOutQuad: function (x, t, b, c, d) {
		return -c *(t/=d)*(t-2) + b;
	},
	easeInOutQuad: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t + b;
		return -c/2 * ((--t)*(t-2) - 1) + b;
	},
	easeInCubic: function (x, t, b, c, d) {
		return c*(t/=d)*t*t + b;
	},
	easeOutCubic: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t + 1) + b;
	},
	easeInOutCubic: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t + b;
		return c/2*((t-=2)*t*t + 2) + b;
	},
	easeInQuart: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t + b;
	},
	easeOutQuart: function (x, t, b, c, d) {
		return -c * ((t=t/d-1)*t*t*t - 1) + b;
	},
	easeInOutQuart: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
		return -c/2 * ((t-=2)*t*t*t - 2) + b;
	},
	easeInQuint: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t*t + b;
	},
	easeOutQuint: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t*t*t + 1) + b;
	},
	easeInOutQuint: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
		return c/2*((t-=2)*t*t*t*t + 2) + b;
	},
	easeInSine: function (x, t, b, c, d) {
		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
	},
	easeOutSine: function (x, t, b, c, d) {
		return c * Math.sin(t/d * (Math.PI/2)) + b;
	},
	easeInOutSine: function (x, t, b, c, d) {
		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
	},
	easeInExpo: function (x, t, b, c, d) {
		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
	},
	easeOutExpo: function (x, t, b, c, d) {
		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
	},
	easeInOutExpo: function (x, t, b, c, d) {
		if (t==0) return b;
		if (t==d) return b+c;
		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
	},
	easeInCirc: function (x, t, b, c, d) {
		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
	},
	easeOutCirc: function (x, t, b, c, d) {
		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
	},
	easeInOutCirc: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
	},
	easeInElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
	},
	easeOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
	},
	easeInOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
	},
	easeInBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*(t/=d)*t*((s+1)*t - s) + b;
	},
	easeOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
	},
	easeInOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158; 
		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
	},
	easeInBounce: function (x, t, b, c, d) {
		return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
	},
	easeOutBounce: function (x, t, b, c, d) {
		if ((t/=d) < (1/2.75)) {
			return c*(7.5625*t*t) + b;
		} else if (t < (2/2.75)) {
			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
		} else if (t < (2.5/2.75)) {
			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
		} else {
			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
		}
	},
	easeInOutBounce: function (x, t, b, c, d) {
		if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
		return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
	}
});

/** A carousel plugin
    @author Donovan Mueller (zotobi@gmail.com)
    @url https://gist.github.com/1303150
    ------------------------------------------------------------------------ */
;(function donutSliderPlugin($){
   var $methods  = {}
     , $settings = { frameSelector:    '.slides'
                   , listSelector:     'ul'
                           // Assumed to be a child of `frameSelctor`. 
                           // The list of slides will be built from the direct
                           // descendents of this list.
                   , axis:             'x'
                           // The axis the slides travel on.
                   , delay:            10000
                           // Milliseconds between slides
                   , transDuration:      600
                           // Milliseconds used for animating the transition 
                           // between slides.
                   , transEasing:      'swing'
                   , hideRestart:      true
                           // Whether or not to hide going back to the first 
                           // slide.
                   , createPosMarkers: 'pos_markers' };
                           // The class name to be used for creating position
                           // markers. If left blank or set to `false` markers
                           // will not be created.
   
   $methods.init = function(settings)
   {
      this.each(function forEachElement()
      {
         var $this = $(this)
           , data  = $this.data('donutSlider')
           , markers, first;
           
         if (!data) {
            data = {};
            
            if ($.isPlainObject(settings) === false) {
               settings = {};
            }
            data.settings = $.extend({}, $settings, settings);
            
            data.frame = $(data.settings.frameSelector);
            data.list  = data.frame.children(data.settings.listSelector);
            data.items = data.list.children();
            
            if (!data.items.length) {
               $this.data('donutSlider', false);
               return;
            }
            
            data.frame.css({position: 'relative', overflow: 'hidden'});
            data.list.css({position: 'absolute', top:  0, left: 0});
            
            // Create position markers
            if ( data.settings.createPosMarkers && 
                 data.settings.createPosMarkers.length )
            {
               markers = $('<ul>')
                         .addClass(data.settings.createPosMarkers);
               for (var s = 1; s <= data.items.length; ++s) {
                  $('<li>')
                  .append('<button type="button">' + s + '</button>')
                  .appendTo(markers);
               }
               
               $this.append(markers);
               data.posMarkers = markers.children();
               
               data.posMarkers.click(function onPosMarkerClick(){
                  data.list.stop().fadeIn(0);
                  $this.donutSlider('goto', $(this).index());
               });
               
               data.posMarkers.eq(0).addClass('active');
            }
            
            // Pause slideshow on hover
            data.frame.hover(
               function onMouseOver(){
                  $this.donutSlider('stop'); 
               },
               function onMouseOut(){
                  $this.donutSlider('play');
               }
            );
            
            $this.data('donutSlider', data);
            
            first = Math.floor(Math.random() * data.items.length);
            $this.donutSlider('goto', first, true);
         }
      }); // for each element 
      
      this.donutSlider('stop')
          .donutSlider('play');
      
      return this;
   }; // .init()
   
   $methods.play = function()
   {
      this.each(function forEachElement()
      {
         var $this = $(this)
           , data  = $this.data('donutSlider');
           
         if (!data) {
            if (data !== false) $this.donutSlider();
            return;
         }
         
         data.interval = setInterval(function gotoNextSlide(){
            $this.donutSlider('next');
         }, data.settings.delay);
         $this.data('donutSlider', data);
      }); // for each element
      
      return this;
   }; // .play()
   
   $methods.stop = function()
   {
      this.each(function forEachElement()
      {
         var $this = $(this)
           , data  = $this.data('donutSlider');
           
         if (!data) {
            if (data !== false) $this.donutSlider();
            return;
         }
         
         clearInterval(data.interval);
         data.interval = null;
         $this.data('donutSlider', data);
      }); // for each element
      
      return this;
   }; // .stop()
   
   $methods.next = function()
   {  /* Goes to next slide */
      this.each(function forEachElement()
      {
         var $this = $(this)
           , data  = $this.data('donutSlider')
           , next;
           
         if (!data) {
            if (data !== false) $this.donutSlider();
            return;
         }
         
         next = (data.activeSlide) ?
                data.activeSlide.next() : data.items.eq(1);
         next = (next.length) ? next.index() : 0;
         
         if (data.settings.hideRestart && next === 0) {
            data.list.fadeOut( (data.settings.transDuration)
                             , function afterhide(){
                                  $this.donutSlider('goto', next, true, false);
                               } )
                     .fadeIn(data.settings.transDuration);
         }
         else {
            $this.donutSlider('goto', next);
         }
      }); // for each element
      
      return this;
   }; // .next()
   
   $methods.goto = function(index, instantly, correctOpacity)
   {  /* Goes to passed slide */
      instantly = instantly || false;
      
      this.each(function forEachElement()
      {
         var $this = $(this)
           , data  = $this.data('donutSlider')
           , slide, css;
           
         if (!data) {
            if (data !== false) $this.donutSlider();
            return;
         }
         
         slide = data.items.eq(index);
         if (!slide.length) return;
         
         css = (data.settings.axis === 'x')
               ? {left: ( -slide.position().left - slide.outerWidth() + 
                          $this.width() ) + 'px'}
               : {top: (-slide.position().top) + 'px'}
               
         if (instantly) {
            data.list.css(css);
         }
         else {
            data.list.stop().animate( css, data.settings.transDuration
                                    , data.settings.transEasing );
         }
         
         if (correctOpacity !== false) {
            data.list.fadeTo(1, 1);
         }
         
         // Mark the related position marker as active.
         if (data.posMarkers) {
            data.posMarkers.not(':eq('+index+')')
                           .removeClass('active');
            data.posMarkers.eq(index)
                           .addClass('active');
         }
         
         data.activeSlide = slide;
         $this.data('donutSlider', data);
         
         // Restart interval timer if already playing. This prevents changing to
         // the next slide right after the user chose to go to a specific slide.
         if (data.interval !== null) {
            $this.donutSlider('stop').donutSlider('play');
         }
      }); // for each element
      
      return this;
   }; // .goto()
   
   $.fn.donutSlider = function(method)
   {
      // Method calling logic
      if ($methods[method]) {
         return $methods[method]
                .apply(this, Array.prototype.slice.call(arguments, 1));
      } 
      else if (typeof method === 'object' || !method) {
        return $methods.init.apply(this, arguments);
      }
      else {
        $.error( 'Method `' +  method + '` does not exist on ' +
                 'jQuery.donutSlider' );
      }
   }; // $.fn.donutSlider()
})(jQuery); // (donutSliderPlugin)()

/** A scroll to plugin.
    Scrolls to the first element in the jQuery object or to the passed 
    position.
    @author Donovan Mueller (zotobi@gmail.com)
    @url https://gist.github.com/1885908
    ------------------------------------------------------------------------ */
;(function donutScrollPlugin($) {
   var viewport = ($.browser.opera) ? 'html' : 'html, body'
                  // Opera jumps to the top when 'html,body' is used.

   $.fn.donutScroll = function(y, callback)
   {
      var docheight = $(document).height()
        , winheight = $(window).height();
        
      if (typeof y === 'undefined' || y === null) y = this.offset().top;
      if (y < 0) y = 0;
      
      // check that we aren't trying to scroll past what is visible
      // otherwise the animation will be cut short and wont be as pretty
      if ((docheight - y) < winheight) {
         y = docheight - winheight;
      }
   
      // Wheeeeee!
      $(viewport).stop().animate( {scrollTop: y}
                                , { duration: 600
                                  , easing:   'easeOutExpo'
                                  , complete: callback } );
   }; // $.fn.donutScroll()
})(jQuery); // (donutScrollPlugin)()


/** Twitter Feed
    Modified from http://twitter.com/javascripts/blogger.js
    ------------------------------------------------------------------------ */ 
function twitterCallback2(twitters) {
    var statusHTML = [];
    for (var i=0; i<twitters.length; i++) {
       var username = twitters[i].user.screen_name;
       var status = twitters[i].text.replace(/((https?|s?ftp|ssh)\:\/\/[^"\s\<\>]*[^.,;'">\:\s\<\>\)\]\!])/g, function(url) {
         return '<a href="'+url+'">'+url+'</a>';
       }).replace(/B@([_a-z0-9]+)/ig, function(reply) {
         return  reply.charAt(0)+'<a href="http://twitter.com/'+reply.substring(1)+'">'+reply.substring(1)+'</a>';
       });
       statusHTML.push('<li><span>'+status+'</span> <a style="font-size:85%" href="http://twitter.com/'+username+'/statuses/'+twitters[i].id_str+'">'+relative_time(twitters[i].created_at)+'</a></li>');
    }
    jQuery(document).ready(function onDOMReady(){
        jQuery('<ul>').addClass('tweets')
                      .html(statusHTML.join(''))
                      .appendTo('#ft > .follow');
    });
 };

function relative_time(time_value) {
   var values = time_value.split(" ");
   time_value = values[1] + " " + values[2] + ", " + values[5] + " " + values[3];
   var parsed_date = Date.parse(time_value);
   var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
   var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
   delta = delta + (relative_to.getTimezoneOffset() * 60);

   if (delta < 60) {
      return 'less than a minute ago';
   } else if(delta < 120) {
      return 'about a minute ago';
   } else if(delta < (60*60)) {
      return (parseInt(delta / 60)).toString() + ' minutes ago';
   } else if(delta < (120*60)) {
      return 'about an hour ago';
   } else if(delta < (24*60*60)) {
      return 'about ' + (parseInt(delta / 3600)).toString() + ' hours ago';
   } else if(delta < (48*60*60)) {
      return '1 day ago';
   } else {
      return (parseInt(delta / 86400)).toString() + ' days ago';
   }
}
