/**
 * Colorado College
 * by White Whale Web Services
 * http://whitewhale.net
 */

var dotBulletsAvailable = 3,
    homepageTimeout,
    homepageFired = false,
    openNav = false;

/**
 * Note: Using "jQuery" instead of "$" due to Prototype library collisions.
 */

jQuery(document).ready(function() {
  addRandomSubnavigationBullets();
  startNavigationCollapse();
  startPlaceholder();
  startLeftScrapbookScatter();
  startIECSSFixes();
  startWebFontFix();
  startSlideshows();
  startHomepage();
  startQuickAccess();
  startVideoPlayer();
  startBlockFeatureFeature();
  startProgramBrowser();
  startLightboxes();
  startLibrarySearchBoxes();
});


function startWebFontFix() {
  // Chrome on Windows cannot handle the web font because in its version,
  // it is missing an apostrophe — rather than showing it as the default
  // font, it shows the entire line as the default font, not cool; to fix
  // this, we're replacing apostrophes with a non-web-font version
   if (BrowserDetect.browser == 'Chrome' && BrowserDetect.OS == 'Windows') {
    jQuery('*')
      .filter(function() {
        return /neofill/i.test(jQuery(this).css('font-family')) && jQuery(this).parents('#main-navigation').length == 0;
      })
      .each(function() {
        // replace apostrophes
        jQuery(this).html(jQuery(this).html().replace(/([^>])(?:'|’)([^<])/ig, '$1<span class="no-web-fonts">’</span>$2'));
      });
  }
  
  if (BrowserDetect.browser == 'Opera') {
    jQuery('*')
      .filter(function() {
        return /neofill/i.test(jQuery(this).css('font-family')) && jQuery(this).parents('#main-navigation').length == 0;
      })
      .each(function() {
        // replace apostrophes
        jQuery(this).html(jQuery(this).html().replace(/([^>])(?:'|’)([^<])/ig, '$1<span class="no-web-fonts">’</span>$2'));

        // replace brackets
        jQuery(this).html(jQuery(this).html().replace(/(?:{)/ig, '('));
        jQuery(this).html(jQuery(this).html().replace(/(?:})/ig, ')'));
      });
  }
}



/**
 * Adds randomized hand-drawn bullets to subnavigation calendar items
 */
function addRandomSubnavigationBullets() {
  var random, previousRandom = 0;
  
  if (jQuery('#subnavigation').length) {
    jQuery('#subnavigation li')
      .each(function(n) {
        // make a random number in the allowed range
        random = Math.round((Math.random() * (dotBulletsAvailable - 1)) + 1);

        // to ensure we don't get the same bullet twice in a row
        while (dotBulletsAvailable > 1 && random == previousRandom) {
          random = Math.round((Math.random() * (dotBulletsAvailable - 1)) + 1);
        }

        previousRandom = random;
        jQuery(this).addClass('dot' + random);
      });
  }
}


/**
 * Collapses the navigation if appropriate, adds triggers to expand
 */
function startNavigationCollapse() {
  var header = jQuery('#header'),
      navList = jQuery('#header ul li ul'),
      openNav = jQuery('#openNav').val(),
    alwaysOpenNav = jQuery('#alwaysOpenNav').val();
  
  if (!jQuery('header.collapsed').length) { return; }  // this page is not a collapsed page

  // initiate collapse CSS
  // header.css('height', '78px').data('nav-is-collapsed', true);
  // navList.css('top', '160px');
  
  // initiate collapse CSS
  if (alwaysOpenNav == "true") { 
    header.css('height', '209px').data('nav-is-collapsed', false);
    navList.css('top', '0px');
    return; 
  }
  if (openNav == "true") {
    header.css('height', '209px').data('nav-is-collapsed', false);
    navList.css('top', '0px');
  } else {
    header.css('height', '78px').data('nav-is-collapsed', true);  
    navList.css('top', '160px');
  }
  
  jQuery('#header h5')
    .bind('click', function() {
      // jQuery('#header').data('nav-is-collapsed') is a state-holder
      // for the navigation, we can't use .toggle() since the click
      // events are spread between many ULs
      if (header.data('nav-is-collapsed')) {
        // already collapsed, expand
        header
          .data('nav-is-collapsed', false)
          .stop()
          .animate({'height': '209px'}, 400, 'easeOutBack');
        jQuery('#header h5').css('cursor', 'default');
        navList.each(function(n) {
          // the delay here sets up a fan-like animation
          jQuery(this).stop().delay(50 * n).animate({'top': 0}, 600, 'easeOutBack');
        });
      } else {
        header
          .data('nav-is-collapsed', true)
          .stop()
          .animate({'height': '78px'}, 700, 'easeInOutBack');
        jQuery('#header h5').css('cursor', 'pointer');
        navList.each(function(n) {
          jQuery(this).stop().delay(50 * n).animate({'top': '160px'}, 600, 'easeOutQuad');
        });
      }
    })
    .css('cursor', 'pointer');  // usability cue
}


/**
 * Starts placeholder on all input boxes
 */
function startPlaceholder() {
  jQuery('input[type="text"]').placeholder();
}


/**
 * Scatters left-scrapbook photos a little
 */
function startLeftScrapbookScatter() {
  var basePositions = [ 0, 17, 34 ].shuffle();
  
  jQuery('.left-scrapbook img').each(function(n) {
    var nudge = Math.round(Math.random() * 12) - 6,   // ±6px
        basePosition = parseInt(basePositions[n % basePositions.length], 10),
        newMarginRight = basePosition + Math.round(nudge);
    
    jQuery(this).css('margin-right', newMarginRight + 'px');
  });
}


/**
 * Applies styles to certain elements that can't comprehend CSS3
 */
function startIECSSFixes() {
  jQuery('aside.left-scrapbook img:nth-child(6n-4)').addClass('ie-bring-to-front');
  
  jQuery('aside.scrunched img:nth-child(6n-4)').removeClass('ie-bring-to-front');
  jQuery('aside.scrunched img:first-child').addClass('ie-bring-to-front');
  
  jQuery('#block-feature .block-selector li:nth-child(4n)').addClass('ie-remove-margin');
  
  jQuery('h1 + h2').addClass('ie-h2-after-h1-fix');
}


/**
 * Sets up and starts Flowplayer
 */
function startVideoPlayer() {
  jQuery('aside.video a, #homepage a.video').each(function(e) {
    // check for a youtube link
    if (jQuery(this).attr('href').match(/youtube\.com/i)) {
      jQuery(this)
        .fancybox({
          type: 'iframe',
          href: 'http://www.youtube.com/embed/' + jQuery(this).attr('href').match(/v=([0-9a-zA-Z_\-]+)&?/i)[1],
          height: 349,
          width: 425,
          transitionIn: 'elastic',
          transitionOut: 'elastic',
          centerOnScroll: true,
          overlayColor: '#292c34',
          overlayOpacity: 0.6,
          titlePosition: 'inside',
          padding: 6
        });
    
    // check for a vimeo link
    } else if (jQuery(this).attr('href').match(/vimeo\.com/i)) {
      jQuery(this)
      .fancybox({
        type: 'iframe',
        href: 'http://player.vimeo.com/video/' + jQuery(this).attr('href').match(/com\/([0-9]+)\??/i)[1] + '?title=0&portrait=0&color=ffffff',
        height: 300,
        width: 400,
        transitionIn: 'elastic',
        transitionOut: 'elastic',
        centerOnScroll: true,
        overlayColor: '#292c34',
        overlayOpacity: 0.6,
        titlePosition: 'inside',
        padding: 6
      });
    
    // this is a normal, uploaded video, use the local player
    } else {
      jQuery(this)
        .fancybox({
          type: 'iframe',
          href: '/assets/player.php?video=' + jQuery(this).attr('href'),
          scrolling: 'no',
          transitionIn: 'elastic',
          transitionOut: 'elastic',
          centerOnScroll: true,
          overlayColor: '#292c34',
          overlayOpacity: 0.6,
          titlePosition: 'inside',
          padding: 6
        });      
    }
  });
}



/**
 * Mimics placeholder in browsers that don't support it
 */
jQuery.fn.extend({ // add plugins
  placeholder: function(options) { // bootstrap HTML5 placeholder attributes for browsers that don't support it
    options = options || {};
    var s = {
      style:options.style || 'placeholder', // the class to add when the element is operating as a placeholder
      clear:options.clear || false // the elements which, when clicked, should wipe the placeholder
    };
    return this.each(function() { // with each matched element
      var self = jQuery(this);
      if (this.placeholder && 'placeholder' in document.createElement(this.tagName)) return; // if the browser supports placeholders for this element, abort
      if (self.data('placeholder')) { // if a placeholder has already been set on this element
        return; // abort to avoid double-binding
      }
      self.data('placeholder',true); // flag this element as having a placeholder, so we'll never double-bind
      var placeholder = self.attr('placeholder') || '',
      clear = function() { // to clear the placeholder
        if (self.val()==placeholder) { // if the text is the placeholder
          self.removeClass(s.style).val(''); // blank the text and remove the placeholder style
        }
      };
      self
        .focus(clear)
        .blur(function() {
          var val = self.val();
          if (!val||val==placeholder) { // if there's no text, or the text is the placeholder
            self.addClass(s.style).val(placeholder); // set the text to the placeholder and add the style
          }
        }).blur(); // and do it now
        self.parents('form').submit(clear);
        jQuery(s.clear).click(clear);
    });
  }
});


/**
 * Slideshows
 */
function startSlideshows() {
  jQuery('aside.slideshow')
    .find('a.more-info')
      .css('display', 'block')
      .click(function(e) {
        e.preventDefault();
        e.stopPropagation();
      })
    .end()
    .each(function(i) {
      var items = jQuery(this).find('li'),
          list = jQuery(this).find('ul'),
          areaWidth = list.width(),
          areaHeight = list.height(),
         ranges = {
          'moveLeft': {
            'top': {
              'start': ((areaHeight/2) * -1) - 30,
              'end': ((areaHeight/2) * -1) - 10
            },
            'left': {
              'start': ((areaWidth/2) * -1) - 30,
              'end': ((areaWidth/2) * -1) - 10
            },
            'rotate': {
              'start': -30,
              'end': -10
            }
          },
          'moveRight': {
            'top': {
              'start': ((areaHeight/2) * -1) - 30,
              'end': ((areaHeight/2) * -1) - 10
            },
            'left': {
              'start': (areaWidth/2) + 10,
              'end': (areaWidth/2) + 30
            },
            'rotate': {
              'start': 10,
              'end': 30
            }
          }
         };
      
      list.data('lowest-z-index', 50000);
      list.data('ranges', ranges);
      
      items.each(function(n) {
        var item = jQuery(this),
            itemWidth = item.width(),
            itemHeight = item.height(),
            newZIndex = 50000 - n,
            newLeft = Math.round((areaWidth - itemWidth) / 2),
            newTop = Math.round((areaHeight - itemHeight) / 2);
        
        list.data('lowest-z-index', newZIndex);

        jQuery(this)
          .css('left', newLeft)
          .css('top', newTop)
          .data('order', n)
          .data('returnLeftValue', newLeft)
          .data('returnTopValue', newTop)
          .css('z-index', newZIndex);  // way up
      });
    });
  
  
  jQuery('aside.slideshow ul')
    .css('cursor', 'pointer')
    .each(function(k) {
      jQuery(this)
        .click(function(e) {
          var items = jQuery(this).find('li'),
              highestZIndex = 0,
              currentItem,
              range,
              useLeft,
              useTop,
              useRotate;

          items.each(function(n) {
            if (jQuery(this).css('z-index') > highestZIndex) {
              highestZIndex = jQuery(this).css('z-index');
              currentItem = jQuery(this);
            }
          });
          
          // move front-most pic
          range = (currentItem.css('z-index') % 2) ? jQuery(this).data('ranges').moveLeft : jQuery(this).data('ranges').moveRight;
           useLeft = range.left.start + (Math.random() * (Math.abs(range.left.start - range.left.end))),
           useTop = range.top.start + (Math.random() * (Math.abs(range.top.start - range.top.end))),
           useRotate = (BrowserDetect.browser == 'Chrome' || BrowserDetect.browser == 'Safari') ? 0 : range.rotate.start + (Math.random() * (Math.abs(range.rotate.start - range.rotate.end)));
                
          currentItem
            .animate({
              'top': useTop,
              'left': useLeft,
              'rotate': useRotate
            }, 215, 'easeOutCubic', function() {
              var updateZIndex = jQuery(this).parents('ul').data('lowest-z-index') - 1;
              jQuery(this).parents('ul').data('lowest-z-index', updateZIndex);
              jQuery(this).css('z-index', updateZIndex);
              
              jQuery(this)
                .animate({
                  'top': jQuery(this).data('returnTopValue'),
                  'left': jQuery(this).data('returnLeftValue'),
                  'rotate': 0
                }, 255, 'easeInQuad');
            });
        })
        .dblclick(function(e) {
          e.preventDefault();
          return false;
        });
    });
  
  jQuery('.slideshow .description a[href="#"]')
    .click('function', function() {
      jQuery(this)
        .parents('.slideshow')
        .find('ul a')
        .eq(0)
          .click();
      return false;
    });
}


/**
 * Homepage picture moving
 */
function startHomepage() {
  if (!jQuery('#homepage').length) {
    return;
  }
  
  // animation
  // -------------------------------------------------------------------------
  jQuery('a.left, a.right')
    .each(function(n) {
      jQuery(this)
        .data('startingLeft', jQuery(this).css('left'))
        .data('startingTop', jQuery(this).css('top'));
    });
    
  homepageTimeout = setTimeout(function() {
    moveHomepageImages();
  }, 3000);
  
  jQuery('a.image, a.video').mouseenter(function() {
    clearTimeout(homepageTimeout);
    moveHomepageImages();
  });
  
  // captions
  // -------------------------------------------------------------------------
  jQuery('#homepage a.left, #homepage a.right')
    .fancybox({
      titlePosition: 'over',
      cyclic: true,
      transitionIn: 'elastic',
      transitionOut: 'elastic',
      centerOnScroll: true,
      overlayColor: '#292c34',
      overlayOpacity: 0.6,
      padding: 6
    });
}


/**
 * Turning on QuickAccess
 */
function startQuickAccess() {
  jQuery('aside.quick-search input.quick-search, #gateway .quick-search input')
    .quickaccess({
      links: '.quick-links a',
      maxResults: 6
    });
  
  // position qa_results
  positionPageQA();
  jQuery(window).resize(function() {
    positionPageQA();
  });
  
  jQuery('#header form .text-box input')
    .quickaccess({
      links: '.quick-links a',
      maxResults: 10,
      results: '#page_qa_results',
      noneFound: 'Press enter to search our site.'
    });
}


/**
 * Positions the page-level QuickAccess
 */
function positionPageQA() {
  jQuery('#page_qa_results')
    .css('top', parseInt(jQuery('#header form .text-box input').offset().top, 10) + jQuery('#header form .text-box input').height() + 10)
    .css('right', jQuery(window).width() - parseInt(jQuery('#header form .text-box input').offset().left, 10) - jQuery('#header form .text-box input').width() - 8);
}



/**
 * Triggers the homepage images to move
 */
function moveHomepageImages() {
  if (homepageFired) {
    return;
  }
  
  homepageFired = true;
  
  jQuery('.left.position-ne').animate({'left': '-=260' }, 500, 'easeOutCirc');
  jQuery('.left.position-nw').animate({'left': '-=60' }, 500, 'easeOutCirc');
  jQuery('.left.position-sw').animate({'left': '-=140' }, 500, 'easeOutCirc');
  jQuery('.left.position-se').animate({'left': '-=190' }, 500, 'easeOutCirc');
  jQuery('.right.position-ne').animate({'left': '+=80' }, 500, 'easeOutCirc');
  jQuery('.right.position-nw').animate({'left': '+=190' }, 500, 'easeOutCirc');
  jQuery('.right.position-sw').animate({'left': '+=257' }, 500, 'easeOutCirc');
  jQuery('.right.position-se').animate({'left': '+=100' }, 500, 'easeOutCirc');
}



/**
 * Makes the feature section for block feature page
 */
function startBlockFeatureFeature() {
  if (!jQuery('#block-feature').length) {
    return;
  }
  
  var tabs = jQuery('<ul id="tabs"></ul>'),
      visuals = jQuery('<ul id="visuals"></ul>'),
      featuredCourseList = jQuery('<div id="featured-courses"><h4>Featured Courses</h4></div>');

  // create a playground for tab area
  jQuery('.block-highlights hgroup')
    .after('<div id="feature-highlights"></div>');

  // create tabs
  jQuery('ul.featured-courses')
    .children('li')
    .each(function(i) {
      var visualItem = jQuery('<li></li>'),  
          tabItem = jQuery('<li></li>')
          backgroundImage = jQuery(this).children('img').attr('src');
      
      // visuals
      visualItem
        .css('background-image', 'url(' + backgroundImage + ')')
        .append('<div class="description">' + jQuery(this).children('.description').html() + '</div>')
        .attr('id', 'visual-' + i);      
      visuals.append(visualItem);
      
      // tabs
      tabItem
        .html('<a href="#">' + jQuery(this).children('h3').html() + '</a>')
        .data('trigger-id', i);
      tabs.append(tabItem);
      featuredCourseList.append(tabs);
    });
  
  jQuery('#feature-highlights')
    .append(visuals)
    .append(featuredCourseList)
    .append('<span class="clear"></span>');
  
  jQuery('.featured-courses').css('display', 'none');
  
  // we need a reference point for swapping z-indexes
  jQuery('#feature-highlights #tabs').data('tabsLastZIndex', 10);
  
  jQuery('#feature-highlights #tabs a')
    .click(function(e) {
      var index = jQuery(this).parent().data('trigger-id'),
          newZIndex = jQuery('#feature-highlights #tabs').data('tabsLastZIndex');

      jQuery('#feature-highlights #tabs').data('tabsLastZIndex', newZIndex + 1);

      jQuery('#feature-highlights #tabs li')
        .each(function(i) {
          if (jQuery(this).data('trigger-id') == index) {
            jQuery(this).addClass('on');
            jQuery('#visual-' + jQuery(this).data('trigger-id')).stop().fadeTo(600, 1).css('z-index', newZIndex);
          } else {
            jQuery(this).removeClass('on');
            jQuery('#visual-' + jQuery(this).data('trigger-id')).stop().fadeTo(600, 0);
          }
        });
      
      return false;
    });
  
  
  jQuery('#feature-highlights #tabs li:first-child a').click();
}


/**
 * Drop-down action for the program browser
 */
function startProgramBrowser() {
  jQuery('#program-browser p')
    .toggle(
      function(e) {
        jQuery(this)
          .parents('#program-browser')
          .find('.programs')
            .slideDown(500, 'easeOutCubic');
      },
      function(e) {
        jQuery(this)
          .parents('#program-browser')
          .find('.programs')
            .slideUp(500, 'easeOutCubic');          
      }
    );
}


/**
 * Adds fancybox lightbox to all links with the class "lightbox"
 */
function startLightboxes() {
  jQuery('a.lightbox').fancybox({
    titlePosition: 'over',
    cyclic: true,
    transitionIn: 'elastic',
    transitionOut: 'elastic',
    centerOnScroll: true,
    overlayColor: '#292c34',
    overlayOpacity: 0.6,
    padding: 6
  });
}


/**
 * Starts the library drop downs
 */
function startLibrarySearchBoxes() {
  if (!jQuery('#search-library, #searchbox').length)  { return; }
  
  jQuery('input[type="button"]')
    .click(function() {
      var searchForm = jQuery(this).parents('form');
      var searchBox = searchForm.find('.search-types');

      searchBox.css('display', (searchBox.css('display') == 'block') ? 'none' : 'block');
    })
    .each(function(i) {
      positionSearchTypeDropDown(jQuery(this));
    });
  
  jQuery('.search-types a')
    .click(function(e) {
      e.preventDefault();
    
      jQuery(this)
        .parents('form')  // update search button value
          .find('input[type="submit"]').val('Search ' + jQuery(this).text())
        .end()
          .find('.search-types')  // hide drop down
          .css('display', 'none')
        .end()
          .find('input[name="search-type"]')
          .val(jQuery(this).data('searchtype'));
      
      positionSearchTypeDropDown(jQuery(this).parents('form').find('input[type="button"]'));
      
      return false;
    });
}

/**
 * Positions the search type drop down on library pages
 */
function positionSearchTypeDropDown(el) {
  var formWidth = el.parents('form').width();
  
  el
    .parents('form')
    .find('.search-types')
      .css({
        top: parseInt(el.position().top, 10) + el.height() + 17,
        right: formWidth - (parseInt(el.position().left, 10) + el.width() + parseInt(el.css('padding-right'), 10) + parseInt(el.css('padding-left'), 10) + 2)
      });
}


/**
 * Browser detection, used to fix web fonts unfortunately
 * source: http://www.quirksmode.org/js/detect.html
 */
var BrowserDetect = {
  init: function () {
    this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
    this.version = this.searchVersion(navigator.userAgent)
      || this.searchVersion(navigator.appVersion)
      || "an unknown version";
    this.OS = this.searchString(this.dataOS) || "an unknown OS";
  },
  searchString: function (data) {
    for (var i=0;i<data.length;i++)  {
      var dataString = data[i].string;
      var dataProp = data[i].prop;
      this.versionSearchString = data[i].versionSearch || data[i].identity;
      if (dataString) {
        if (dataString.indexOf(data[i].subString) != -1)
          return data[i].identity;
      }
      else if (dataProp)
        return data[i].identity;
    }
  },
  searchVersion: function (dataString) {
    var index = dataString.indexOf(this.versionSearchString);
    if (index == -1) return;
    return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
  },
  dataBrowser: [
    {
      string: navigator.userAgent,
      subString: "Chrome",
      identity: "Chrome"
    },
    {   string: navigator.userAgent,
      subString: "OmniWeb",
      versionSearch: "OmniWeb/",
      identity: "OmniWeb"
    },
    {
      string: navigator.vendor,
      subString: "Apple",
      identity: "Safari",
      versionSearch: "Version"
    },
    {
      prop: window.opera,
      identity: "Opera"
    },
    {
      string: navigator.vendor,
      subString: "iCab",
      identity: "iCab"
    },
    {
      string: navigator.vendor,
      subString: "KDE",
      identity: "Konqueror"
    },
    {
      string: navigator.userAgent,
      subString: "Firefox",
      identity: "Firefox"
    },
    {
      string: navigator.vendor,
      subString: "Camino",
      identity: "Camino"
    },
    {    // for newer Netscapes (6+)
      string: navigator.userAgent,
      subString: "Netscape",
      identity: "Netscape"
    },
    {
      string: navigator.userAgent,
      subString: "MSIE",
      identity: "Explorer",
      versionSearch: "MSIE"
    },
    {
      string: navigator.userAgent,
      subString: "Gecko",
      identity: "Mozilla",
      versionSearch: "rv"
    },
    {     // for older Netscapes (4-)
      string: navigator.userAgent,
      subString: "Mozilla",
      identity: "Netscape",
      versionSearch: "Mozilla"
    }
  ],
  dataOS : [
    {
      string: navigator.platform,
      subString: "Win",
      identity: "Windows"
    },
    {
      string: navigator.platform,
      subString: "Mac",
      identity: "Mac"
    },
    {
         string: navigator.userAgent,
         subString: "iPhone",
         identity: "iPhone/iPod"
      },
    {
      string: navigator.platform,
      subString: "Linux",
      identity: "Linux"
    }
  ]

};
BrowserDetect.init();



/**
 * Adds shuffle functionality to Arrays
 * source: http://javascript.about.com/library/blshuffle.htm
 */
Array.prototype.shuffle = function() {
  var s = [];
  while (this.length) {
    s.push(this.splice(Math.random() * this.length, 1));
  }
  while (s.length) {
    this.push(s.pop());
  }
  return this;
}
