-
-
Save draeton/be36b3b5ba1219baeaa1 to your computer and use it in GitHub Desktop.
OnStar » Experience OnStar code sample
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* Brand Lounge - Experience OnStar Plugin | |
* | |
* Copyright (c) 2011 Digitas | |
* All Rights Reserved. | |
* | |
*/ | |
/** | |
* Create the brand lounge | |
* | |
* Dependencies: jquery.ba-bbq.js, jquery.tmpl.js, page.lounge-nf.css, cufon-yui.js, shadedborder.js | |
* http://admin.brightcove.com/js/BrightcoveExperiences.js , | |
* http://admin.brightcove.com/js/APIModules_all.js | |
* | |
* @example $('#lounge').lounge(); | |
* @desc Initializes the brand lounge using all default values. | |
* | |
* @param {Object} options An object literal with key/value pairs for lounge settings | |
* | |
* @option {String} templates The jQuery template file, relative path from doclib | |
* @option {Object} params The JSON data selection object | |
* @option {String} doclib The root directory for the document library | |
* | |
* @name $.fn.lounge | |
* @author Matthew Cobbs <matthew.cobbs@digitas.com> | |
*/ | |
/*global jQuery, Liferay, Cufon, brightcove, APIModules, RUZEE */ | |
(function ($, window, Liferay, Cufon, brightcove, APIModules, RUZEE) { | |
/** | |
* This module holds all of the brand lounge methods | |
* for use in the lounge namespace | |
*/ | |
var methods = (function () { | |
var _$lounge = null, // global brand lounge div reference | |
_$grid = null, // global grid div reference | |
_$back = null, // the back button | |
_$thumbs = null, // the content thumbnails | |
_$features = null, // the content features | |
_$allsquares = null, // the grid array squares | |
_gridArray = [], // a temporary array of grid squares | |
_currentFeature = '', // current feature id string | |
_backClass = '', // need to save for restoring class for tracking | |
_isIe = Liferay.Browser.isIe(), | |
_borders = { | |
dt: RUZEE.ShadedBorder.create({corner:4}), | |
dtInner: RUZEE.ShadedBorder.create({corner:4}), | |
dd: RUZEE.ShadedBorder.create({corner:4}), | |
ddInner: RUZEE.ShadedBorder.create({corner:4,border:3}) | |
}, | |
// default settings | |
_defaults = { | |
templates: '', // jquery template file | |
jsondir: '', // json file location | |
params: { | |
brand: 'onstar', // selected brand string | |
lang: 'en_us', // selected language string | |
id: '', // deep linking id string | |
v: '' // video id | |
}, | |
doclib: '', // location of the doclibrary | |
imglib: '' // location of the imglibrary | |
}, | |
// lounge settings object | |
_settings; | |
/** | |
* initialize the lounge | |
* @param {Object} options | |
* @return {Object} jQuery object | |
* @namespace $.fn.lounge | |
*/ | |
function init (options) { | |
// merge options with defaults | |
_settings = $.extend(true, {}, _defaults, options); | |
return this.each(function () { | |
var $this = $(this); | |
// $this is the brand lounge | |
_$lounge = $this; | |
// load the content | |
$this.bind('templatesLoaded', function () { | |
$this.lounge('getLoungeContent'); | |
}); | |
$this.lounge('getLoungeTemplates'); | |
// bind the hashchange event to get lounge content | |
$(window).bind('hashchange', function (e) { | |
$this.lounge('getLoungeContent', e); | |
}); | |
}); | |
} | |
/** | |
* get the query parameters for the content json based on the hash in the url | |
* @param {Object} e The hashchange event object | |
* @return {Object} The query paramaters object | |
* @namespace $.fn.lounge | |
*/ | |
function getQueryParameters (e) { | |
var state = $.bbq.getState(), | |
i; | |
// some defaults | |
state.brand = state.brand || _settings.params.brand; | |
state.lang = state.lang || _settings.params.lang; | |
// get param values from state | |
for (i in _settings.params) { | |
if (_settings.params.hasOwnProperty(i)) { | |
_settings.params[i] = state.hasOwnProperty(i) ? state[i] : ''; | |
} | |
} | |
return _settings.params; | |
} | |
/** | |
* create the grid of 60 squares | |
* @return {Object} jQuery object | |
* @namespace $.fn.lounge | |
*/ | |
function createGrid () { | |
return this.each(function () { | |
var $this = $(this), | |
$gridsquarewrap = $('div.grid-square-wrap'), | |
i; | |
$('img.grid-square', $gridsquarewrap).css({ | |
width: '8px', | |
height: '8px', | |
top: '30px', | |
left: '30px', | |
opacity: 0 | |
}); | |
// remove from #lounge and add 59 squares (for 60 total) | |
$this.remove(); | |
for (i = 0; i < 59; i++) { | |
$gridsquarewrap.clone().appendTo($this); | |
} | |
// reattach and show (still hidden because img opacity == 0) | |
$this.appendTo(_$lounge).show(); | |
// set all squares | |
_$allsquares = $('img.grid-square'); | |
}); | |
} | |
/** | |
* start the grid hover animations | |
* @return {Object} jQuery object | |
* @namespace $.fn.lounge | |
*/ | |
function bindGridHandlers () { | |
return _isIe ? this : this.each(function () { | |
var $this = $(this), | |
shrink = { | |
width: '64px', | |
height: '64px', | |
top: '2px', | |
left: '2px', | |
opacity: 0.05 | |
}, | |
grow = { | |
width: '68px', | |
height: '68px', | |
top: '0px', | |
left: '0px', | |
opacity: 0.2 | |
}, | |
hover = function (e) { | |
var $this = $(this); | |
if (e.type === 'mouseover') { | |
$this.animate(shrink, 200); | |
} else if (e.type === 'mouseout') { | |
$this.animate(grow, 400); | |
} | |
}; | |
$this.delegate('img.grid-square', 'hover', hover); | |
}); | |
} | |
/** | |
* stop the grid hover animations | |
* @return {Object} jQuery object | |
* @namespace $.fn.lounge | |
*/ | |
function unbindGridHandlers () { | |
return _isIe ? this : this.each(function () { | |
$(this).undelegate('img.grid-square', 'hover'); | |
}); | |
} | |
/** | |
* hide grid squares in random order | |
* @param {Array} squares An array of squares or nothing | |
* @param {Function} callback Function on complete | |
* @return {Object} jQuery object | |
* @namespace $.fn.lounge | |
*/ | |
function transitionGridIn (squares, callback) { | |
return this.each(function () { | |
var $squares = squares ? $(squares) : _$allsquares, | |
l = $squares.length, | |
grow = { | |
width: '68px', | |
height: '68px', | |
top: '0px', | |
left: '0px', | |
opacity: 0.2 | |
}, | |
duration = 400; | |
// fade in fixed length | |
$squares.animate(grow, duration, 'swing', function () { | |
if (--l === 0 && callback) { | |
callback(); | |
} | |
}); | |
}); | |
} | |
/** | |
* show grid squares in random order | |
* @param {Array} squares An array of squares or nothing | |
* @param {Function} callback Function on complete | |
* @return {Object} jQuery object | |
* @namespace $.fn.lounge | |
*/ | |
function transitionGridOut (squares, callback) { | |
return this.each(function () { | |
var $squares = squares ? $(squares) : _$allsquares, | |
l = $squares.length, | |
shrink = { | |
width: '8px', | |
height: '8px', | |
top: '30px', | |
left: '30px', | |
opacity: 0 | |
}, | |
duration = 250; | |
// fade out fixed length | |
$squares.animate(shrink, duration += 5, 'swing', function () { | |
if (--l === 0 && callback) { | |
callback(); | |
} | |
}); | |
}); | |
} | |
/** | |
* return an array of grid squares based on position and size | |
* @return {Array} | |
* @namespace $.fn.lounge | |
*/ | |
function getGridArray (width, height, row, col) { | |
var $squares = $('img.grid-square'), | |
rows = [], | |
result = [], | |
idx = (row - 1) * 10 + (col - 1), | |
i, j, k, l; | |
rows.push(idx); | |
for (i = 0; i < height - 1; i++) { | |
idx += 10; | |
rows.push(idx); | |
} | |
for (j = 0, l = rows.length; j < l; j++) { | |
for (k = 0; k < width; k++) { | |
result.push( $squares[rows[j]+k] ); | |
} | |
} | |
return result; | |
} | |
/** | |
* routes to a brand lounge feature | |
* @param {String} id The feature id | |
* @param {String} v Brightcove video id, if in query string | |
* @namespace $.fn.lounge | |
* @private | |
*/ | |
function gotoFeature (id, v) { | |
var $feature = $('#lounge-dd-'+id), | |
layout = $feature.data('layout'), // layout properties | |
$inner = $feature.find('.inner'), | |
$close = $feature.find('.close'), | |
backTracking; | |
// check if current feature | |
if (id === _currentFeature) { | |
// if a video id was passed, trigger the video handler | |
if (v) { | |
$('#video-'+v).trigger('click'); | |
} | |
} else { | |
_currentFeature = id; | |
// set back tracking class | |
backTracking = $.trim( $close.attr('class').replace('close', '') ); | |
_$back.attr('class', _backClass); // reset back class | |
_$back.addClass(backTracking); | |
// stop the slideshows | |
_$lounge.lounge('stopSlideshows'); | |
// set the grid array based on feature layout | |
_gridArray = _$grid.lounge('getGridArray', layout.w, layout.h, layout.row, layout.col); | |
// fade out the grid squares first | |
_$grid.lounge('transitionGridOut', _gridArray, function () { | |
// show the dd (content) | |
_$thumbs.fadeOut('fast', function () { | |
if (_$thumbs.filter(":animated").length === 1) { | |
_$back.fadeIn('fast'); | |
$feature.fadeIn('fast', function () { | |
// create video player if necessary | |
$(window).trigger('createVideoPlayers'); | |
// rounded corners | |
if ( !$feature.data('cornered') ) { | |
_borders.dd.render( $feature ); | |
_borders.ddInner.render( $feature.find('.inner') ); | |
$feature.data('cornered', true); | |
} | |
$inner.animate({ | |
top: '-6px', | |
left: '6px' | |
}, 200); | |
}); | |
} | |
}); | |
}); | |
} | |
return true; | |
} | |
/** | |
* routes to thumbnails view | |
* @namespace $.fn.lounge | |
* @private | |
*/ | |
function gotoThumbnails () { | |
if (_currentFeature) { | |
_currentFeature = ""; | |
var $inners = _$features.find('.inner'); | |
// close out video players | |
$(window).trigger('closeVideoPlayers'); | |
_$back.fadeOut('fast'); | |
_$features.fadeOut('fast', function () { | |
// reset the .inner div position | |
$inners.css({ | |
top: '0px', | |
left: '0px' | |
}); | |
}); | |
// begin slideshow aimations | |
_$lounge.lounge('startSlideshows'); | |
// fade in the grid elements here | |
_$lounge.lounge('transitionGridIn', _gridArray, function () { | |
_$thumbs.fadeIn('fast'); | |
}); | |
} | |
return true; | |
} | |
/** | |
* bind the click and hover handlers for the content blocks | |
* @return {Object} jQuery object | |
* @namespace $.fn.lounge | |
*/ | |
function bindLoungeHandlers () { | |
return this.each(function () { | |
var $this = $(this); | |
// click handlers for displaying and hiding content divs | |
$this.delegate('dt', 'click', function () { | |
var $thumb = $(this), | |
id = $thumb.attr('id'), | |
linkid = id.replace('lounge-dt-', ''); | |
// set the hash id | |
$.bbq.pushState({id: linkid}, 2); | |
}); | |
$this.delegate('div.back, div.close', 'click', function () { | |
// set the hash id | |
$.bbq.pushState({}, 2); | |
}); | |
// hover effects | |
$this.delegate('dt', 'hover', function (e) { | |
var $this = $(this), | |
$inner = $this.find('.inner'); | |
if (e.type === 'mouseover') { | |
$inner.stop().animate({ | |
top: '-6px', | |
left: '6px' | |
}, 200); | |
} else if (e.type === 'mouseout') { | |
$inner.stop().animate({ | |
top: '0px', | |
left: '0px' | |
}, 200); | |
} | |
}); | |
// begin slideshow aimations | |
$this.lounge('startSlideshows'); | |
}); | |
} | |
/** | |
* unbind the lounge handlers | |
* @return {Object} jQuery object | |
* @namespace $.fn.lounge | |
*/ | |
function unbindLoungeHandlers () { | |
return this.each(function () { | |
var $this = $(this); | |
$this.undelegate('dt'); | |
$this.undelegate('div.back'); | |
}); | |
} | |
/** | |
* start up any slideshows | |
* @return {Object} jQuery object | |
* @namespace $.fn.lounge | |
*/ | |
function startSlideshows () { | |
return this.each(function () { | |
var $this = $(this), | |
$slideshows = $('.slideshow', $this); | |
$slideshows.each(function () { | |
var $this = $(this), | |
$slides = $('.slide', $this), | |
interval = $this.data('interval'), | |
$now, $next; | |
// don't set a new interval if one exists | |
if (interval) { | |
return; | |
} | |
// hide all but the first slide | |
$slides.show().slice(1).hide(); | |
// set an interval to loop through slides | |
interval = setInterval(function () { | |
$now = $slides.filter(':visible'); | |
$next = $now.nextAll('.slide').eq(0); | |
if (!$next.length) { | |
$next = $slides.eq(0); | |
} | |
$now.fadeOut(); | |
$next.fadeIn(); | |
}, 1800); | |
// save the interval id on the slideshow | |
$this.data('interval', interval); | |
}); | |
}); | |
} | |
/** | |
* stop any slideshows | |
* @return {Object} jQuery object | |
* @namespace $.fn.lounge | |
*/ | |
function stopSlideshows () { | |
return this.each(function () { | |
var $this = $(this), | |
$slideshows = $('.slideshow', $this); | |
$slideshows.each(function () { | |
var $this = $(this), | |
interval = $this.data('interval'); | |
// if there is an interval on the slideshow, clear it | |
if (interval) { | |
clearInterval(interval); | |
$this.data('interval', null); | |
} | |
}); | |
}); | |
} | |
/** | |
* get the lounge templates and append to the body | |
* @return {Object} jQuery object | |
* @namespace $.fn.lounge | |
*/ | |
function getLoungeTemplates () { | |
return this.each(function () { | |
var $this = $(this); | |
$.get(_settings.templates, function (data) { | |
$('body').append(data); | |
$this.trigger('templatesLoaded'); | |
}); | |
}); | |
} | |
/** | |
* load the lounge content from a json file, and parse with jQuery template | |
* @param {Object} e The hashchange event object | |
* @return {Object} jQuery object | |
* @namespace $.fn.lounge | |
*/ | |
function getLoungeContent (e) { | |
var json, params = getQueryParameters(e); | |
// skip loading if we're already here | |
if (_$lounge.data('brand') === params.brand && _$lounge.data('lang') === params.lang) { | |
// if there is a deep-linking id, trigger handler | |
if (params.id) { | |
gotoFeature(params.id, params.v); // pass id and, if exists, video id | |
} else { | |
gotoThumbnails(); | |
} | |
return this; | |
} | |
// set the json url | |
json = _settings.jsondir + params.brand + '-' + params.lang + '.json'; | |
return this.each(function () { | |
// get default json | |
$.ajax({ | |
url: json, | |
dataType: 'json', | |
success: function (json) { | |
// set lounge data | |
_$lounge.data('brand', params.brand); | |
_$lounge.data('lang', params.lang); | |
// back to home, if after initial load | |
if (_$features) { | |
$.bbq.pushState({}, 2); | |
} | |
if (json) { | |
// switch up bg if there is one in the file | |
if (json.background) { | |
_$lounge.css('background-image', "url('" + json.background.src + "')"); | |
} | |
// apply the jquery template to the rest | |
_$lounge.lounge('unbindLoungeHandlers'); | |
_$lounge.html( $("#loungeTemplate").tmpl(json) ); | |
_$lounge.lounge('bindLoungeHandlers'); | |
// set collections | |
_$thumbs = $('dt', _$lounge); | |
_$features = $('dd', _$lounge).each(function () { | |
// parse the class for layout properties | |
var $feature = $(this), | |
layout = $feature.attr('class'); | |
$feature.data('layout', { | |
w: layout.match(/w\-(\d+)/)[1], | |
h: layout.match(/h\-(\d+)/)[1], | |
row: layout.match(/row\-(\d+)/)[1], | |
col: layout.match(/col\-(\d+)/)[1] | |
}); | |
}); | |
// set up videos queue | |
$(window).trigger('setupVideosQueue'); | |
// the background (display) grid | |
_$grid = $('div.grid', _$lounge); | |
_$grid.lounge('createGrid').lounge('bindGridHandlers').lounge('transitionGridIn'); | |
// the content div, which rests over the grid | |
$('.lounge-content', _$lounge).fadeIn('fast'); | |
// the back button | |
_$back = $('div.back', _$lounge); | |
_backClass = _$back.attr('class'); | |
// run the cufon replacement on new content | |
if (Cufon.replaceAll) { | |
Cufon.replaceAll(); | |
} | |
// rounded corners on thumbs | |
_borders.dt.render( _$thumbs ); | |
_borders.dtInner.render( _$thumbs.find('.inner') ); | |
// if there is a deep-linking id, go to feature | |
if (params.id) { | |
gotoFeature(params.id, params.v); | |
} | |
} | |
}, | |
error: function (xhr, status, e) { | |
// back to defaults | |
$.bbq.pushState({}, 2); | |
} | |
}); | |
}); | |
} | |
// public interface | |
return { | |
'init': init, | |
'bindGridHandlers': bindGridHandlers, | |
'bindLoungeHandlers': bindLoungeHandlers, | |
'createGrid': createGrid, | |
'getGridArray': getGridArray, | |
'getLoungeContent': getLoungeContent, | |
'getLoungeTemplates': getLoungeTemplates, | |
'startSlideshows': startSlideshows, | |
'stopSlideshows': stopSlideshows, | |
'transitionGridIn': transitionGridIn, | |
'transitionGridOut': transitionGridOut, | |
'unbindGridHandlers': unbindGridHandlers, | |
'unbindLoungeHandlers': unbindLoungeHandlers | |
}; | |
}()); | |
/** | |
* brand lounge plugin controller function; determines which plugin method | |
* to call; if blank or an options object is passed in, calls init | |
* @param {String} method The method name | |
* @return {*} The result of the method | |
* @namespace $.fn | |
*/ | |
function lounge (method) { | |
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.lounge' ); | |
return this; | |
} | |
} | |
// extend the jQuery prototype | |
$.extend($.fn, {'lounge': lounge}); | |
}(jQuery, this, Liferay, Cufon, brightcove, APIModules, RUZEE)); | |
/*! | |
* VideoPlayer - Brightcove API Wrapper | |
* | |
* Copyright (c) 2011 Digitas | |
* All Rights Reserved. | |
*/ | |
/** | |
* Create and manipulate brightcove video players using HTML controls | |
* | |
* Dependencies: http://admin.brightcove.com/js/BrightcoveExperiences.js , | |
* http://admin.brightcove.com/js/APIModules_all.js | |
* | |
* @author Matthew Cobbs <matthew.cobbs@digitas.com> | |
*/ | |
/*global jQuery, brightcove, APIModules */ | |
(function ($, window, brightcove, APIModules) { | |
var document = window.document, | |
_videosQueue = {}, // a hash for video player stuff | |
_isIE = Liferay.Browser.isIe(), | |
console = window.console || {log: function () {}}; | |
/** | |
* constructor function for video players | |
* @param {String} playerID The brightcove player id | |
* @private | |
*/ | |
function VideoPlayer(playerID) { | |
// brightcove stuff | |
this.id = playerID; | |
this.player = null; | |
this.controls = null; | |
this.scrollIndex = 0; | |
this.scrollMaxIndex = 0; | |
// DOM stuff | |
this.$player = $('.videos-'+this.id); | |
this.$videos = this.$player.parents('.videos').eq(0); | |
this.$note = this.$videos.find('.videos-note'); | |
this.$subtitle = this.$videos.find('.videos-subtitle').eq(0); | |
this.subtitleHtml = this.$subtitle.html(); | |
this.$thumbsDiv = this.$videos.find('.videos-thumbs'); | |
this.$thumbs = this.$videos.find('.videos-thumb'); | |
this.$prev = this.$videos.find('.videos-prev'); | |
this.$next = this.$videos.find('.videos-next'); | |
// check | |
this.hasThumbs = this.$thumbs.length > 0; | |
// get started | |
this.init(); | |
} | |
/** | |
* init | |
*/ | |
VideoPlayer.prototype.init = function () { | |
if (this.hasThumbs) { | |
this.scrollMaxIndex = this.$thumbs.length - 3; | |
this.$thumbsDiv.css({'left': '0px', 'display': 'block'}); | |
this.bindHandlers(); | |
this.prevNextCheck(); | |
} | |
// fix this, there is no history | |
var state = $.bbq.getState(); | |
if (state.data && state.data.v) { | |
this.playVideo(state.data.v); | |
} else { | |
this.playVideo(); | |
} | |
}; | |
/** | |
* event listeners | |
*/ | |
VideoPlayer.prototype.bindHandlers = function () { | |
var self = this; // inside event handlers | |
if (this.hasThumbs) { | |
this.$thumbs.unbind('click').click(function () { | |
var id = $(this).attr('id').replace('video-', ''); | |
self.playVideo(id); | |
return true; | |
}); | |
this.$prev.unbind('click').click(function () { | |
if (self.scrollIndex <= 0) { | |
return; | |
} | |
self.scrollTo( --self.scrollIndex ); | |
}); | |
this.$next.unbind('click').click(function () { | |
if (self.scrollIndex >= self.scrollMaxIndex) { | |
return; | |
} | |
self.scrollTo( ++self.scrollIndex ); | |
}); | |
} | |
}; | |
/** | |
* unbind event listeners when removing brightcove players | |
*/ | |
VideoPlayer.prototype.unbindHandlers = function () { | |
if (this.hasThumbs) { | |
this.$thumbs.unbind('click'); | |
this.$prev.unbind('click'); | |
this.$next.unbind('click'); | |
} | |
}; | |
/** | |
* set controls from brightcove API | |
* | |
* Throws an error if controls fail to load | |
*/ | |
VideoPlayer.prototype.setControls = function () { | |
this.player = brightcove.getExperience(this.id); | |
if (this.player.type === 'flash') { | |
this.controls = this.player.getModule(APIModules.VIDEO_PLAYER); | |
} else { // html, create a shim | |
var self = this, | |
$newPlayer = _videosQueue[self.id].clone.clone(); | |
this.controls = { | |
'loadVideo': function (id) { | |
brightcove.removeExperience(self.id); | |
$newPlayer.append('<param name="@videoPlayer" value="' + id + '" />'); | |
self.$player.prepend($newPlayer); | |
_videosQueue[self.id].skipInit = true; | |
brightcove.createExperience($newPlayer[0], $newPlayer[0].parentNode, true); | |
}, | |
'pause': function () { | |
brightcove.removeExperience(self.id); | |
self.$player.prepend($newPlayer); | |
} | |
}; | |
} | |
if (!this.controls) { | |
throw new Error('Failed to load controls from Brightcove API'); | |
} | |
return true; // success | |
}; | |
/** | |
* play the video with the matching id | |
* @param {String} videoID The brightcove video id | |
*/ | |
VideoPlayer.prototype.playVideo = function (videoID) { | |
var $thumb, subtitle, index; | |
if (this.hasThumbs) { | |
if (videoID) { | |
$thumb = this.$thumbs.filter('#video-'+videoID); | |
index = this.$thumbs.index($thumb); | |
} else { | |
// get the first video id | |
$thumb = this.$thumbs.eq(0); | |
index = 0; | |
videoID = ($thumb.attr('id') || "").replace('video-', ''); | |
} | |
} | |
try { | |
if (this.setControls() && videoID) { | |
this.controls.loadVideo(videoID); | |
if (this.hasThumbs) { | |
// switch in the subtitle and add playing class | |
subtitle = $thumb.find('.videos-subtitle').html(); | |
this.$thumbs.removeClass('playing'); | |
this.$note.hide(); | |
this.$subtitle.html(subtitle); | |
$thumb.addClass('playing'); | |
// scroll to index of thumb, or max if less | |
if (index < this.scrollIndex || index > this.scrollIndex + 2) { | |
this.scrollIndex = index; | |
if (this.scrollIndex > this.scrollMaxIndex) { | |
this.scrollIndex = this.scrollMaxIndex; | |
} | |
this.scrollTo(this.scrollIndex); | |
} | |
} | |
} | |
} catch (ex) { | |
console.log(ex); | |
} | |
}; | |
/** | |
* scroll thumbs to an index | |
*/ | |
VideoPlayer.prototype.scrollTo = function (index) { | |
if (this.hasThumbs) { | |
if (_isIE) { | |
this.$thumbsDiv.css({ | |
'left': (-index * 158) + 'px' | |
}); | |
} else { | |
this.$thumbsDiv.stop().animate({ | |
'left': (-index * 158) + 'px' | |
}, 100); | |
} | |
this.prevNextCheck(); | |
} | |
}; | |
/** | |
* check whether prev and next arrows should be disabled | |
*/ | |
VideoPlayer.prototype.prevNextCheck = function () { | |
if (this.hasThumbs) { | |
if (this.scrollIndex === 0) { | |
this.$prev.addClass('videos-prev-disabled'); | |
} else { | |
this.$prev.removeClass('videos-prev-disabled'); | |
} | |
if (this.scrollIndex === this.scrollMaxIndex) { | |
this.$next.addClass('videos-next-disabled'); | |
} else { | |
this.$next.removeClass('videos-next-disabled'); | |
} | |
this.$prev.show(); | |
this.$next.show(); | |
} | |
}; | |
/** | |
* close out video player and reset player state | |
*/ | |
VideoPlayer.prototype.close = function () { | |
try { | |
if (this.setControls()) { | |
// stop playing video, unbind playlist handlers | |
this.controls.stop(); | |
this.unbindHandlers(); | |
// remove experience, replace with original html | |
brightcove.removeExperience(this.id); | |
this.$player.append(_videosQueue[this.id].clone.clone()); | |
// reset display back to starting content | |
this.$thumbs.removeClass('playing'); | |
this.$subtitle.html(this.subtitleHtml); | |
this.$note.show(); | |
Cufon.replaceAll(); | |
} | |
} catch (ex) { | |
console.log(ex); | |
} | |
}; | |
/** | |
* add all players on page to videos queue | |
* @namespace VideoPlayer | |
* @private | |
*/ | |
function setupVideosQueue() { | |
$('.BrightcoveExperience').each(function () { | |
var $this = $(this), | |
playerID = $this.attr('id'); | |
// test html5 | |
//$this.append('<param name="forceHTML5" value="true" />'); | |
// add secure parameter to videos if https | |
if (document.location.protocol === 'https:') { | |
//$this.append('<param name="secureConnections" value="true" />'); | |
} | |
_videosQueue[playerID] = {clone: $this.clone()}; | |
}); | |
} | |
$(window).bind('setupVideosQueue', setupVideosQueue); | |
/** | |
* create brightcove video player | |
* @param {String} playerID The brightcove player id | |
* @namespace VideoPlayer | |
* @private | |
*/ | |
function setupVideoPlayer (playerID) { | |
if (_videosQueue[playerID] && _videosQueue[playerID].skipInit) { | |
// skipping init for html5 | |
_videosQueue[playerID].skipInit = false; | |
} else { | |
if (_videosQueue[playerID].player) { | |
_videosQueue[playerID].player.init(); | |
} else { | |
_videosQueue[playerID].player = new VideoPlayer(playerID); | |
} | |
} | |
} | |
// brightcove on template loaded handler | |
window.onTemplateLoaded = function (id) { | |
setupVideoPlayer(id); | |
}; | |
/** | |
* pause and reset all brightcove videos, before closing feature | |
* @namespace VideoPlayer | |
* @private | |
*/ | |
function closeVideoPlayers () { | |
for (var i in _videosQueue) { | |
if (_videosQueue.hasOwnProperty(i) && _videosQueue[i].player) { | |
if (_videosQueue[i].player.$player.is(':visible')) { | |
_videosQueue[i].player.close(); | |
} | |
} | |
} | |
} | |
$(window).bind('closeVideoPlayers', closeVideoPlayers); | |
/** | |
* create all visible video players | |
* @namespace VideoPlayer | |
* @private | |
*/ | |
function createVideoPlayers() { | |
$('.BrightcoveExperience').filter(':visible').each(function () { | |
var player = this, | |
playerContainer = this.parentNode; | |
brightcove.createExperience(player, playerContainer, true); | |
}); | |
} | |
$(window).bind('createVideoPlayers', createVideoPlayers); | |
}(jQuery, this, brightcove, APIModules)); | |
/** | |
* Miscellaneous helpers | |
* | |
* Dependencies: cufon-yui.js | |
* | |
* @author Matthew Cobbs <matthew.cobbs@digitas.com> | |
*/ | |
/*global Cufon */ | |
(function (window, Cufon) { | |
// Cufon | |
Cufon.replaceAll = function () { | |
Cufon.replace('.gothamMedium', {fontFamily: 'Gotham-Medium'}); | |
Cufon.replace('.gothamBold', {fontFamily: 'Gotham-Bold'}); | |
Cufon.replace('.gothamBook', {fontFamily: 'Gotham-Book'}); | |
}; | |
Cufon.replaceAll(); | |
}(this, Cufon)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* jQuery.browser.mobile (http://detectmobilebrowser.com/) | |
* | |
* jQuery.browser.mobile will be true if the browser is a mobile device | |
* | |
**/ | |
(function(a){jQuery.browser.mobile=/android.+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|meego.+mobile|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))})(navigator.userAgent||navigator.vendor||window.opera); | |
// ## Onstar Tracking - Omniture Module | |
// | |
// Copyright (c) 2011 Digitas | |
// All Rights Reserved. | |
// | |
// Allows DOM event tracking through Omniture using JSON objects | |
// The typical approach is to pass a tracking object with IDs for each | |
// specific event type and action to track. | |
// | |
// *Dependencies*: [Omniture](http://www.omniture.com), [jQuery 1.4.2+](http://www.jquery.com), [Liferay](http://www.liferay.com) | |
// | |
// @name OnstarTracking | |
// @author Matthew Cobbs <matthew.cobbs@digitas.com> | |
// @modifiedBy Jair Reina <jair.reina@boszdigital.com> | |
// | |
/*global jQuery, s_account, s_gi, Liferay*/ | |
(function ($, window, Liferay) { | |
var document = window.document, // set reference to window document | |
_s = null; // omniture tracking object | |
// ## Constructor and Prototype Setup | |
// | |
// Set up a private `OnstarTracking` constructor to be used to create | |
// the global `OnstarTracking` instance. This is followed by the | |
// prototype, which holds all of the shared methods and variables | |
// between each instance. The prototype is created using an | |
// immediately-invoked function expression that returns an object | |
// holding the publicly accessible member methods and properties. | |
// | |
// @param {Object} [options] Optional instance settings object | |
// @return {OnstarTracking} | |
// @constructor | |
var OnstarTracking = function (options) { | |
if (!(this instanceof OnstarTracking)) { | |
return new OnstarTracking(options); // make sure this is a new instance | |
} else { | |
this.lang = null; // language val for prop4 | |
this.tracking = {}; // tracking data grouped into hashes by event type | |
this.events = {}; // a hash of all event types the document is listening for | |
this.settings = {}; // module settings | |
this.trackFilter = null; // OnstarTracking select filter | |
this.trackRegex = null; // OnstarTracking regex | |
return OnstarTracking.prototype.init.call(this, arguments); | |
} | |
}; | |
OnstarTracking.prototype = (function () { | |
// *Declare Private Variables* | |
// | |
// These private variables are inaccessible to external code and will | |
// persist between different `OnstarTracking` instances | |
var _defaults = { // module defaults | |
defaultTrack: 'link', // default track type | |
defaultEvent: 'click', // default event type | |
defaultLang: 'us_en', // default langauge | |
trackClass: 'otrack', // OnstarTracking document class name | |
namespace: '.otrack', // event namespace | |
clearProps: "prop1 prop2 prop3 prop4 prop5 prop6 prop7 prop8 prop9 prop10 prop11 prop12 prop13 prop14 prop15 prop16 prop17 prop18 prop19 prop25 eVar22 events" // properties to clear before tacking events | |
}; | |
// ###getLanguage | |
// | |
// *Get the language setting from Liferay* | |
// | |
// @return {String} | |
// @namespace OnstarTracking | |
// @private | |
function getLanguage () { | |
var liferayLang, lang, liferayToOmniture; | |
liferayToOmniture = { | |
'en_us': 'us_en', | |
'es_us': 'us_sp', | |
'en_ca': 'ca_en', | |
'fr_ca': 'ca_fr' | |
}; | |
liferayLang = Liferay && Liferay.ThemeDisplay.getLanguageId().toLowerCase(); | |
lang = liferayToOmniture[liferayLang] || this.settings.defaultLang; | |
return lang; | |
} | |
// ###getDeviceType | |
// | |
// *Gets the device type where the page is being rendered it could be: | |
// MOBILE | |
// DESKTOP | |
// | |
// @return {String} | |
// @deviceType Mobile Device Type | |
// @private | |
function getDeviceType () { | |
var deviceType = "DESKTOP"; | |
if($.browser.mobile) | |
deviceType = "MOBILE"; | |
return deviceType; | |
} | |
// `_tags` and `_tagsRegExp` are used to set dynamic properties at | |
// run time. Any of these tags can be used in any tracking object | |
// property | |
var _tagsRegExp = /{\w+\}/g; | |
var _propertyRegExp = /\jQuery:|\|/g; | |
var _idRegExp = /jQuery:(.*?)(\||$)/g; | |
// if somebody needs a custom tag, it should be defined here following the same pattern: | |
// "{tagName}: functionThatReturnsTheValueForThisTag" | |
var _tags = { | |
"{lang}": getLanguage, | |
"{deviceType}": getDeviceType, | |
}; | |
// ###getTag | |
// | |
// *Get the value of a dynamic tag from the `_tags` object, using | |
// `val` as the index for lookup* | |
// | |
// @retrun {String} | |
// @namespace OnstarTracking | |
// @private | |
function getTagValue(val) { | |
var result = "", | |
fn; | |
if (_tags.hasOwnProperty(val)) { | |
fn = _tags[val]; | |
result = fn(); | |
} | |
return result; | |
} | |
// ###getLinkTrackVars | |
// | |
// *Get a list of link tracking props from `props` keys.* | |
// This is used to set the `linkTrackVars` property before making a | |
// call to Omniture | |
// | |
// @param {Object} props The properties object | |
// @return {String} | |
// @namespace OnstarTracking | |
// @private | |
function getLinkTrackVars (props) { | |
var linkVars = [], i; | |
for (i in props) { | |
if (props.hasOwnProperty(i)) { | |
linkVars.push(i); | |
} | |
} | |
return linkVars.join(','); | |
} | |
// ###clearTracking | |
// | |
// *Clear tracking variables.* Txhis is used to clear out the value of | |
// properties before each call to Omniture | |
// | |
// @namespace OnstarTracking | |
// @private | |
function clearTracking () { | |
var i, l, prop; | |
for (i = 0, l = this.settings.clearProps.length; i < l; i++) { | |
prop = this.settings.clearProps[i]; | |
_s[prop] = ""; | |
} | |
} | |
// ###trackEvent | |
// | |
// *Trigger omniture tracking event.* This function is used internally | |
// to pass a set of properties to track to Omniture | |
// | |
// @param {Object} props The event properties | |
// @param {Event} [e] Optional event object | |
// @namespace OnstarTracking | |
// @private | |
function trackEvent (props, e) { | |
if (!_s) { | |
_s = s_gi(s_account); | |
} | |
$.proxy(clearTracking, this)(); | |
$.extend(_s, props); | |
if (props._track === 'page') { | |
_s.t(); | |
} else { | |
_s.tl(true, 'o', 'link tracking'); | |
} | |
if (window.console) { | |
console.log(props._track, props._event, props); | |
} | |
} | |
// ###addDocumentListener | |
// | |
// *Bind a new event type handler to the document.* | |
// This is called after the tracking action objects have been added | |
// to OnstarTracking. If the `type` has not been passed yet, a new | |
// delegated handler is attached to the document to watch for events | |
// of that type | |
// | |
// @param {String} type The event type name | |
// @namespace OnstarTracking | |
// @private | |
function addDocumentListener (type) { | |
var self = this; | |
if (!this.events.hasOwnProperty(type)) { | |
$(document).delegate(this.trackFilter, type + this.settings.namespace, function (e) { | |
// Match the tracking class | |
var match = this.className.match(self.trackRegex); | |
if (match) { | |
self.track(type, match[0], e); | |
} | |
}); | |
// Add event type to hash to prevent adding another handler | |
// to the document | |
this.events[type] = true; | |
} | |
} | |
// ##Return the public interface | |
return { | |
// ###init | |
// | |
// *Sets or resets module settings using an options hash, sets the | |
// current language, and initializes the Omniture object.* | |
// This method can be used externally to update the internal options | |
// used by this module. For example, if there are additional properties | |
// to clear, you may pass an updated `clearProps` property | |
// | |
// @param {Object} options An object with module settings overrides | |
// @namespace OnstarTracking | |
init: function (options) { | |
this.settings = $.extend({}, _defaults, options || {}); | |
if (typeof this.settings.clearProps === "string") { | |
this.settings.clearProps = this.settings.clearProps.split(" "); | |
} | |
this.lang = $.proxy(getLanguage, this)(); | |
this.trackFilter = "." + this.settings.trackClass; | |
this.trackRegex = new RegExp(this.settings.trackClass + "\\-\\d+"); | |
}, | |
// ###add | |
// | |
// *Add a hash of tracking events to be monitored.* | |
// The keys of the object should be the tracking classes | |
// used in the document | |
// | |
// @param {Object} o The hash of tracking events | |
// @namespace OnstarTracking | |
// @example | |
// OnstarTracking.add({ | |
// "otrack-00006": { | |
// "pageName": "ONSTAR | NEW SERVICES MODULE | CHEVROLET", | |
// "prop1": "NEW SERVICES MODULE", | |
// "prop2": "CHEVROLET", | |
// "prop3": "NEW SERVICES MODULE | CHEVROLET", | |
// "prop4": "<<language>>", | |
// "prop16": "NEW SERVICES MODULE | CHEVROLET | PAGE LOAD", | |
// "prop25": "ONSTAR", | |
// "_track": "page", | |
// "_event": "load" | |
// }, | |
// "otrack-00010": { | |
// "prop1": "NEW SERVICES MODULE", | |
// "prop2": "CHEVROLET", | |
// "prop3": "NEW SERVICES MODULE | CHEVROLET", | |
// "prop4": "<<language>>", | |
// "prop16": "NEW SERVICES MODULE | CHEVROLET | EXPERIENCE ON", | |
// "getTagValue5": "ONSTAR" | |
// }); | |
// | |
// This adds two actions to the `OnstarTracking` hash. The first object is tracked | |
// automatically on page load, because `_event = "load"`. The `_track` property is | |
// set to `"page"` to make this an `s.t()` call. The second object is tracked as a | |
// `"click"` action, because the `_event` default is `"click"`. Because there is no | |
// `_track` property on the second object, the default of an `s.tl()` call is used. | |
// | |
// Tracking objects can contain any of the properties used in Omniture tracking | |
// calls. `prop4` will be overwritten with the current language by this module. | |
// `linkTrackVars` is automatically compiled by the module, so it is not necessary | |
// to pass it in. | |
add : function (o) { | |
var i, props; | |
for (i in o) { | |
if (o.hasOwnProperty(i)) { | |
props = o[i]; // get the tracking event | |
props.prop4 = this.lang; // set language | |
props.linkTrackVars = getLinkTrackVars(props); | |
props._track = props._track || this.settings.defaultTrack; // set the track type | |
props._event = props._event || this.settings.defaultEvent; // set the event type | |
// Add tracking event to hash | |
this.tracking[props._event] = this.tracking[props._event] || {}; | |
this.tracking[props._event][i] = props; | |
if (props._event === "load" && (document.getElementById(i))) { | |
// Immediately track load actions | |
this.track(props._event, i); | |
props._tracked = true; | |
} else { | |
// Otherwise, add listener | |
$.proxy(addDocumentListener, this)(props._event); | |
} | |
} | |
} | |
}, | |
// ###remove | |
// | |
// *Remove tracking events.* If you pass no arguments, this method | |
// removes all tracking events from the module. If you pass only | |
// `eventType`, this method removes all tracking events with that | |
// type. If you pass both `eventType` and `eventID`, this method | |
// removes only that specific tracking event. | |
// | |
// @param {String} [eventType] The optional type of event (e.g. click) | |
// @param {String} [eventID] The optional id of the tracking event | |
// @namespace OnstarTracking | |
// | |
// @example OnstarTracking.remove('click', 'otrack-98765'); | |
// @example OnstarTracking.remove('click'); | |
// @example OnstarTracking.remove(); | |
remove: function (eventType, eventID) { | |
var hash; | |
if (typeof eventType === "undefined" && typeof eventID === "undefined") { | |
this.tracking = {}; | |
this.events = {}; | |
$(document).unbind(this.trackFilter, this.settings.namespace); | |
} else if (typeof eventType !== "undefined" && typeof eventID === "undefined") { | |
delete this.tracking[eventType]; | |
delete this.events[eventType]; | |
$(document).undelegate(this.trackFilter, eventType + this.settings.namespace); | |
} else if (typeof eventType !== "undefined" && typeof eventID !== "undefined") { | |
hash = this.tracking[eventType]; | |
if (hash) { | |
delete hash[eventID]; | |
} | |
} | |
}, | |
// ###track | |
// | |
// *Track an event by pulling the properties by `eventID` | |
// out of the `_tracking[eventType]` hash.* | |
// This method can also be used externally to track events | |
// without DOM interaction. This will trigger tracking on events | |
// already added to the `OnstarTracking` module | |
// | |
// @param {String} eventType The type of event (e.g. click) | |
// @param {String} eventID The id of the tracking event | |
// @param {Event} [e] Optional event object | |
// @namespace OnstarTracking | |
// | |
// @example OnstarTracking.track('click', 'otrack-98765'); | |
track: function (eventType, eventID, e) { | |
var hash, props, i, target; | |
hash = this.tracking[eventType]; | |
// Gets the element that has been clicked | |
if (typeof e != "undefined") { | |
target = (e.currentTarget) ? e.currentTarget : e.srcElement; | |
} | |
if (hash) { | |
props = hash[eventID]; | |
if (props) { | |
// Deep copy of 'props' | |
var parsedProps = jQuery.extend(true, {}, props); | |
// replace dynamic tags | |
for (i in props) { | |
var propVal = props[i]; | |
// props[i] can either be a string or a function | |
if (typeof propVal == "string") { | |
// If it has "[", it means we're asking for a property on the element | |
if (propVal.indexOf("[") != -1) { | |
parsedProps[i] = propVal.replace(_propertyRegExp, function (val) { | |
return target[val]; | |
}); | |
} else { | |
// If there's a jQuery:, it means we're asking for the contents of some element | |
// using a jQuery selector | |
if (propVal.indexOf("jQuery:") != -1) { | |
parsedProps[i] = propVal.replace(_idRegExp, function (val) { | |
val = val.replace("jQuery:", "").replace("|", ""); | |
var text = $(val).text(); | |
if (text == "") { | |
text = $(val).val(); | |
} | |
return text; | |
}); | |
} else { | |
parsedProps[i] = props[i].replace(_tagsRegExp, function (val) { | |
return getTagValue(val); | |
}); | |
} | |
} | |
} else { | |
parsedProps[i] = (props[i](target)).toUpperCase(); | |
} | |
} | |
$.proxy(trackEvent, this)(parsedProps, e); | |
} | |
} | |
} | |
}; | |
})(); | |
// Initialize the module instance and return to the window | |
window.OnstarTracking = new OnstarTracking(); | |
// Set internal Omniture module reference | |
$(document).ready(function () { | |
_s = s_gi(s_account); | |
}); | |
})(jQuery, this, Liferay); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment