/*!
* jQuery Cycle2; version: 2.1.5 build: 20140415
* http://jquery.malsup.com/cycle2/
* Copyright (c) 2014 M. Alsup; Dual licensed: MIT/GPL
*/
!function(a){"use strict";function b(a){return(a||"").toLowerCase()}var c="2.1.5";a.fn.cycle=function(c){var d;return 0!==this.length||a.isReady?this.each(function(){var d,e,f,g,h=a(this),i=a.fn.cycle.log;if(!h.data("cycle.opts")){(h.data("cycle-log")===!1||c&&c.log===!1||e&&e.log===!1)&&(i=a.noop),i("--c2 init--"),d=h.data();for(var j in d)d.hasOwnProperty(j)&&/^cycle[A-Z]+/.test(j)&&(g=d[j],f=j.match(/^cycle(.*)/)[1].replace(/^[A-Z]/,b),i(f+":",g,"("+typeof g+")"),d[f]=g);e=a.extend({},a.fn.cycle.defaults,d,c||{}),e.timeoutId=0,e.paused=e.paused||!1,e.container=h,e._maxZ=e.maxZ,e.API=a.extend({_container:h},a.fn.cycle.API),e.API.log=i,e.API.trigger=function(a,b){return e.container.trigger(a,b),e.API},h.data("cycle.opts",e),h.data("cycle.API",e.API),e.API.trigger("cycle-bootstrap",[e,e.API]),e.API.addInitialSlides(),e.API.preInitSlideshow(),e.slides.length&&e.API.initSlideshow()}}):(d={s:this.selector,c:this.context},a.fn.cycle.log("requeuing slideshow (dom not ready)"),a(function(){a(d.s,d.c).cycle(c)}),this)},a.fn.cycle.API={opts:function(){return this._container.data("cycle.opts")},addInitialSlides:function(){var b=this.opts(),c=b.slides;b.slideCount=0,b.slides=a(),c=c.jquery?c:b.container.find(c),b.random&&c.sort(function(){return Math.random()-.5}),b.API.add(c)},preInitSlideshow:function(){var b=this.opts();b.API.trigger("cycle-pre-initialize",[b]);var c=a.fn.cycle.transitions[b.fx];c&&a.isFunction(c.preInit)&&c.preInit(b),b._preInitialized=!0},postInitSlideshow:function(){var b=this.opts();b.API.trigger("cycle-post-initialize",[b]);var c=a.fn.cycle.transitions[b.fx];c&&a.isFunction(c.postInit)&&c.postInit(b)},initSlideshow:function(){var b,c=this.opts(),d=c.container;c.API.calcFirstSlide(),"static"==c.container.css("position")&&c.container.css("position","relative"),a(c.slides[c.currSlide]).css({opacity:1,display:"block",visibility:"visible"}),c.API.stackSlides(c.slides[c.currSlide],c.slides[c.nextSlide],!c.reverse),c.pauseOnHover&&(c.pauseOnHover!==!0&&(d=a(c.pauseOnHover)),d.hover(function(){c.API.pause(!0)},function(){c.API.resume(!0)})),c.timeout&&(b=c.API.getSlideOpts(c.currSlide),c.API.queueTransition(b,b.timeout+c.delay)),c._initialized=!0,c.API.updateView(!0),c.API.trigger("cycle-initialized",[c]),c.API.postInitSlideshow()},pause:function(b){var c=this.opts(),d=c.API.getSlideOpts(),e=c.hoverPaused||c.paused;b?c.hoverPaused=!0:c.paused=!0,e||(c.container.addClass("cycle-paused"),c.API.trigger("cycle-paused",[c]).log("cycle-paused"),d.timeout&&(clearTimeout(c.timeoutId),c.timeoutId=0,c._remainingTimeout-=a.now()-c._lastQueue,(c._remainingTimeout<0||isNaN(c._remainingTimeout))&&(c._remainingTimeout=void 0)))},resume:function(a){var b=this.opts(),c=!b.hoverPaused&&!b.paused;a?b.hoverPaused=!1:b.paused=!1,c||(b.container.removeClass("cycle-paused"),0===b.slides.filter(":animated").length&&b.API.queueTransition(b.API.getSlideOpts(),b._remainingTimeout),b.API.trigger("cycle-resumed",[b,b._remainingTimeout]).log("cycle-resumed"))},add:function(b,c){var d,e=this.opts(),f=e.slideCount,g=!1;"string"==a.type(b)&&(b=a.trim(b)),a(b).each(function(){var b,d=a(this);c?e.container.prepend(d):e.container.append(d),e.slideCount++,b=e.API.buildSlideOpts(d),e.slides=c?a(d).add(e.slides):e.slides.add(d),e.API.initSlide(b,d,--e._maxZ),d.data("cycle.opts",b),e.API.trigger("cycle-slide-added",[e,b,d])}),e.API.updateView(!0),g=e._preInitialized&&2>f&&e.slideCount>=1,g&&(e._initialized?e.timeout&&(d=e.slides.length,e.nextSlide=e.reverse?d-1:1,e.timeoutId||e.API.queueTransition(e)):e.API.initSlideshow())},calcFirstSlide:function(){var a,b=this.opts();a=parseInt(b.startingSlide||0,10),(a>=b.slides.length||0>a)&&(a=0),b.currSlide=a,b.reverse?(b.nextSlide=a-1,b.nextSlide<0&&(b.nextSlide=b.slides.length-1)):(b.nextSlide=a+1,b.nextSlide==b.slides.length&&(b.nextSlide=0))},calcNextSlide:function(){var a,b=this.opts();b.reverse?(a=b.nextSlide-1<0,b.nextSlide=a?b.slideCount-1:b.nextSlide-1,b.currSlide=a?0:b.nextSlide+1):(a=b.nextSlide+1==b.slides.length,b.nextSlide=a?0:b.nextSlide+1,b.currSlide=a?b.slides.length-1:b.nextSlide-1)},calcTx:function(b,c){var d,e=b;return e._tempFx?d=a.fn.cycle.transitions[e._tempFx]:c&&e.manualFx&&(d=a.fn.cycle.transitions[e.manualFx]),d||(d=a.fn.cycle.transitions[e.fx]),e._tempFx=null,this.opts()._tempFx=null,d||(d=a.fn.cycle.transitions.fade,e.API.log('Transition "'+e.fx+'" not found.  Using fade.')),d},prepareTx:function(a,b){var c,d,e,f,g,h=this.opts();return h.slideCount<2?void(h.timeoutId=0):(!a||h.busy&&!h.manualTrump||(h.API.stopTransition(),h.busy=!1,clearTimeout(h.timeoutId),h.timeoutId=0),void(h.busy||(0!==h.timeoutId||a)&&(d=h.slides[h.currSlide],e=h.slides[h.nextSlide],f=h.API.getSlideOpts(h.nextSlide),g=h.API.calcTx(f,a),h._tx=g,a&&void 0!==f.manualSpeed&&(f.speed=f.manualSpeed),h.nextSlide!=h.currSlide&&(a||!h.paused&&!h.hoverPaused&&h.timeout)?(h.API.trigger("cycle-before",[f,d,e,b]),g.before&&g.before(f,d,e,b),c=function(){h.busy=!1,h.container.data("cycle.opts")&&(g.after&&g.after(f,d,e,b),h.API.trigger("cycle-after",[f,d,e,b]),h.API.queueTransition(f),h.API.updateView(!0))},h.busy=!0,g.transition?g.transition(f,d,e,b,c):h.API.doTransition(f,d,e,b,c),h.API.calcNextSlide(),h.API.updateView()):h.API.queueTransition(f))))},doTransition:function(b,c,d,e,f){var g=b,h=a(c),i=a(d),j=function(){i.animate(g.animIn||{opacity:1},g.speed,g.easeIn||g.easing,f)};i.css(g.cssBefore||{}),h.animate(g.animOut||{},g.speed,g.easeOut||g.easing,function(){h.css(g.cssAfter||{}),g.sync||j()}),g.sync&&j()},queueTransition:function(b,c){var d=this.opts(),e=void 0!==c?c:b.timeout;return 0===d.nextSlide&&0===--d.loop?(d.API.log("terminating; loop=0"),d.timeout=0,e?setTimeout(function(){d.API.trigger("cycle-finished",[d])},e):d.API.trigger("cycle-finished",[d]),void(d.nextSlide=d.currSlide)):void 0!==d.continueAuto&&(d.continueAuto===!1||a.isFunction(d.continueAuto)&&d.continueAuto()===!1)?(d.API.log("terminating automatic transitions"),d.timeout=0,void(d.timeoutId&&clearTimeout(d.timeoutId))):void(e&&(d._lastQueue=a.now(),void 0===c&&(d._remainingTimeout=b.timeout),d.paused||d.hoverPaused||(d.timeoutId=setTimeout(function(){d.API.prepareTx(!1,!d.reverse)},e))))},stopTransition:function(){var a=this.opts();a.slides.filter(":animated").length&&(a.slides.stop(!1,!0),a.API.trigger("cycle-transition-stopped",[a])),a._tx&&a._tx.stopTransition&&a._tx.stopTransition(a)},advanceSlide:function(a){var b=this.opts();return clearTimeout(b.timeoutId),b.timeoutId=0,b.nextSlide=b.currSlide+a,b.nextSlide<0?b.nextSlide=b.slides.length-1:b.nextSlide>=b.slides.length&&(b.nextSlide=0),b.API.prepareTx(!0,a>=0),!1},buildSlideOpts:function(c){var d,e,f=this.opts(),g=c.data()||{};for(var h in g)g.hasOwnProperty(h)&&/^cycle[A-Z]+/.test(h)&&(d=g[h],e=h.match(/^cycle(.*)/)[1].replace(/^[A-Z]/,b),f.API.log("["+(f.slideCount-1)+"]",e+":",d,"("+typeof d+")"),g[e]=d);g=a.extend({},a.fn.cycle.defaults,f,g),g.slideNum=f.slideCount;try{delete g.API,delete g.slideCount,delete g.currSlide,delete g.nextSlide,delete g.slides}catch(i){}return g},getSlideOpts:function(b){var c=this.opts();void 0===b&&(b=c.currSlide);var d=c.slides[b],e=a(d).data("cycle.opts");return a.extend({},c,e)},initSlide:function(b,c,d){var e=this.opts();c.css(b.slideCss||{}),d>0&&c.css("zIndex",d),isNaN(b.speed)&&(b.speed=a.fx.speeds[b.speed]||a.fx.speeds._default),b.sync||(b.speed=b.speed/2),c.addClass(e.slideClass)},updateView:function(a,b){var c=this.opts();if(c._initialized){var d=c.API.getSlideOpts(),e=c.slides[c.currSlide];!a&&b!==!0&&(c.API.trigger("cycle-update-view-before",[c,d,e]),c.updateView<0)||(c.slideActiveClass&&c.slides.removeClass(c.slideActiveClass).eq(c.currSlide).addClass(c.slideActiveClass),a&&c.hideNonActive&&c.slides.filter(":not(."+c.slideActiveClass+")").css("visibility","hidden"),0===c.updateView&&setTimeout(function(){c.API.trigger("cycle-update-view",[c,d,e,a])},d.speed/(c.sync?2:1)),0!==c.updateView&&c.API.trigger("cycle-update-view",[c,d,e,a]),a&&c.API.trigger("cycle-update-view-after",[c,d,e]))}},getComponent:function(b){var c=this.opts(),d=c[b];return"string"==typeof d?/^\s*[\>|\+|~]/.test(d)?c.container.find(d):a(d):d.jquery?d:a(d)},stackSlides:function(b,c,d){var e=this.opts();b||(b=e.slides[e.currSlide],c=e.slides[e.nextSlide],d=!e.reverse),a(b).css("zIndex",e.maxZ);var f,g=e.maxZ-2,h=e.slideCount;if(d){for(f=e.currSlide+1;h>f;f++)a(e.slides[f]).css("zIndex",g--);for(f=0;f<e.currSlide;f++)a(e.slides[f]).css("zIndex",g--)}else{for(f=e.currSlide-1;f>=0;f--)a(e.slides[f]).css("zIndex",g--);for(f=h-1;f>e.currSlide;f--)a(e.slides[f]).css("zIndex",g--)}a(c).css("zIndex",e.maxZ-1)},getSlideIndex:function(a){return this.opts().slides.index(a)}},a.fn.cycle.log=function(){window.console&&console.log&&console.log("[cycle2] "+Array.prototype.join.call(arguments," "))},a.fn.cycle.version=function(){return"Cycle2: "+c},a.fn.cycle.transitions={custom:{},none:{before:function(a,b,c,d){a.API.stackSlides(c,b,d),a.cssBefore={opacity:1,visibility:"visible",display:"block"}}},fade:{before:function(b,c,d,e){var f=b.API.getSlideOpts(b.nextSlide).slideCss||{};b.API.stackSlides(c,d,e),b.cssBefore=a.extend(f,{opacity:0,visibility:"visible",display:"block"}),b.animIn={opacity:1},b.animOut={opacity:0}}},fadeout:{before:function(b,c,d,e){var f=b.API.getSlideOpts(b.nextSlide).slideCss||{};b.API.stackSlides(c,d,e),b.cssBefore=a.extend(f,{opacity:1,visibility:"visible",display:"block"}),b.animOut={opacity:0}}},scrollHorz:{before:function(a,b,c,d){a.API.stackSlides(b,c,d);var e=a.container.css("overflow","hidden").width();a.cssBefore={left:d?e:-e,top:0,opacity:1,visibility:"visible",display:"block"},a.cssAfter={zIndex:a._maxZ-2,left:0},a.animIn={left:0},a.animOut={left:d?-e:e}}}},a.fn.cycle.defaults={allowWrap:!0,autoSelector:".cycle-slideshow[data-cycle-auto-init!=false]",delay:0,easing:null,fx:"fade",hideNonActive:!0,loop:0,manualFx:void 0,manualSpeed:void 0,manualTrump:!0,maxZ:100,pauseOnHover:!1,reverse:!1,slideActiveClass:"cycle-slide-active",slideClass:"cycle-slide",slideCss:{position:"absolute",top:0,left:0},slides:"> img",speed:500,startingSlide:0,sync:!0,timeout:4e3,updateView:0},a(document).ready(function(){a(a.fn.cycle.defaults.autoSelector).cycle()})}(jQuery),/*! Cycle2 autoheight plugin; Copyright (c) M.Alsup, 2012; version: 20130913 */
function(a){"use strict";function b(b,d){var e,f,g,h=d.autoHeight;if("container"==h)f=a(d.slides[d.currSlide]).outerHeight(),d.container.height(f);else if(d._autoHeightRatio)d.container.height(d.container.width()/d._autoHeightRatio);else if("calc"===h||"number"==a.type(h)&&h>=0){if(g="calc"===h?c(b,d):h>=d.slides.length?0:h,g==d._sentinelIndex)return;d._sentinelIndex=g,d._sentinel&&d._sentinel.remove(),e=a(d.slides[g].cloneNode(!0)),e.removeAttr("id name rel").find("[id],[name],[rel]").removeAttr("id name rel"),e.css({position:"static",visibility:"hidden",display:"block"}).prependTo(d.container).addClass("cycle-sentinel cycle-slide").removeClass("cycle-slide-active"),e.find("*").css("visibility","hidden"),d._sentinel=e}}function c(b,c){var d=0,e=-1;return c.slides.each(function(b){var c=a(this).height();c>e&&(e=c,d=b)}),d}function d(b,c,d,e){var f=a(e).outerHeight();c.container.animate({height:f},c.autoHeightSpeed,c.autoHeightEasing)}function e(c,f){f._autoHeightOnResize&&(a(window).off("resize orientationchange",f._autoHeightOnResize),f._autoHeightOnResize=null),f.container.off("cycle-slide-added cycle-slide-removed",b),f.container.off("cycle-destroyed",e),f.container.off("cycle-before",d),f._sentinel&&(f._sentinel.remove(),f._sentinel=null)}a.extend(a.fn.cycle.defaults,{autoHeight:0,autoHeightSpeed:250,autoHeightEasing:null}),a(document).on("cycle-initialized",function(c,f){function g(){b(c,f)}var h,i=f.autoHeight,j=a.type(i),k=null;("string"===j||"number"===j)&&(f.container.on("cycle-slide-added cycle-slide-removed",b),f.container.on("cycle-destroyed",e),"container"==i?f.container.on("cycle-before",d):"string"===j&&/\d+\:\d+/.test(i)&&(h=i.match(/(\d+)\:(\d+)/),h=h[1]/h[2],f._autoHeightRatio=h),"number"!==j&&(f._autoHeightOnResize=function(){clearTimeout(k),k=setTimeout(g,50)},a(window).on("resize orientationchange",f._autoHeightOnResize)),setTimeout(g,30))})}(jQuery),/*! caption plugin for Cycle2;  version: 20130306 */
function(a){"use strict";a.extend(a.fn.cycle.defaults,{caption:"> .cycle-caption",captionTemplate:"{{slideNum}} / {{slideCount}}",overlay:"> .cycle-overlay",overlayTemplate:"<div>{{title}}</div><div>{{desc}}</div>",captionModule:"caption"}),a(document).on("cycle-update-view",function(b,c,d,e){if("caption"===c.captionModule){a.each(["caption","overlay"],function(){var a=this,b=d[a+"Template"],f=c.API.getComponent(a);f.length&&b?(f.html(c.API.tmpl(b,d,c,e)),f.show()):f.hide()})}}),a(document).on("cycle-destroyed",function(b,c){var d;a.each(["caption","overlay"],function(){var a=this,b=c[a+"Template"];c[a]&&b&&(d=c.API.getComponent("caption"),d.empty())})})}(jQuery),/*! command plugin for Cycle2;  version: 20140415 */
function(a){"use strict";var b=a.fn.cycle;a.fn.cycle=function(c){var d,e,f,g=a.makeArray(arguments);return"number"==a.type(c)?this.cycle("goto",c):"string"==a.type(c)?this.each(function(){var h;return d=c,f=a(this).data("cycle.opts"),void 0===f?void b.log('slideshow must be initialized before sending commands; "'+d+'" ignored'):(d="goto"==d?"jump":d,e=f.API[d],a.isFunction(e)?(h=a.makeArray(g),h.shift(),e.apply(f.API,h)):void b.log("unknown command: ",d))}):b.apply(this,arguments)},a.extend(a.fn.cycle,b),a.extend(b.API,{next:function(){var a=this.opts();if(!a.busy||a.manualTrump){var b=a.reverse?-1:1;a.allowWrap===!1&&a.currSlide+b>=a.slideCount||(a.API.advanceSlide(b),a.API.trigger("cycle-next",[a]).log("cycle-next"))}},prev:function(){var a=this.opts();if(!a.busy||a.manualTrump){var b=a.reverse?1:-1;a.allowWrap===!1&&a.currSlide+b<0||(a.API.advanceSlide(b),a.API.trigger("cycle-prev",[a]).log("cycle-prev"))}},destroy:function(){this.stop();var b=this.opts(),c=a.isFunction(a._data)?a._data:a.noop;clearTimeout(b.timeoutId),b.timeoutId=0,b.API.stop(),b.API.trigger("cycle-destroyed",[b]).log("cycle-destroyed"),b.container.removeData(),c(b.container[0],"parsedAttrs",!1),b.retainStylesOnDestroy||(b.container.removeAttr("style"),b.slides.removeAttr("style"),b.slides.removeClass(b.slideActiveClass)),b.slides.each(function(){a(this).removeData(),c(this,"parsedAttrs",!1)})},jump:function(a,b){var c,d=this.opts();if(!d.busy||d.manualTrump){var e=parseInt(a,10);if(isNaN(e)||0>e||e>=d.slides.length)return void d.API.log("goto: invalid slide index: "+e);if(e==d.currSlide)return void d.API.log("goto: skipping, already on slide",e);d.nextSlide=e,clearTimeout(d.timeoutId),d.timeoutId=0,d.API.log("goto: ",e," (zero-index)"),c=d.currSlide<d.nextSlide,d._tempFx=b,d.API.prepareTx(!0,c)}},stop:function(){var b=this.opts(),c=b.container;clearTimeout(b.timeoutId),b.timeoutId=0,b.API.stopTransition(),b.pauseOnHover&&(b.pauseOnHover!==!0&&(c=a(b.pauseOnHover)),c.off("mouseenter mouseleave")),b.API.trigger("cycle-stopped",[b]).log("cycle-stopped")},reinit:function(){var a=this.opts();a.API.destroy(),a.container.cycle()},remove:function(b){for(var c,d,e=this.opts(),f=[],g=1,h=0;h<e.slides.length;h++)c=e.slides[h],h==b?d=c:(f.push(c),a(c).data("cycle.opts").slideNum=g,g++);d&&(e.slides=a(f),e.slideCount--,a(d).remove(),b==e.currSlide?e.API.advanceSlide(1):b<e.currSlide?e.currSlide--:e.currSlide++,e.API.trigger("cycle-slide-removed",[e,b,d]).log("cycle-slide-removed"),e.API.updateView())}}),a(document).on("click.cycle","[data-cycle-cmd]",function(b){b.preventDefault();var c=a(this),d=c.data("cycle-cmd"),e=c.data("cycle-context")||".cycle-slideshow";a(e).cycle(d,c.data("cycle-arg"))})}(jQuery),/*! hash plugin for Cycle2;  version: 20130905 */
function(a){"use strict";function b(b,c){var d;return b._hashFence?void(b._hashFence=!1):(d=window.location.hash.substring(1),void b.slides.each(function(e){if(a(this).data("cycle-hash")==d){if(c===!0)b.startingSlide=e;else{var f=b.currSlide<e;b.nextSlide=e,b.API.prepareTx(!0,f)}return!1}}))}a(document).on("cycle-pre-initialize",function(c,d){b(d,!0),d._onHashChange=function(){b(d,!1)},a(window).on("hashchange",d._onHashChange)}),a(document).on("cycle-update-view",function(a,b,c){c.hash&&"#"+c.hash!=window.location.hash&&(b._hashFence=!0,window.location.hash=c.hash)}),a(document).on("cycle-destroyed",function(b,c){c._onHashChange&&a(window).off("hashchange",c._onHashChange)})}(jQuery),/*! loader plugin for Cycle2;  version: 20131121 */
function(a){"use strict";a.extend(a.fn.cycle.defaults,{loader:!1}),a(document).on("cycle-bootstrap",function(b,c){function d(b,d){function f(b){var f;"wait"==c.loader?(h.push(b),0===j&&(h.sort(g),e.apply(c.API,[h,d]),c.container.removeClass("cycle-loading"))):(f=a(c.slides[c.currSlide]),e.apply(c.API,[b,d]),f.show(),c.container.removeClass("cycle-loading"))}function g(a,b){return a.data("index")-b.data("index")}var h=[];if("string"==a.type(b))b=a.trim(b);else if("array"===a.type(b))for(var i=0;i<b.length;i++)b[i]=a(b[i])[0];b=a(b);var j=b.length;j&&(b.css("visibility","hidden").appendTo("body").each(function(b){function g(){0===--i&&(--j,f(k))}var i=0,k=a(this),l=k.is("img")?k:k.find("img");return k.data("index",b),l=l.filter(":not(.cycle-loader-ignore)").filter(':not([src=""])'),l.length?(i=l.length,void l.each(function(){this.complete?g():a(this).load(function(){g()}).on("error",function(){0===--i&&(c.API.log("slide skipped; img not loaded:",this.src),0===--j&&"wait"==c.loader&&e.apply(c.API,[h,d]))})})):(--j,void h.push(k))}),j&&c.container.addClass("cycle-loading"))}var e;c.loader&&(e=c.API.add,c.API.add=d)})}(jQuery),/*! pager plugin for Cycle2;  version: 20140415 */
function(a){"use strict";function b(b,c,d){var e,f=b.API.getComponent("pager");f.each(function(){var f=a(this);if(c.pagerTemplate){var g=b.API.tmpl(c.pagerTemplate,c,b,d[0]);e=a(g).appendTo(f)}else e=f.children().eq(b.slideCount-1);e.on(b.pagerEvent,function(a){b.pagerEventBubble||a.preventDefault(),b.API.page(f,a.currentTarget)})})}function c(a,b){var c=this.opts();if(!c.busy||c.manualTrump){var d=a.children().index(b),e=d,f=c.currSlide<e;c.currSlide!=e&&(c.nextSlide=e,c._tempFx=c.pagerFx,c.API.prepareTx(!0,f),c.API.trigger("cycle-pager-activated",[c,a,b]))}}a.extend(a.fn.cycle.defaults,{pager:"> .cycle-pager",pagerActiveClass:"cycle-pager-active",pagerEvent:"click.cycle",pagerEventBubble:void 0,pagerTemplate:"<span>&bull;</span>"}),a(document).on("cycle-bootstrap",function(a,c,d){d.buildPagerLink=b}),a(document).on("cycle-slide-added",function(a,b,d,e){b.pager&&(b.API.buildPagerLink(b,d,e),b.API.page=c)}),a(document).on("cycle-slide-removed",function(b,c,d){if(c.pager){var e=c.API.getComponent("pager");e.each(function(){var b=a(this);a(b.children()[d]).remove()})}}),a(document).on("cycle-update-view",function(b,c){var d;c.pager&&(d=c.API.getComponent("pager"),d.each(function(){a(this).children().removeClass(c.pagerActiveClass).eq(c.currSlide).addClass(c.pagerActiveClass)}))}),a(document).on("cycle-destroyed",function(a,b){var c=b.API.getComponent("pager");c&&(c.children().off(b.pagerEvent),b.pagerTemplate&&c.empty())})}(jQuery),/*! prevnext plugin for Cycle2;  version: 20140408 */
function(a){"use strict";a.extend(a.fn.cycle.defaults,{next:"> .cycle-next",nextEvent:"click.cycle",disabledClass:"disabled",prev:"> .cycle-prev",prevEvent:"click.cycle",swipe:!1}),a(document).on("cycle-initialized",function(a,b){if(b.API.getComponent("next").on(b.nextEvent,function(a){a.preventDefault(),b.API.next()}),b.API.getComponent("prev").on(b.prevEvent,function(a){a.preventDefault(),b.API.prev()}),b.swipe){var c=b.swipeVert?"swipeUp.cycle":"swipeLeft.cycle swipeleft.cycle",d=b.swipeVert?"swipeDown.cycle":"swipeRight.cycle swiperight.cycle";b.container.on(c,function(){b._tempFx=b.swipeFx,b.API.next()}),b.container.on(d,function(){b._tempFx=b.swipeFx,b.API.prev()})}}),a(document).on("cycle-update-view",function(a,b){if(!b.allowWrap){var c=b.disabledClass,d=b.API.getComponent("next"),e=b.API.getComponent("prev"),f=b._prevBoundry||0,g=void 0!==b._nextBoundry?b._nextBoundry:b.slideCount-1;b.currSlide==g?d.addClass(c).prop("disabled",!0):d.removeClass(c).prop("disabled",!1),b.currSlide===f?e.addClass(c).prop("disabled",!0):e.removeClass(c).prop("disabled",!1)}}),a(document).on("cycle-destroyed",function(a,b){b.API.getComponent("prev").off(b.nextEvent),b.API.getComponent("next").off(b.prevEvent),b.container.off("swipeleft.cycle swiperight.cycle swipeLeft.cycle swipeRight.cycle swipeUp.cycle swipeDown.cycle")})}(jQuery),/*! progressive loader plugin for Cycle2;  version: 20130315 */
function(a){"use strict";a.extend(a.fn.cycle.defaults,{progressive:!1}),a(document).on("cycle-pre-initialize",function(b,c){if(c.progressive){var d,e,f=c.API,g=f.next,h=f.prev,i=f.prepareTx,j=a.type(c.progressive);if("array"==j)d=c.progressive;else if(a.isFunction(c.progressive))d=c.progressive(c);else if("string"==j){if(e=a(c.progressive),d=a.trim(e.html()),!d)return;if(/^(\[)/.test(d))try{d=a.parseJSON(d)}catch(k){return void f.log("error parsing progressive slides",k)}else d=d.split(new RegExp(e.data("cycle-split")||"\n")),d[d.length-1]||d.pop()}i&&(f.prepareTx=function(a,b){var e,f;return a||0===d.length?void i.apply(c.API,[a,b]):void(b&&c.currSlide==c.slideCount-1?(f=d[0],d=d.slice(1),c.container.one("cycle-slide-added",function(a,b){setTimeout(function(){b.API.advanceSlide(1)},50)}),c.API.add(f)):b||0!==c.currSlide?i.apply(c.API,[a,b]):(e=d.length-1,f=d[e],d=d.slice(0,e),c.container.one("cycle-slide-added",function(a,b){setTimeout(function(){b.currSlide=1,b.API.advanceSlide(-1)},50)}),c.API.add(f,!0)))}),g&&(f.next=function(){var a=this.opts();if(d.length&&a.currSlide==a.slideCount-1){var b=d[0];d=d.slice(1),a.container.one("cycle-slide-added",function(a,b){g.apply(b.API),b.container.removeClass("cycle-loading")}),a.container.addClass("cycle-loading"),a.API.add(b)}else g.apply(a.API)}),h&&(f.prev=function(){var a=this.opts();if(d.length&&0===a.currSlide){var b=d.length-1,c=d[b];d=d.slice(0,b),a.container.one("cycle-slide-added",function(a,b){b.currSlide=1,b.API.advanceSlide(-1),b.container.removeClass("cycle-loading")}),a.container.addClass("cycle-loading"),a.API.add(c,!0)}else h.apply(a.API)})}})}(jQuery),/*! tmpl plugin for Cycle2;  version: 20121227 */
function(a){"use strict";a.extend(a.fn.cycle.defaults,{tmplRegex:"{{((.)?.*?)}}"}),a.extend(a.fn.cycle.API,{tmpl:function(b,c){var d=new RegExp(c.tmplRegex||a.fn.cycle.defaults.tmplRegex,"g"),e=a.makeArray(arguments);return e.shift(),b.replace(d,function(b,c){var d,f,g,h,i=c.split(".");for(d=0;d<e.length;d++)if(g=e[d]){if(i.length>1)for(h=g,f=0;f<i.length;f++)g=h,h=h[i[f]]||c;else h=g[c];if(a.isFunction(h))return h.apply(g,e);if(void 0!==h&&null!==h&&h!=c)return h}return c})}})}(jQuery);
//# sourceMappingURL=jquery.cycle2.js.map;
/* Plugin for Cycle2; Copyright (c) 2012 M. Alsup; v20140114 */
(function(e){"use strict";e(document).on("cycle-bootstrap",function(e,t,i){"carousel"===t.fx&&(i.getSlideIndex=function(e){var t=this.opts()._carouselWrap.children(),i=t.index(e);return i%t.length},i.next=function(){var e=t.reverse?-1:1;t.allowWrap===!1&&t.currSlide+e>t.slideCount-t.carouselVisible||(t.API.advanceSlide(e),t.API.trigger("cycle-next",[t]).log("cycle-next"))})}),e.fn.cycle.transitions.carousel={preInit:function(t){t.hideNonActive=!1,t.container.on("cycle-destroyed",e.proxy(this.onDestroy,t.API)),t.API.stopTransition=this.stopTransition;for(var i=0;t.startingSlide>i;i++)t.container.append(t.slides[0])},postInit:function(t){var i,n,s,o,r=t.carouselVertical;t.carouselVisible&&t.carouselVisible>t.slideCount&&(t.carouselVisible=t.slideCount-1);var l=t.carouselVisible||t.slides.length,c={display:r?"block":"inline-block",position:"static"};if(t.container.css({position:"relative",overflow:"hidden"}),t.slides.css(c),t._currSlide=t.currSlide,o=e('<div class="cycle-carousel-wrap"></div>').prependTo(t.container).css({margin:0,padding:0,top:0,left:0,position:"absolute"}).append(t.slides),t._carouselWrap=o,r||o.css("white-space","nowrap"),t.allowWrap!==!1){for(n=0;(void 0===t.carouselVisible?2:1)>n;n++){for(i=0;t.slideCount>i;i++)o.append(t.slides[i].cloneNode(!0));for(i=t.slideCount;i--;)o.prepend(t.slides[i].cloneNode(!0))}o.find(".cycle-slide-active").removeClass("cycle-slide-active"),t.slides.eq(t.startingSlide).addClass("cycle-slide-active")}t.pager&&t.allowWrap===!1&&(s=t.slideCount-l,e(t.pager).children().filter(":gt("+s+")").hide()),t._nextBoundry=t.slideCount-t.carouselVisible,this.prepareDimensions(t)},prepareDimensions:function(t){var i,n,s,o,r=t.carouselVertical,l=t.carouselVisible||t.slides.length;if(t.carouselFluid&&t.carouselVisible?t._carouselResizeThrottle||this.fluidSlides(t):t.carouselVisible&&t.carouselSlideDimension?(i=l*t.carouselSlideDimension,t.container[r?"height":"width"](i)):t.carouselVisible&&(i=l*e(t.slides[0])[r?"outerHeight":"outerWidth"](!0),t.container[r?"height":"width"](i)),n=t.carouselOffset||0,t.allowWrap!==!1)if(t.carouselSlideDimension)n-=(t.slideCount+t.currSlide)*t.carouselSlideDimension;else for(s=t._carouselWrap.children(),o=0;t.slideCount+t.currSlide>o;o++)n-=e(s[o])[r?"outerHeight":"outerWidth"](!0);t._carouselWrap.css(r?"top":"left",n)},fluidSlides:function(t){function i(){clearTimeout(s),s=setTimeout(n,20)}function n(){t._carouselWrap.stop(!1,!0);var e=t.container.width()/t.carouselVisible;e=Math.ceil(e-r),t._carouselWrap.children().width(e),t._sentinel&&t._sentinel.width(e),l(t)}var s,o=t.slides.eq(0),r=o.outerWidth()-o.width(),l=this.prepareDimensions;e(window).on("resize",i),t._carouselResizeThrottle=i,n()},transition:function(t,i,n,s,o){var r,l={},c=t.nextSlide-t.currSlide,a=t.carouselVertical,d=t.speed;if(t.allowWrap===!1){s=c>0;var u=t._currSlide,p=t.slideCount-t.carouselVisible;c>0&&t.nextSlide>p&&u==p?c=0:c>0&&t.nextSlide>p?c=t.nextSlide-u-(t.nextSlide-p):0>c&&t.currSlide>p&&t.nextSlide>p?c=0:0>c&&t.currSlide>p?c+=t.currSlide-p:u=t.currSlide,r=this.getScroll(t,a,u,c),t.API.opts()._currSlide=t.nextSlide>p?p:t.nextSlide}else s&&0===t.nextSlide?(r=this.getDim(t,t.currSlide,a),o=this.genCallback(t,s,a,o)):s||t.nextSlide!=t.slideCount-1?r=this.getScroll(t,a,t.currSlide,c):(r=this.getDim(t,t.currSlide,a),o=this.genCallback(t,s,a,o));l[a?"top":"left"]=s?"-="+r:"+="+r,t.throttleSpeed&&(d=r/e(t.slides[0])[a?"height":"width"]()*t.speed),t._carouselWrap.animate(l,d,t.easing,o)},getDim:function(t,i,n){var s=e(t.slides[i]);return s[n?"outerHeight":"outerWidth"](!0)},getScroll:function(e,t,i,n){var s,o=0;if(n>0)for(s=i;i+n>s;s++)o+=this.getDim(e,s,t);else for(s=i;s>i+n;s--)o+=this.getDim(e,s,t);return o},genCallback:function(t,i,n,s){return function(){var i=e(t.slides[t.nextSlide]).position(),o=0-i[n?"top":"left"]+(t.carouselOffset||0);t._carouselWrap.css(t.carouselVertical?"top":"left",o),s()}},stopTransition:function(){var e=this.opts();e.slides.stop(!1,!0),e._carouselWrap.stop(!1,!0)},onDestroy:function(){var t=this.opts();t._carouselResizeThrottle&&e(window).off("resize",t._carouselResizeThrottle),t.slides.prependTo(t.container),t._carouselWrap.remove()}}})(jQuery);;
/* Plugin for Cycle2; Copyright (c) 2012 M. Alsup; v20140128 */
(function(e){"use strict";e.event.special.swipe=e.event.special.swipe||{scrollSupressionThreshold:10,durationThreshold:1e3,horizontalDistanceThreshold:30,verticalDistanceThreshold:75,setup:function(){var i=e(this);i.bind("touchstart",function(t){function n(i){if(r){var t=i.originalEvent.touches?i.originalEvent.touches[0]:i;s={time:(new Date).getTime(),coords:[t.pageX,t.pageY]}}}var s,o=t.originalEvent.touches?t.originalEvent.touches[0]:t,r={time:(new Date).getTime(),coords:[o.pageX,o.pageY],origin:e(t.target)};i.bind("touchmove",n).one("touchend",function(){i.unbind("touchmove",n),r&&s&&s.time-r.time<e.event.special.swipe.durationThreshold&&Math.abs(r.coords[0]-s.coords[0])>e.event.special.swipe.horizontalDistanceThreshold&&Math.abs(r.coords[1]-s.coords[1])<e.event.special.swipe.verticalDistanceThreshold&&r.origin.trigger("swipe").trigger(r.coords[0]>s.coords[0]?"swipeleft":"swiperight"),r=s=void 0})})}},e.event.special.swipeleft=e.event.special.swipeleft||{setup:function(){e(this).bind("swipe",e.noop)}},e.event.special.swiperight=e.event.special.swiperight||e.event.special.swipeleft})(jQuery);;
(function () {
    var ccl_carousel;

    ccl_carousel = window.ccl_carousel ? window.ccl_carousel : {};

    ccl_carousel.Carousel = (function () {
        function Carousel(el, opts) {
            this.el = el;
            this.opts = opts;
            var _this = this;
            _this.$pager = this.el.find("ul.pager");

            if (this.el.length === 0) {
                return;
            }

            if ($(this.el.parent())[0].hasAttribute("data-pager")) {
                $(this.el.parent().attr("data-pager")).replaceWith(_this.$pager);
            }

            this.el.closest("#hero-section").addClass("content-loaded").removeClass("loading-content");
            this.el.closest(".carousel-widget").removeAttr("style");
            this.initResponsiveImages();
            if (this.el.length && !this.el.find(".slides").data("cycle.API")) {
                this.setSpecialClicks();
                this.setClicksPlayer();
                if (this.el.find(".slides > li").length >= 2
                    || (this.el.find(".slides > li").length == 0 && this.el.find(".slides > .slide").length > 0)) {
                    this.initCarousel();
                    if (this.el.find(".cycle-slide").not(".cycle-sentinel").length <= 1) {
                        this.el.find('.ccl-carousel-controls, .ccl-carousel-btn-pause').hide();
                        _this.$pager.hide();
                    }
                  this.SetFocusBehaviour();
                }
                else {
                    var $prev = $(this.el.parent())[0].hasAttribute("data-prev-button") ? $(this.el.parent().attr("data-prev-button")) : this.el.parent().find(".prev");
                    var $next = $(this.el.parent())[0].hasAttribute("data-next-button") ? $(this.el.parent().attr("data-next-button")) : this.el.parent().find(".next");
                    $prev.hide();
                    $next.hide();
                    this.el.find('.ccl-carousel-controls, .ccl-carousel-btn-pause').hide();
                    _this.$pager.hide();
                }
            } else {
                this.el.find('.slides').cycle('resume');
            }
            _this.$pager.attr('role', 'list');
            this.el.find('a.ccl-carousel-controls').unbind("click");
            this.el.find('a.ccl-carousel-controls').on("click", function (e) {
                if ($(this).hasClass("ccl-carousel-btn-play")) {
                    $(this).removeClass('ccl-carousel-btn-play').addClass('ccl-carousel-btn-pause').find('span').text('Pause animation');
                    _this.el.find(".slides").cycle('resume');
                }
                else if ($(this).hasClass("ccl-carousel-btn-pause")) {
                    $(this).removeClass('ccl-carousel-btn-pause').addClass('ccl-carousel-btn-play').find('span').text('Start animation');
                    _this.el.find(".slides").cycle('pause');
                }
            });

            //Initialization a11y
            var array = this.el.find('.slides').find('img').map(function (index, item) {
                return $(item).attr('alt');
            }).get();

            var items = _this.$pager.find("li>a");
            items.each(function (i) {
                $(this).data("alt-bullet", array[i]);
                var context = "";
                if (i == 0) {
                    context = array[i] + " - Current Slide Number " + (i + 1) + " of " + items.length;
                }
                else {
                    context = array[i] + " - Slide Number " + (i + 1) + " of " + items.length;
                }
                $(this).attr("title", context);
                $(this).attr("aria-label", context);
            });
            this.setADALinksAriaLabel();
            this.SetNextPrevAda(0);
            $(document).trigger("CCL-ccl_carousel-initialized");
        }

        Carousel.prototype.setADALinksAriaLabel = function () {
            var $itemsList = $("#HeroSlidesContainer li");
            $itemsList.each(function () {
                if ($itemsList.find('a').length) {
                    if ($itemsList.find('.overlay').length) {
                        if ($itemsList.find(".overlay").children().length > 0) {
                            var onlyP = $itemsList.find('.overlay').find('p:only-child');
                            if (onlyP.length) { if ($.trim(onlyP.text()).length == 0) { return; } }
                        }
                    }
                }
            });

        };

        Carousel.prototype.setSpecialClicks = function () {
            var $videoLB;
            var _this = this;
            this.el.on("click", "a.video", function (e) {
                $videoLB = _this.GetVideoLightbox();
                var url;
                url = $(e.currentTarget).attr("href");
                $.colorbox({
                    inline: true,
                    transition: "none",
                    opacity: 1,
                    href: $videoLB,
                    reposition: false,
                    onOpen: function () {
                        $('#cboxClose').show();
                        $videoLB.find("iframe").attr("src", url);
                        return _this.el.find(".slides").cycle("pause");
                    },
                    onClosed: function () {
                        return $('#cboxClose').hide();
                    },
                    onCleanup: function () {
                        $videoLB.find("iframe").attr("src", "");
                        return window.setTimeout((function () {
                            return _this.el.find(".slides").cycle("resume").cycle("next");
                        }), 1000);
                    }
                });
                return e.preventDefault();
            });
            if (window.navigator.userAgent.match(/iPad/i)) { //Pause Carousel
                this.el.on("click", "a.panorama-overlay, div.slide #panorama, div.slide #panorama div, div.slide #panorama canvas, div.slide.qtvr", function (e) {
                    _this.el.find(".slides").cycle("pause");
                    _this.el.find("a.call-to-action").one("click", function (e, opt, outgoing, incoming, fwd) {
                        _this.el.find(".slides").cycle("resume");

                    });
                });
            }
            return this.el.on("click", "a.panorama-overlay", function (e) {
                var $overlay, panHtml;
                $overlay = $(e.currentTarget);
                if (!$overlay.hasClass('html5')) {
                    panHtml = $overlay.next(".panorama").html().replace(/transparent/g, "opaque");
                    $overlay.parent().html(panHtml);
                } else {
                    $overlay.remove();
                }
                return e.preventDefault();
            });
        };

        Carousel.prototype.setClicksPlayer = function () {
            var _this = this;
            var $videoLb = _this.GetVideoLightbox();
            this.el.on("click", "a.ccl-video-player", function (e) {
                var $anchor = $(this);
                if ($anchor.parents().is(".ccl-mobile")) {
                    _this.openMobileVideoModal(e, _this);
                    return e.preventDefault();
                }
                _this.initVideoPlayer($anchor);
                _this.openCclVideoPlayer($videoLb, $anchor);
                return e.preventDefault();
            });
        };

        Carousel.prototype.openModal = function (self, $lastFocus) {
            var $modal = this.GetVideoLightbox();
            if ($modal.length === 1) {
                var classList = $modal.attr('class').split(/\s+/);
                $.each(classList,
                    function (index, item) {
                        $modal.addClass(item + "--open");
                        var html = "<div id='" + item + "-video' class='" + item + "__wrapper'><header class='" +
                            item +
                            "__header'><button class='" +
                            item +
                            "__close' aria- label='close modal' role='button'></button></header>" +
                            "<div class='video-container'><div class='pane mobile'><div id='media'></div></div></div></div>";
                        $modal.html(html);
                        self.initCloseModal(item, $lastFocus);
                    });   
            }
            //this.setModalExclusiveTabbing();
        };
        Carousel.prototype.closeModal = function () {
            var $modal = this.GetVideoLightbox();
            var classList = $modal.attr('class').split(/\s+/);
            $.each(classList,
                function (index, item) {
                    $modal.removeClass(item + "--open");
                });
            var videoContainer = $(".video-container #media");
            videoContainer.empty();
        };
        Carousel.prototype.initCloseModal = function (modalClassName, lastFocus) {
            var $modal = $("." + modalClassName);
            var $close = $modal.find('.' + modalClassName + '__close');
            var $overlay = $modal.siblings('.' + modalClassName + '__overlay');
            var self = this;
            $close.add($overlay).on('click',
                function (e) {
                    e.preventDefault();
                    self.closeModal();
                    $(lastFocus).focus();
                });
        };

        Carousel.prototype.openMobileVideoModal = function (e, self) {
            var $this = $(e.currentTarget);
            var videoId = $this.attr("data-video-id");
            var videoDescription = $this.attr("data-video-description-id");
            var idYoutube = videoId ? this.getVideoId(videoId) : '';
            var videoDescId = videoDescription ? this.getVideoId(videoDescription) : ''; 
            var title = $this.attr("data-title");
            var multiplier = $this.attr("data-size-multiplier") ? $(this).attr("data-size-multiplier") : 19;
            e.preventDefault();
            self.openModal(self, $this);
            self.createVideo(idYoutube, videoDescId, title, multiplier);
        };

        Carousel.prototype.createVideo = function (videoId, videoDescId, title, multiplier) {
            var videoContainer = $(".video-container #media");
            var videoHtml = '<div class="ccl-yt-video" data-video-id="' +
                videoId +
                '" data-video-description-id="' +
                videoDescId +
                '" data-size-multiplier="' +
                multiplier +
                '" data-title="' +
                title +
                '"></div>';
            videoContainer.html(videoHtml);
            $(".ccl-yt-video").cclVideo(true);
        };

        Carousel.prototype.openCclVideoPlayer = function ($videoLb, $anchor) {
            var _this = this;
            $.colorbox({
                inline: true,
                transition: "none",
                opacity: 1,
                reposition: true,
                scrolling: false,
                href: $videoLb,
                trapFocus: false,
                height: "720px",
                width: "660px",
                onOpen: function () {
                    //Trap focus
                    $("body").on("keydown.colorboxTab", '.ccl-video .radio-toggle input:radio', function (e) {
                        var pressedKey = (e.keyCode ? e.keyCode : e.which);
                        // Check for TAB key press
                        if (pressedKey === 9) {
                            if (!e.shiftKey) {
                                $("body").find("#cboxClose").focus();
                                e.preventDefault();
                            }
                        }
                    });
                    $("body").on("keydown.colorboxTab", "#cboxClose", function (e) {
                        var pressedKey = (e.keyCode ? e.keyCode : e.which);
                        // Check for TAB key press
                        if (pressedKey === 9) {
                            // SHIFT + TAB key
                            if (e.shiftKey) {
                                $('.video-lightbox input[name="ad-toggle0"]').first().focus();
                                e.preventDefault();
                            }
                        }
                        else {
                            if (pressedKey === 13) {
                                $('#cboxClose').click();
                                e.preventDefault();
                            }
                        }
                    });
                    $("body").on("focus.colorboxTab", "#cboxClose", function () {
                        $('#cboxClose').addClass("ccl-explicithighlights");

                    });
                    $("body").on("focusout.colorboxTab", "#cboxClose", function () {
                        $('#cboxClose').removeClass("ccl-explicithighlights");
                    });

                    
                    fixCloseButtonTabOrderAndFocus();

                    function fixCloseButtonTabOrderAndFocus() {
                        $("#cboxClose").show();
                        $("#cboxClose").attr("tabindex", "0").attr("role", "button").attr("aria-label", "Close Video Dialog");
                        setTimeout(function() {
                            $("#cboxClose").detach().prependTo("#cboxContent");
                            setTimeout(function() {
                                $("#cboxClose").focus();
                            }, 500);
                        }, 50);
                    }

                    setTimeout(function () {
                        $("#cboxClose").focus();
                    }, 50);

                    return _this.el.find(".slides").cycle("pause");
                },
                onClosed: function () {
                    $videoLb.html("");
                    $("body").off(".colorboxTab");
                    return $('#cboxClose').hide();
                },
                onCleanup: function () {
                    $anchor.focus();
                    return window.setTimeout((function () {
                        return _this.el.find(".slides").cycle("resume").cycle("next");
                    }), 1000);
                }
            });
        };

        Carousel.prototype.initVideoPlayer = function (el) {
            var _this = this;
            _this.initCclVideoPlayer(el);
        };

        Carousel.prototype.initCclVideoPlayer = function (el) {
            var $videoLb = this.GetVideoLightbox();
            var videoId = el.attr("data-video-id");
            var idYoutube = videoId ? this.getVideoId(videoId) : '';
            var title = el.attr("data-title");
            var videoDescription = el.attr("data-video-description-id");

            if (idYoutube !== "") {
                var youtubeDescId = videoDescription ? this.getVideoId(videoDescription) : '';
                var multiplier = 32;
                var $videoTag = $('<div class="ccl-yt-video ccl-video-spaceless" data-video-id="' +
                    idYoutube +
                    '" data-video-description-id="' +
                    youtubeDescId +
                    '" data-size-multiplier="' +
                    multiplier +
                    '" data-title="' +
                    title +
                    '" data-width="100%" data-height="300px"></div>');
                $videoLb.html("");
                //$videoLb.append("<a tabindex='0' id='HelperPlayer' aria-label='Close Video Dialog' role='button' style='outline: 0 !important;height: 0;width: 0;'>&nbsp</a>");
                $videoLb.append($videoTag);
                $videoTag.cclVideo();
            }
        };

        Carousel.prototype.getVideoId = function (description) {
            if (description && description.indexOf("youtu.be") === -1 && description.indexOf("youtube.com") === -1) {
                return description;
            } else {
                var regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=|\?v=)([^#\&\?]*).*/;
                var match = description.match(regExp);
                if (match && match[2].length === 11) {
                    return match[2];
                }
            }
            return null;
        };

        Carousel.prototype.initResponsiveImages = function () {
            var _this = this;
            var bgItems = this.el.find("li[data-desktop-src]");

            bgItems.each(function (index, value) {
                var mobileImg = $(this).attr('data-mobile-src');
                var desktopImg = $(this).attr('data-desktop-src');
                _this.loadImage(mobileImg);
                _this.loadImage(desktopImg);
            });

            _this.handle_resize();
        };

        Carousel.prototype.loadImage = function(imgUrl, callbackFn) {
            var image = new Image();
            image.src = imgUrl;
            if (callbackFn) {
                image.onload = function() {
                    callbackFn();
                };
            }
        };

        Carousel.prototype.handle_resize = function () {
            var _this = this;
            var lastWindowWidth;

            function setImage() {
                var w = $(window).width();
                if ((w >= 1024 && !lastWindowWidth) || (w >= 1024 && lastWindowWidth < 1024)) {
                    _this.setDesktopImages();
                } else if ((w < 1024 && !lastWindowWidth) || (w < 1024 && lastWindowWidth <= 1024)) {
                    _this.setMobileImages();
                }
                lastWindowWidth = w;
            }

            setImage();
            $(window).resize(setImage);
        };

        Carousel.prototype.setDesktopImages = function () {
            var bgItems = this.el.find("li[data-desktop-src]");

            bgItems.each(function (index, value) {
                var img = $(this).attr('data-desktop-src');
                $(this).css('background-image', 'url("' + img + '")');
            });
        };

        Carousel.prototype.setMobileImages = function () {
            var bgItems = this.el.find("li[data-mobile-src]");

            bgItems.each(function (index, value) {
                var img = $(this).attr('data-mobile-src');
                $(this).css('background-image', 'url("' + img + '")');
            });
        };

        Carousel.prototype.initCarousel = function () {
            var defaultOpts, hasSwipe, opts, transitionFx, rotateSeconds, $prev, $next, _this = this;
            opts = $.isEmptyObject(this.el.data()) ? this.opts : this.el.data();
            hasSwipe = this.el.find('.slides').hasClass('has-pan') ? false : true;
            transitionFx = $(this.el.parent())[0].hasAttribute("data-transition") ? this.el.parent().attr("data-transition") : (this.el.find('.slides').hasClass('hero') ? 'fade' : 'scrollHorz');
            $prev = $(this.el.parent())[0].hasAttribute("data-prev-button") ? $(this.el.parent().attr("data-prev-button")) : this.el.parent().find(".prev");
            $next = $(this.el.parent())[0].hasAttribute("data-next-button") ? $(this.el.parent().attr("data-next-button")) : this.el.parent().find(".next");
            this.SetClickOnEnterKeyPress($prev);
            this.SetClickOnEnterKeyPress($next);
            rotateSeconds = parseInt(this.el.parent().attr("data-timeout") || $("#HeroBannerRotationTimeinSeconds").val() || "6");
            defaultOpts = {
                log: false,
                pager: _this.$pager,
                pagerTemplate: "<li><a href='javascript:;'><span class='bullet'></span></a></li>",
                slides: this.el.find(".slides").children(),
                prev: $prev,
                next: $next,
                speed: 1000,
                timeout: rotateSeconds * 1000,
                swipe: hasSwipe,
                fx: transitionFx,
                width: 860,
                pauseOnHover: true
            };
            this.options = opts ? $.extend(defaultOpts, opts) : defaultOpts;
            if (this.el.find(".slides").children().length > 1 || (this.el.find(".slides > li").length == 0 && this.el.find(".slides > .slide").length > 0)) {
                return this.el.css("height", "100%").find(".slides").on("cycle-before", function (e, opt, outgoing, incoming, fwd) {
                    var $ob, code, par;
                    $ob = $(incoming).find("object, embed, #panorama");
                    if ($ob.length) {
                        $ob.show();
                    }
                    $ob = $(incoming).find("object,embed");
                    if ((window.navigator.userAgent.match(/MSIE/i) || window.navigator.userAgent.match(/Trident/i)) && $ob.length) {
                        if ($ob.length) {
                            code = $ob.parent().html();
                            par = $ob.parent().empty();
                            return window.setTimeout(function () {
                                return par.html(code);
                            }, 10);
                        }
                    }
                    var fixedHiddenBanner = $('#hero-section div.carousel-widget.typehero li.cycle-slide')
                        .filter(function () {
                            return $(this).css('visibility') == 'hidden';
                        })[0];
                    if (fixedHiddenBanner) {
                        if (!$(fixedHiddenBanner).attr("aria-hidden")) {
                            $(fixedHiddenBanner).attr("aria-hidden", true);
                        }
                    }
                }).on("cycle-resumed", function () {
                    if (_this.el.find('a.ccl-carousel-controls').hasClass("ccl-carousel-btn-play")) {
                        $(this).closest(".slides").cycle('pause');
                    }
                }).on("cycle-after", function (e, opt, outgoing, incoming, fwd) {
                    var $ob, $pan, attributes, flashvars, gyro, pano, params, xml;

                    if (!_this.el.parent().hasClass("full-cover")) {
                        _this.el.find(".slides").cycle("resume");
                    }
                    
                    //a11y behavior
                    var items = _this.$pager.find("li>a");
                    items.each(function (i) {
                        var alt = $(this).data("alt-bullet");
                        var context = "";
                        if ($(this).closest(".cycle-pager-active").length == 1) {
                            context = alt + " - Current Slide Number " + (i + 1) + " of " + items.length;

                            if (rotateSeconds <= 0) {
                                _this.el.find(".carousel-context").text(context);
                            }

                            _this.SetNextPrevAda(i);
                        }
                        else {
                            context = alt + " - Slide Number " + (i + 1) + " of " + items.length;
                        }
                        $(this).attr("title", context);
                        $(this).attr("aria-label", context);
                    });

                    $ob = $(outgoing).find("object, embed, #panorama");
                    if ($ob.length) {
                        $ob.hide();
                    }
                    $pan = $(incoming).find('#panorama');
                    if ($pan.length && !$(incoming).hasClass('added')) {
                        console.log('Add panorama');
                        $(incoming).addClass('added');
                        if (ggHasHtml5Css3D() || ggHasWebGL()) {
                            pano = new pano2vrPlayer('panorama');
                            pano.readConfigUrl($pan.attr('data-pano'));
                            return gyro = new pano2vrGyro(pano, 'panorama');
                        } else {
                            flashvars = {
                                externalinterface: '1'
                            };
                            params = {
                                quality: 'high',
                                bgcolor: '#ffffff',
                                allowscriptaccess: 'sameDomain',
                                allowfullscreen: 'true',
                                wmode: 'transparent'
                            };
                            attributes = {
                                id: 'pano',
                                name: 'pano',
                                align: 'middle'
                            };
                            return swfobject.embedSWF($pan.attr('data-panoswf'), "panorama", "100%", "275", "9.0.0", "", flashvars, params, attributes);
                        }
                    }
                    else if ($pan.length
                        && $(incoming).hasClass('added')
                        && !$(incoming).find('.panorama-overlay').length
                        && window.navigator.userAgent.match(/iPad/i)) {
                        _this.el.find(".slides").cycle("pause");
                    }

                    $(document).trigger("ccl-carousel-cycled",
                        {
                            $el: _this.el
                        });
                }).on("cycle-initialized", function (e, opt) {
                    var $ob;
                    $ob = $(e.currentTarget).find("object, embed");
                    if ($ob.length) {
                        $ob.hide();
                        return window.setTimeout(function () {
                            return $ob.show();
                        }, 10);
                    }
                    if (_this.el.parent().hasClass("full-cover")) {
                        _this.el.find(".slides").cycle("pause");
                    }
                    console.log("Carousel initialized.");
                }).cycle(this.options);
            } else {
                return this.el.find('.step-nav').hide();
            }
        };

        Carousel.prototype.SetFocusBehaviour = function () {
            var anchors = this.el.find(".slides > li > a");
            var slideItemsWithoutLink = this.el.find(".slides > li").not(":has(a)");
            var slides = this.el.find(".slides");
            var pager = this.$pager.find("li>a");

            anchors.each(function () {
              $(this).on("focus",
                function() {
                  slides.cycle('pause');
                  $(this).parent().closest('div').addClass("carousel-reference-focused");
                });
            });

            anchors.each(function () {
                $(this).on("blur",
                    function () {
                        if ($(this).parent().find("a:focus-within").length === 0) {
                            slides.cycle('resume');
                        }
                        anchors.parent().closest('div').removeClass("carousel-reference-focused");
                    });
            });

            pager.each(function () {
                $(this).on("focus",
                    function () {
                        slides.cycle('resume');
                    });
            });

            pager.each(function () {
                $(this).on("blur",
                    function () {
                        if ($(this).parent().find("a:focus-within").length === 0) {
                            slides.cycle('pause');
                        }
                    });
            });

            slideItemsWithoutLink.focus(
                function () {
                    slides.cycle('pause');
                    $(this).parent().closest('div').addClass("carousel-reference-focused");
                }).blur(
                function () {
                    slides.cycle('resume');
                    $(this).parent().closest('div').removeClass("carousel-reference-focused");
                });
        }

        Carousel.prototype.SetClickOnEnterKeyPress = function($ele, $focusEl) {
          $ele.keyup(function (e) {
              var pressedKey = (e.keyCode ? e.keyCode : e.which);
              if (pressedKey === 13) {
                  $(this).click();
              }
          });
        }
        
        Carousel.prototype.destroy = function () {
            return this.el.find(".slides").cycle("destroy");
        };

        Carousel.prototype.SetNextPrevAda = function(i) {
            var items = this.$pager.find("li>a");

            if (!items || items.length <= 1) {
            return;
            }

            var prevIndex, nextIndex;

            if (i === 0) {
                prevIndex = items.length - 1;
                nextIndex = i + 1;
            } else if (i === (items.length - 1)) {
                prevIndex = i - 1;
                nextIndex = 0;
            } else {
                prevIndex = i - 1;
                nextIndex = i + 1;
            }

            var prevText = items.eq(prevIndex).find("span").text();
            var nextText = items.eq(nextIndex).find("span").text();
            var $prev = $(this.el.parent())[0].hasAttribute("data-prev-button") ? $(this.el.parent().attr("data-prev-button")) : this.el.parent().find(".prev");
            var $next = $(this.el.parent())[0].hasAttribute("data-next-button") ? $(this.el.parent().attr("data-next-button")) : this.el.parent().find(".next");

            $prev.html("<span class='ccl-srOnly'>Go to previous slide - " + prevText + "</span>");
            $next.html("<span class='ccl-srOnly'>Go to next slide - " + nextText + "</span>");
        }

        Carousel.prototype.GetVideoLightbox = function () {
            var modalSelector = "#hero-lightbox.video-lightbox";
            var $modal = $(modalSelector);
            if ($modal.length === 0) {
                $("body").append('<div id="hero-lightbox" class="video-lightbox" role="dialog" aria-modal="true"></div>');
                $modal = $(modalSelector);
            }

            return $modal;
        };

        return Carousel;

    })();

    window.ccl_carousel = ccl_carousel;

    //(function ($) {
    //    return $('.carousel-widget').each(function (i, el) {
    //        return new ccl_carousel.Carousel($(el));
    //    });
    //})(jQuery);


}).call(this);
console.log("Carousel loaded.");
$(document).trigger("CCL-ccl_carousel-loaded");
;
var ccl_homepage = {
    setCtaWidths: function() {
        setTimeout(function() {
            $("#ccl_homepage .homepage-content .touts .link").each(function() {
                var o = $(this),
                    w = o.width() + 1,
                    left = 73 + Math.ceil((78 - (w + 20)) / 2);

                o.css({ "width": w + "px", "left": left + "px" });
            });
        }, 300);


    },

    initBannerRotator: function(selector) {

        var rotator = $(selector),
            prev = rotator.find(".prev-btn"),
            next = rotator.find(".next-btn"),
            arrows = prev.add(next);

        rotator.hover(function() {
            if ($(window).width() >= 1200) {
                if ($.browser && $.browser.msie && parseInt($.browser.version, 10) < 9) {
                    arrows.show();
                } else {
                    arrows.stop(false, true).fadeIn();
                }
            }
        }, function() {
            if ($.browser && $.browser.msie && parseInt($.browser.version, 10) < 9) {
                arrows.hide();
            } else {
                arrows.stop(false, true).fadeOut();
            }
        });

        rotator.find(".slideshow a").each(function() {
            var a = $(this),
                img = a.find("img").attr("src");

            a.css("background", "url(" + img + ") no-repeat center 0");
        });

        rotator.find(".slideshow").cycle({
            next: next,
            prev: prev,
            pause: true,
            pager: $("#banner-rotator-pager"),
            pagerAnchorBuilder: function(idx, slide) {
                if (idx != 2) {
                    return '<li><a href="#">' + (idx + 1) + '</a></li>';
                } else {
                    return '<li class="last-child"><a href="#">' + (idx + 1) + '</a></li>';
                }
            },
            timeout: 10000,
            fit: true,
            width: "100%",
            height: "475px"
        });

        rotator.addSwipeEvents().bind("swipeleft", function(evt, touch) {
            rotator.find(".slideshow").cycle("next");
        }).bind("swiperight", function(evt, touch) {
            rotator.find(".slideshow").cycle("prev");
        });
    },

    initPIE: function() {
        if (window.PIE) {
            $(".help-module, #homepage_email_signup, #cruise-search-widget .wrapper, #cruise-search-widget .inner, .touts .flag, .tout .cta, .banners .hero-cta", "#ccl_homepage").each(function() {
                PIE.attach(this);
            });
        }
    },

    supportPH: function() {
        var phSupport = ("placeholder" in document.createElement("input"));
        if (!phSupport) {
            var $inputs = $("#ccl_homepage .homepage-content *[placeholder][type!=password]");
            if ($inputs) {
                $inputs.each(function() {
                    var o = $(this),
                        ph = o.attr("placeholder");

                    o.val(ph).focus(function() {
                        if (o.val() == ph) {
                            o.val("");
                        }
                    }).blur(function() {
                        if (o.val() == "") {
                            o.val(ph);
                        }
                    });
                });
            }
        }
    },

    initHeroCta: function() {
        var currentColor,
            darkerColor;

        $(document).on('mouseenter', '.hero-cta2', function () {
            currentColor = ccl_homepage.rgb2hex($(this).css('backgroundColor'));
            darkerColor = ccl_homepage.decreaseHexBrightness(currentColor, 40);
            $(this).css('backgroundColor', darkerColor);
        }).on('mouseleave', '.hero-cta2', function () {
            $(this).css('backgroundColor', currentColor);
        });
    },

    rgb2hex: function(rgb) {
        rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);

        function hex(x) {
            return ("0" + parseInt(x).toString(16)).slice(-2);
        }

        return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
    },

    increaseRgbBrightness: function(r, g, b, percent) {
        return '#' + ((0 | (1 << 8) + r + (256 - r) * percent / 100).toString(16)).substr(1) + ((0 | (1 << 8) + g + (256 - g) * percent / 100).toString(16)).substr(1) + ((0 | (1 << 8) + b + (256 - b) * percent / 100).toString(16)).substr(1);
    },

    increaseHexBrightness: function(hex, percent) {
        // strip the leading # if it's there
        hex = hex.replace(/^\s*#|\s*$/g, '');

        // convert 3 char codes --> 6, e.g. `E0F` --> `EE00FF`
        if (hex.length == 3) {
            hex = hex.replace(/(.)/g, '$1$1');
        }

        var r = parseInt(hex.substr(0, 2), 16),
            g = parseInt(hex.substr(2, 2), 16),
            b = parseInt(hex.substr(4, 2), 16);

        return ccl_homepage.increaseRgbBrightness(r, g, b, percent);
    },

    decreaseRgbBrightness: function(r, g, b, percent) {
        return '#' + ((0 | (1 << 8) + r * (1 - percent / 100)).toString(16)).substr(1) + ((0 | (1 << 8) + g * (1 - percent / 100)).toString(16)).substr(1) + ((0 | (1 << 8) + b * (1 - percent / 100)).toString(16)).substr(1);
    },

    decreaseHexBrightness: function(hex, percent) {
        // strip the leading # if it's there
        hex = hex.replace(/^\s*#|\s*$/g, '');

        // convert 3 char codes --> 6, e.g. `E0F` --> `EE00FF`
        if (hex.length == 3) {
            hex = hex.replace(/(.)/g, '$1$1');
        }

        var r = parseInt(hex.substr(0, 2), 16),
            g = parseInt(hex.substr(2, 2), 16),
            b = parseInt(hex.substr(4, 2), 16);

        return ccl_homepage.decreaseRgbBrightness(r, g, b, percent);
    }


};
$(document).trigger("CCL-ccl_homepage-loaded");;
(function ($, Carnival) {

    if (!Carnival) Carnival = {};

    if (!Carnival.Homepage) Carnival.Homepage = {};

    var home = {};

    home.$el = $("#ccl-refresh-homepage");

    home.touch = Modernizr.touch;

    home.init = function () {

        if (!Carnival.Homepage.$el.length) {
            return;
        }

        var isUseAusFac = Carnival.Homepage.$el.find(".cruise-search-widget").hasClass('useAusFac');
        home.isUseAusFac = isUseAusFac || false;

        home.initCarousel();
        
        home.initCourtesyHold(); // unix timestamp 10/5/2013 (http://www.unixtimestamp.com/)
    };

    function carouselInit() {
        if (window.ccl_carousel && window.ccl_carousel.Carousel) {
            var $car = new window.ccl_carousel.Carousel($('#hero-section .carousel-widget'));
        } else {
            console.log("ccl_carousel not ready");
            setTimeout(function () { carouselInit(); }, 100);
        }
    };

    home.initCarousel = function () {
        if (!Carnival.Personalizer) {
            carouselInit();
        }
    };

    home.getCurrentTimezoneOffset = function () {
        var currDate = new Date();
        var dstStartDateInUTC = Carnival.AppResources.Core.GetResourceString("ccl-homepage-init.js", 'DSTStartDateInUTC'),
            dstEndDateInUTC = Carnival.AppResources.Core.GetResourceString("ccl-homepage-init.js", 'DSTEndDateInUTC'),
            startDateSplit = dstStartDateInUTC.split('.'),
            endDateSplit = dstEndDateInUTC.split('.'),
            startDateInUTC = Date.UTC(parseInt(startDateSplit[0]), parseInt(startDateSplit[1]) - 1, parseInt(startDateSplit[2]), parseInt(startDateSplit[3]), parseInt(startDateSplit[4]), parseInt(startDateSplit[5])),
            endDateInUTC = Date.UTC(parseInt(endDateSplit[0]), parseInt(endDateSplit[1]) - 1, parseInt(endDateSplit[2]), parseInt(endDateSplit[3]), parseInt(endDateSplit[4]), parseInt(endDateSplit[5])),
            now = currDate.getTime(),
            currentTimezoneOffset = 240;

        if (!isNaN(startDateInUTC) && !isNaN(endDateInUTC)) {
            var isDaylightSavingsTime = now >= startDateInUTC && now < endDateInUTC;
            if (isDaylightSavingsTime) {
                currentTimezoneOffset = parseInt(Carnival.AppResources.Core.GetResourceString("ccl-homepage-init.js", 'DSTTimezoneOffset'));
            }
            else {
                currentTimezoneOffset = parseInt(Carnival.AppResources.Core.GetResourceString("ccl-homepage-init.js", 'StdTimezoneOffset'));
            }
        }
        return currentTimezoneOffset;
    };

    home.initCourtesyHold = function () {
        //if courtesy hold expiration exist from cookie start the countdown
        if (typeof window.chExpiration != 'undefined'
            && window.chExpiration != ''
            && window.chExpiration != null
            && ($('.courtesy-hold-2016').length < 1 || $.cookie('CHPersist'))) {

            /*Courtesy hold expiration date and time is always in EST time. 
            Here we are converting both EST and local time to UTC in order to calculate accurate remaing time.*/
            var split = window.chExpiration.split(',');
            var expires = Date.UTC(parseInt(split[0]), parseInt(split[1]), parseInt(split[2]), parseInt(split[3]), parseInt(split[4]), parseInt(split[5]));
            var timespaninseconds = home.getUTCTimeUntilExpiration(expires); //Remaining time span in seconds  

            home.$el.find(".slides>li>a.courtesy-hold").each(function () {
                var o = $(this),
                    time = timespaninseconds,
                    layout = getCountdownLayout();

                o.find(".countdown-clock").countdown({
                    until: time,
                    layout: layout,
                    format: "DHMS",
                    onExpiry: function () {
                        var $cta = o.find('.cta');
                        var text = $cta.data('alternate-text');
                        if (text) {
                            $cta.find('span').html(text);
                        } else {
                            $cta.hide();
                        }


                        if ($.cookie('cclCH')) {
                            var cclCh = JSON.parse($.cookie('cclCH'));
                            o.attr('href', cclCh.FindSimilarCruisesUrl ? cclCh.FindSimilarCruisesUrl : '/cruise-search');
                        }
                    }
                });

                // second spot is placed inside a 'pull-left' class span
                o.find('.pull-left').removeClass();
            });
        }
    };

    home.getUTCTimeUntilExpiration = function (expires) {
        var now = new Date(); //Local time
        var nowutcinms = now.valueOf() - (now.getTimezoneOffset() * 60000); //Number of ms since 1970 Utc

        ////////////////////////////////////////////////////////////////////////
        // Correct offset difference between timezones            
        var currentTimezoneOffset = home.getCurrentTimezoneOffset();
        var diff = (currentTimezoneOffset - now.getTimezoneOffset()) * 60000;
        expires += diff;
        ////////////////////////////////////////////////////////////////////////

        var timespaninseconds = ((expires - nowutcinms) / 1000) | 0; //Remaining time span in seconds   

        return timespaninseconds;
    };
    
    home.setSpecialClicks = function () {
        var $videoLB;
        var _this = this;
        $('.banners').on("click", "a.video", function (e) {
            $videoLB = _this.GetVideoLightbox();
            var url;
            url = $(e.currentTarget).attr("href");
            $.colorbox({
                inline: true,
                transition: "none",
                opacity: 1,
                href: $videoLB,
                reposition: false,
                onOpen: function () {
                    $('#cboxClose').show();
                    $videoLB.find("iframe").attr("src", url);
                    return $('.banners').find(".slides").cycle("pause");
                },
                onClosed: function () {
                    return $('#cboxClose').hide();
                },
                onCleanup: function () {
                    $videoLB.find("iframe").attr("src", "");
                    return window.setTimeout((function () {
                        return $('.banners').find(".slides").cycle("resume").cycle("next");
                    }), 1000);
                }
            });
            return e.preventDefault();
        });
        if (window.navigator.userAgent.match(/iPad/i)) { //Pause Carousel
            $('.banners').on("click", "a.panorama-overlay, div.slide #panorama, div.slide #panorama div, div.slide #panorama canvas, div.slide.qtvr", function (e) {
                $('.banners').find(".slides").cycle("pause");
                $('.banners').find("a.call-to-action").one("click", function (e, opt, outgoing, incoming, fwd) {
                    $('.banners').find(".slides").cycle("resume");

                });
            });
        }
        return $('.banners').on("click", "a.panorama-overlay", function (e) {
            var $overlay, panHtml;
            $overlay = $(e.currentTarget);
            if (!$overlay.hasClass('html5')) {
                panHtml = $overlay.next(".panorama").html().replace(/transparent/g, "opaque");
                $overlay.parent().html(panHtml);
            } else {
                $overlay.remove();
            }
            return e.preventDefault();
        });
    };

    home.setClicksAblePlayer = function () {
        var _this = this;
        var $videoLB = _this.GetVideoLightbox();
        $('.banners').on("click", "a.videoable", function (e) {
            var $anchor = $(this);
            var datayoutubespecific = $anchor.attr("data-youtube-able");
            _this.initVideoPlayer($anchor);
            $.colorbox({
                inline: true,
                transition: "none",
                opacity: 1,
                reposition: true,
                scrolling: false,
                href: $videoLB,
                trapFocus: false,
                height: "720px",
                width: "660px",
                onOpen: function () {
                    //Trap focus
                    $("body").on("keydown.colorboxTab", '.able-button-handler-fullscreen', function (e) {
                        var pressedKey = (e.keyCode ? e.keyCode : e.which);
                        // Check for TAB key press
                        if (pressedKey === 9) {
                            if (!e.shiftKey) {
                                $("body").find("#HelperPlayer").focus();
                                e.preventDefault();
                            }
                        }
                    });
                    $("body").on("keydown.colorboxTab", "#HelperPlayer", function (e) {
                        var pressedKey = (e.keyCode ? e.keyCode : e.which);
                        // Check for TAB key press
                        if (pressedKey === 9) {
                            // SHIFT + TAB key
                            if (e.shiftKey) {
                                $('.able-button-handler-fullscreen').first().focus();
                                e.preventDefault();
                            }
                        }
                        else {
                            if (pressedKey === 13) {
                                $('#cboxClose').click();
                                e.preventDefault();
                            }
                        }
                    });
                    $("body").on("focus.colorboxTab", "#HelperPlayer", function () {
                        $('#cboxClose').addClass("ccl-explicithighlights");

                    });
                    $("body").on("focusout.colorboxTab", "#HelperPlayer", function () {
                        $('#cboxClose').removeClass("ccl-explicithighlights");
                    });

                    $('#cboxClose').show();
                    $("#cboxClose").attr("tabindex", "-1");
                    setTimeout(function () {
                        $("#HelperPlayer").focus();
                    }, 50);

                    return $('.banners').find(".slides").cycle("pause");
                },
                onClosed: function () {
                    $videoLB.html("");
                    $("body").off(".colorboxTab");
                    return $('#cboxClose').hide();
                },
                onCleanup: function () {
                    return window.setTimeout((function () {
                        return $('.banners').find(".slides").cycle("resume").cycle("next");
                    }), 1000);
                }
            });
            return e.preventDefault();
        });

        //Custom Handler Esc Key general
        $videoLB.off(".ableplayer");
        $videoLB.on('keydown.ableplayer', function (e) {
            //Esc Key
            if (e.which === 27) {
                e.preventDefault();
                e.stopPropagation();

                var skipEventHandler = false;

                //Get element with focus
                var $preferences = $(".able-button-handler-preferences");
                if ($preferences.hasClass("opened")) {
                    skipEventHandler = true;
                    $preferences.removeClass("opened");
                }

                if (!skipEventHandler) {
                    //Close modal
                    $.colorbox.close();
                }
            }
        });

        $videoLB.on("click.ableplayer", ".able-button-handler-preferences", function () {
            $videoLB.find(".able-button-handler-preferences").toggleClass("opened");
        });

        $videoLB.on("click.ableplayer", '#ccl-detail-video-prefs-menu ul li input', function () {
            $videoLB.find(".able-button-handler-preferences").removeClass("opened");
        });
    };

    home.setADACarouselBannerCompliance = function () {
        $(".banners").find(".banner a").each(function () {
            if ($(this).find(".overlay").children().length > 0) {
                $(this).removeAttr("aria-label");
            }
        });
    };

    home.initVideoPlayer = function (el) {
        $videoLB = this.GetVideoLightbox();
        var $linksVideo = el;

        var idYoutube = $linksVideo.data("youtube-able");
        if (idYoutube != "") {
            var $videoTag = $('<div id="able-' + idYoutube + '" class="container-able"><video data-include-transcript="false" data-able-player data-debug preload="auto" \
                data-youtube-id="' + idYoutube + '" width="640" height="370"></video></div>');

            var caps = $linksVideo.data("caption-able");
            if (caps != undefined && caps != "") {
                $trackCaption = $('<track kind="captions" src="' + caps + '">');
                $videoTag.find("video").append($trackCaption);
            }

            var description = $linksVideo.data("description-able");
            if (description != undefined && description != "") {
                this.loadDescriptionAblePlayer(description, $videoTag);
            }

            $videoLB.html("");
            $videoLB.append("<a tabindex='0' id='HelperPlayer' aria-label='Close Video Dialog' role='button' style='outline: 0 !important;height: 0;width: 0;'>&nbsp</a>");
            $videoLB.append($videoTag);
            var ablePlayer = new window.AblePlayer($videoTag.find("video"));
        }
    };

    home.loadDescriptionAblePlayer = function (description, $videoTag) {
        var regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=|\?v=)([^#\&\?]*).*/;
        var match = description.match(regExp);
        if (match && match[2].length == 11) {
            $videoTag.find("video").attr("data-youtube-desc-id", match[2]);
        }
        else {
            $trackDescription = $('<track kind="descriptions" src="' + description + '">');
            $videoTag.find("video").append($trackDescription);
        }
    };

    home.GetVideoLightbox = function() {
        var $modal = $(".video-lightbox");
        if ($modal.length === 0) {
            $("body").append('<div class="video-lightbox" role="dialog" aria-modal="true" aria-labelledby="sr-announce"></div>');
            $modal = $(".video-lightbox");
        }

        return $modal;
    };

    function removeEmptyProperties(obj) {
        for (var key in obj) {
            if (obj[key] == '')
                delete obj[key]
        }
        return obj;
    }

    function getCountdownLayout() {
        return '<span class="num day">{dnn} <span class="label">Days</span></span> \
					<span class="num hour">{hnn} <span class="label">Hours</span></span> \
					<span class="num min">{mnn} <span class="label">Mins</span></span>';
    }

    Carnival.Homepage = $.extend(home, Carnival.Homepage);

    window.Carnival = Carnival;

    $(function () {
        if (Carnival.Homepage.$el.length && !Carnival.Personalizer) {
            Carnival.Homepage.init();
        }
    });

})(jQuery, window.Carnival);
$(document).trigger("CCL-Homepage-loaded");;
/**
 * easyXDM
 * http://easyxdm.net/
 * Copyright(c) 2009, Øyvind Sean Kinsey, oyvind@kinsey.no.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
(function (window, document, location, setTimeout, decodeURIComponent, encodeURIComponent) {
/*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
/*global easyXDM, JSON, XMLHttpRequest, window, escape, unescape, ActiveXObject */
//
// easyXDM
// http://easyxdm.net/
// Copyright(c) 2009, Øyvind Sean Kinsey, oyvind@kinsey.no.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

var global = this;
var channelId = Math.floor(Math.random() * 100) * 100; // randomize the initial id in case of multiple closures loaded 
var emptyFn = Function.prototype;
var reURI = /^(http.?:\/\/([^\/\s]+))/; // returns groups for origin (1) and domain (2)
var reParent = /[\-\w]+\/\.\.\//; // matches a foo/../ expression 
var reDoubleSlash = /([^:])\/\//g; // matches // anywhere but in the protocol
var namespace = ""; // stores namespace under which easyXDM object is stored on the page (empty if object is global)
var easyXDM = {};
var _easyXDM = window.easyXDM; // map over global easyXDM in case of overwrite
var IFRAME_PREFIX = "easyXDM_";
var HAS_NAME_PROPERTY_BUG;



// http://peter.michaux.ca/articles/feature-detection-state-of-the-art-browser-scripting
function isHostMethod(object, property){
    var t = typeof object[property];
    return t == 'function' ||
    (!!(t == 'object' && object[property])) ||
    t == 'unknown';
}

function isHostObject(object, property){
    return !!(typeof(object[property]) == 'object' && object[property]);
}

// end

// http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/
function isArray(o){
    return Object.prototype.toString.call(o) === '[object Array]';
}

// end

/*
 * Cross Browser implementation for adding and removing event listeners.
 */
var on, un;
if (isHostMethod(window, "addEventListener")) {
    on = function(target, type, listener){
        target.addEventListener(type, listener, false);
    };
    un = function(target, type, listener){
        target.removeEventListener(type, listener, false);
    };
}
else if (isHostMethod(window, "attachEvent")) {
    on = function(object, sEvent, fpNotify){
        object.attachEvent("on" + sEvent, fpNotify);
    };
    un = function(object, sEvent, fpNotify){
        object.detachEvent("on" + sEvent, fpNotify);
    };
}
else {
    throw new Error("Browser not supported");
}

/*
 * Cross Browser implementation of DOMContentLoaded.
 */
var domIsReady = false, domReadyQueue = [], readyState;
if ("readyState" in document) {
    // If browser is WebKit-powered, check for both 'loaded' (legacy browsers) and
    // 'interactive' (HTML5 specs, recent WebKit builds) states.
    // https://bugs.webkit.org/show_bug.cgi?id=45119
    readyState = document.readyState;
    domIsReady = readyState == "complete" || (~ navigator.userAgent.indexOf('AppleWebKit/') && (readyState == "loaded" || readyState == "interactive"));
}
else {
    // If readyState is not supported in the browser, then in order to be able to fire whenReady functions apropriately
    // when added dynamically _after_ DOM load, we have to deduce wether the DOM is ready or not.
    // We only need a body to add elements to, so the existence of document.body is enough for us.
    domIsReady = !!document.body;
}

function dom_onReady(){
    dom_onReady = emptyFn;
    domIsReady = true;
    for (var i = 0; i < domReadyQueue.length; i++) {
        domReadyQueue[i]();
    }
    domReadyQueue.length = 0;
}


if (!domIsReady) {
    if (isHostMethod(window, "addEventListener")) {
        on(document, "DOMContentLoaded", dom_onReady);
    }
    else {
        on(document, "readystatechange", function(){
            if (document.readyState == "complete") {
                dom_onReady();
            }
        });
    }
    
    // A fallback to window.onload, that will always work
    on(window, "load", dom_onReady);
}
/**
 * This will add a function to the queue of functions to be run once the DOM reaches a ready state.
 * If functions are added after this event then they will be executed immediately.
 * @param {function} fn The function to add
 * @param {Object} scope An optional scope for the function to be called with.
 */
function whenReady(fn, scope){
    if (domIsReady) {
        fn.call(scope);
        return;
    }
    domReadyQueue.push(function(){
        fn.call(scope);
    });
}

/**
 * Returns an instance of easyXDM from the parent window with
 * respect to the namespace.
 *
 * @return An instance of easyXDM (in the parent window)
 */
function getParentObject(){
    var obj = parent;
    if (namespace !== "") {
        for (var i = 0, ii = namespace.split("."); i < ii.length; i++) {
            obj = obj[ii[i]];
        }
    }
    return obj.easyXDM;
}

/**
 * Removes easyXDM variable from the global scope. It also returns control
 * of the easyXDM variable to whatever code used it before.
 *
 * @param {String} ns A string representation of an object that will hold
 *                    an instance of easyXDM.
 * @return An instance of easyXDM
 */
function noConflict(ns){
    
    window.easyXDM = _easyXDM;
    namespace = ns;
    if (namespace) {
        IFRAME_PREFIX = "easyXDM_" + namespace.replace(".", "_") + "_";
    }
    return easyXDM;
}

/*
 * Methods for working with URLs
 */
/**
 * Get the domain name from a url.
 * @param {String} url The url to extract the domain from.
 * @return The domain part of the url.
 * @type {String}
 */
function getDomainName(url){
    return url.match(reURI)[2];
}

/**
 * Returns  a string containing the schema, domain and if present the port
 * @param {String} url The url to extract the location from
 * @return {String} The location part of the url
 */
function getLocation(url){
    return url.match(reURI)[1];
}

/**
 * Resolves a relative url into an absolute one.
 * @param {String} url The path to resolve.
 * @return {String} The resolved url.
 */
function resolveUrl(url){
    
    // replace all // except the one in proto with /
    url = url.replace(reDoubleSlash, "$1/");
    
    // If the url is a valid url we do nothing
    if (!url.match(/^(http||https):\/\//)) {
        // If this is a relative path
        var path = (url.substring(0, 1) === "/") ? "" : location.pathname;
        if (path.substring(path.length - 1) !== "/") {
            path = path.substring(0, path.lastIndexOf("/") + 1);
        }
        
        url = location.protocol + "//" + location.host + path + url;
    }
    
    // reduce all 'xyz/../' to just '' 
    while (reParent.test(url)) {
        url = url.replace(reParent, "");
    }
    
    return url;
}

/**
 * Appends the parameters to the given url.<br/>
 * The base url can contain existing query parameters.
 * @param {String} url The base url.
 * @param {Object} parameters The parameters to add.
 * @return {String} A new valid url with the parameters appended.
 */
function appendQueryParameters(url, parameters){
    
    var hash = "", indexOf = url.indexOf("#");
    if (indexOf !== -1) {
        hash = url.substring(indexOf);
        url = url.substring(0, indexOf);
    }
    var q = [];
    for (var key in parameters) {
        if (parameters.hasOwnProperty(key)) {
            q.push(key + "=" + encodeURIComponent(parameters[key]));
        }
    }
    return url + ((url.indexOf("?") === -1) ? "?" : "&") + q.join("&") + hash;
}

var query = (function(){
    var query = {}, pair, search = location.search.substring(1).split("&"), i = search.length;
    while (i--) {
        pair = search[i].split("=");
        query[pair[0]] = decodeURIComponent(pair[1]);
    }
    return query;
}());

/*
 * Helper methods
 */
/**
 * Helper for checking if a variable/property is undefined
 * @param {Object} v The variable to test
 * @return {Boolean} True if the passed variable is undefined
 */
function undef(v){
    return typeof v === "undefined";
}

/**
 * A safe implementation of HTML5 JSON. Feature testing is used to make sure the implementation works.
 * @return {JSON} A valid JSON conforming object, or null if not found.
 */
function getJSON(){
    var cached = {};
    var obj = {
        a: [1, 2, 3]
    }, json = "{\"a\":[1,2,3]}";
    
    if (JSON && typeof JSON.stringify === "function" && JSON.stringify(obj).replace((/\s/g), "") === json) {
        // this is a working JSON instance
        return JSON;
    }
    if (Object.toJSON) {
        if (Object.toJSON(obj).replace((/\s/g), "") === json) {
            // this is a working stringify method
            cached.stringify = Object.toJSON;
        }
    }
    
    if (typeof String.prototype.evalJSON === "function") {
        obj = json.evalJSON();
        if (obj.a && obj.a.length === 3 && obj.a[2] === 3) {
            // this is a working parse method           
            cached.parse = function(str){
                return str.evalJSON();
            };
        }
    }
    
    if (cached.stringify && cached.parse) {
        // Only memoize the result if we have valid instance
        getJSON = function(){
            return cached;
        };
        return cached;
    }
    return null;
}

/**
 * Applies properties from the source object to the target object.<br/>
 * @param {Object} target The target of the properties.
 * @param {Object} source The source of the properties.
 * @param {Boolean} noOverwrite Set to True to only set non-existing properties.
 */
function apply(destination, source, noOverwrite){
    var member;
    for (var prop in source) {
        if (source.hasOwnProperty(prop)) {
            if (prop in destination) {
                member = source[prop];
                if (typeof member === "object") {
                    apply(destination[prop], member, noOverwrite);
                }
                else if (!noOverwrite) {
                    destination[prop] = source[prop];
                }
            }
            else {
                destination[prop] = source[prop];
            }
        }
    }
    return destination;
}

// This tests for the bug in IE where setting the [name] property using javascript causes the value to be redirected into [submitName].
function testForNamePropertyBug(){
    var el = document.createElement("iframe");
    el.name = IFRAME_PREFIX + "TEST";
    apply(el.style, {
        position: "absolute",
        left: "-2000px",
        top: "0px"
    });
    document.body.appendChild(el);
    HAS_NAME_PROPERTY_BUG = !(el.contentWindow === window.frames[el.name]);
    document.body.removeChild(el);
}

/**
 * Creates a frame and appends it to the DOM.
 * @param config {object} This object can have the following properties
 * <ul>
 * <li> {object} prop The properties that should be set on the frame. This should include the 'src' property.</li>
 * <li> {object} attr The attributes that should be set on the frame.</li>
 * <li> {DOMElement} container Its parent element (Optional).</li>
 * <li> {function} onLoad A method that should be called with the frames contentWindow as argument when the frame is fully loaded. (Optional)</li>
 * </ul>
 * @return The frames DOMElement
 * @type DOMElement
 */
function createFrame(config){
    if (undef(HAS_NAME_PROPERTY_BUG)) {
        testForNamePropertyBug();
    }
    var frame;
    // This is to work around the problems in IE6/7 with setting the name property. 
    // Internally this is set as 'submitName' instead when using 'iframe.name = ...'
    // This is not required by easyXDM itself, but is to facilitate other use cases 
    if (HAS_NAME_PROPERTY_BUG) {
        frame = document.createElement("<iframe name=\"" + config.props.name + "\"/>");
    }
    else {
        frame = document.createElement("IFRAME");
        frame.name = config.props.name;
    }
    
    frame.id = frame.name = config.props.name;
    delete config.props.name;
    
    if (config.onLoad) {
        on(frame, "load", config.onLoad);
    }
    
    if (typeof config.container == "string") {
        config.container = document.getElementById(config.container);
    }
    
    if (!config.container) {
        // This needs to be hidden like this, simply setting display:none and the like will cause failures in some browsers.
        frame.style.position = "absolute";
        frame.style.left = "-2000px";
        frame.style.top = "0px";
        config.container = document.body;
    }
    
    frame.border = frame.frameBorder = 0;
    config.container.insertBefore(frame, config.container.firstChild);
    
    // transfer properties to the frame
    apply(frame, config.props);
    return frame;
}

/**
 * Check whether a domain is allowed using an Access Control List.
 * The ACL can contain * and ? as wildcards, or can be regular expressions.
 * If regular expressions they need to begin with ^ and end with $.
 * @param {Array/String} acl The list of allowed domains
 * @param {String} domain The domain to test.
 * @return {Boolean} True if the domain is allowed, false if not.
 */
function checkAcl(acl, domain){
    // normalize into an array
    if (typeof acl == "string") {
        acl = [acl];
    }
    var re, i = acl.length;
    while (i--) {
        re = acl[i];
        re = new RegExp(re.substr(0, 1) == "^" ? re : ("^" + re.replace(/(\*)/g, ".$1").replace(/\?/g, ".") + "$"));
        if (re.test(domain)) {
            return true;
        }
    }
    return false;
}

/*
 * Functions related to stacks
 */
/**
 * Prepares an array of stack-elements suitable for the current configuration
 * @param {Object} config The Transports configuration. See easyXDM.Socket for more.
 * @return {Array} An array of stack-elements with the TransportElement at index 0.
 */
function prepareTransportStack(config){
    var protocol = config.protocol, stackEls;
    config.isHost = config.isHost || undef(query.xdm_p);
    
    if (!config.props) {
        config.props = {};
    }
    if (!config.isHost) {
        config.channel = query.xdm_c;
        config.secret = query.xdm_s;
        config.remote = query.xdm_e;
        protocol = query.xdm_p;
        if (config.acl && !checkAcl(config.acl, config.remote)) {
            throw new Error("Access denied for " + config.remote);
        }
    }
    else {
        config.remote = resolveUrl(config.remote);
        config.channel = config.channel || "default" + channelId++;
        config.secret = Math.random().toString(16).substring(2);
        if (undef(protocol)) {
            if (getLocation(location.href) == getLocation(config.remote)) {
                /*
                 * Both documents has the same origin, lets use direct access.
                 */
                protocol = "4";
            }
            else if (isHostMethod(window, "postMessage") || isHostMethod(document, "postMessage")) {
                /*
                 * This is supported in IE8+, Firefox 3+, Opera 9+, Chrome 2+ and Safari 4+
                 */
                protocol = "1";
            }
            else if (isHostMethod(window, "ActiveXObject") && isHostMethod(window, "execScript")) {
                /*
                 * This is supported in IE6 and IE7
                 */
                protocol = "3";
            }
            else if (navigator.product === "Gecko" && "frameElement" in window && navigator.userAgent.indexOf('WebKit') == -1) {
                /*
                 * This is supported in Gecko (Firefox 1+)
                 */
                protocol = "5";
            }
            else if (config.remoteHelper) {
                /*
                 * This is supported in all browsers that retains the value of window.name when
                 * navigating from one domain to another, and where parent.frames[foo] can be used
                 * to get access to a frame from the same domain
                 */
                config.remoteHelper = resolveUrl(config.remoteHelper);
                protocol = "2";
            }
            else {
                /*
                 * This is supported in all browsers where [window].location is writable for all
                 * The resize event will be used if resize is supported and the iframe is not put
                 * into a container, else polling will be used.
                 */
                protocol = "0";
            }
        }
    }
    
    switch (protocol) {
        case "0":// 0 = HashTransport
            apply(config, {
                interval: 100,
                delay: 2000,
                useResize: true,
                useParent: false,
                usePolling: false
            }, true);
            if (config.isHost) {
                if (!config.local) {
                    // If no local is set then we need to find an image hosted on the current domain
                    var domain = location.protocol + "//" + location.host, images = document.body.getElementsByTagName("img"), image;
                    var i = images.length;
                    while (i--) {
                        image = images[i];
                        if (image.src.substring(0, domain.length) === domain) {
                            config.local = image.src;
                            break;
                        }
                    }
                    if (!config.local) {
                        // If no local was set, and we are unable to find a suitable file, then we resort to using the current window 
                        config.local = window;
                    }
                }
                
                var parameters = {
                    xdm_c: config.channel,
                    xdm_p: 0
                };
                
                if (config.local === window) {
                    // We are using the current window to listen to
                    config.usePolling = true;
                    config.useParent = true;
                    config.local = location.protocol + "//" + location.host + location.pathname + location.search;
                    parameters.xdm_e = config.local;
                    parameters.xdm_pa = 1; // use parent
                }
                else {
                    parameters.xdm_e = resolveUrl(config.local);
                }
                
                if (config.container) {
                    config.useResize = false;
                    parameters.xdm_po = 1; // use polling
                }
                config.remote = appendQueryParameters(config.remote, parameters);
            }
            else {
                apply(config, {
                    channel: query.xdm_c,
                    remote: query.xdm_e,
                    useParent: !undef(query.xdm_pa),
                    usePolling: !undef(query.xdm_po),
                    useResize: config.useParent ? false : config.useResize
                });
            }
            stackEls = [new easyXDM.stack.HashTransport(config), new easyXDM.stack.ReliableBehavior({}), new easyXDM.stack.QueueBehavior({
                encode: true,
                maxLength: 4000 - config.remote.length
            }), new easyXDM.stack.VerifyBehavior({
                initiate: config.isHost
            })];
            break;
        case "1":
            stackEls = [new easyXDM.stack.PostMessageTransport(config)];
            break;
        case "2":
            stackEls = [new easyXDM.stack.NameTransport(config), new easyXDM.stack.QueueBehavior(), new easyXDM.stack.VerifyBehavior({
                initiate: config.isHost
            })];
            break;
        case "3":
            stackEls = [new easyXDM.stack.NixTransport(config)];
            break;
        case "4":
            stackEls = [new easyXDM.stack.SameOriginTransport(config)];
            break;
        case "5":
            stackEls = [new easyXDM.stack.FrameElementTransport(config)];
            break;
    }
    // this behavior is responsible for buffering outgoing messages, and for performing lazy initialization
    stackEls.push(new easyXDM.stack.QueueBehavior({
        lazy: config.lazy,
        remove: true
    }));
    return stackEls;
}

/**
 * Chains all the separate stack elements into a single usable stack.<br/>
 * If an element is missing a necessary method then it will have a pass-through method applied.
 * @param {Array} stackElements An array of stack elements to be linked.
 * @return {easyXDM.stack.StackElement} The last element in the chain.
 */
function chainStack(stackElements){
    var stackEl, defaults = {
        incoming: function(message, origin){
            this.up.incoming(message, origin);
        },
        outgoing: function(message, recipient){
            this.down.outgoing(message, recipient);
        },
        callback: function(success){
            this.up.callback(success);
        },
        init: function(){
            this.down.init();
        },
        destroy: function(){
            this.down.destroy();
        }
    };
    for (var i = 0, len = stackElements.length; i < len; i++) {
        stackEl = stackElements[i];
        apply(stackEl, defaults, true);
        if (i !== 0) {
            stackEl.down = stackElements[i - 1];
        }
        if (i !== len - 1) {
            stackEl.up = stackElements[i + 1];
        }
    }
    return stackEl;
}

/**
 * This will remove a stackelement from its stack while leaving the stack functional.
 * @param {Object} element The elment to remove from the stack.
 */
function removeFromStack(element){
    element.up.down = element.down;
    element.down.up = element.up;
    element.up = element.down = null;
}

/*
 * Export the main object and any other methods applicable
 */
/** 
 * @class easyXDM
 * A javascript library providing cross-browser, cross-domain messaging/RPC.
 * @version 2.4.10.103
 * @singleton
 */
apply(easyXDM, {
    /**
     * The version of the library
     * @type {string}
     */
    version: "2.4.10.103",
    /**
     * This is a map containing all the query parameters passed to the document.
     * All the values has been decoded using decodeURIComponent.
     * @type {object}
     */
    query: query,
    /**
     * @private
     */
    stack: {},
    /**
     * Applies properties from the source object to the target object.<br/>
     * @param {object} target The target of the properties.
     * @param {object} source The source of the properties.
     * @param {boolean} noOverwrite Set to True to only set non-existing properties.
     */
    apply: apply,
    
    /**
     * A safe implementation of HTML5 JSON. Feature testing is used to make sure the implementation works.
     * @return {JSON} A valid JSON conforming object, or null if not found.
     */
    getJSONObject: getJSON,
    /**
     * This will add a function to the queue of functions to be run once the DOM reaches a ready state.
     * If functions are added after this event then they will be executed immediately.
     * @param {function} fn The function to add
     * @param {object} scope An optional scope for the function to be called with.
     */
    whenReady: whenReady,
    /**
     * Removes easyXDM variable from the global scope. It also returns control
     * of the easyXDM variable to whatever code used it before.
     *
     * @param {String} ns A string representation of an object that will hold
     *                    an instance of easyXDM.
     * @return An instance of easyXDM
     */
    noConflict: noConflict
});

/*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
/*global console, _FirebugCommandLine,  easyXDM, window, escape, unescape, isHostObject, undef, _trace, domIsReady, emptyFn, namespace */
//
// easyXDM
// http://easyxdm.net/
// Copyright(c) 2009, Øyvind Sean Kinsey, oyvind@kinsey.no.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

/*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
/*global easyXDM, window, escape, unescape, isHostObject, isHostMethod, un, on, createFrame, debug */
//
// easyXDM
// http://easyxdm.net/
// Copyright(c) 2009, Øyvind Sean Kinsey, oyvind@kinsey.no.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

/** 
 * @class easyXDM.DomHelper
 * Contains methods for dealing with the DOM
 * @singleton
 */
easyXDM.DomHelper = {
    /**
     * Provides a consistent interface for adding eventhandlers
     * @param {Object} target The target to add the event to
     * @param {String} type The name of the event
     * @param {Function} listener The listener
     */
    on: on,
    /**
     * Provides a consistent interface for removing eventhandlers
     * @param {Object} target The target to remove the event from
     * @param {String} type The name of the event
     * @param {Function} listener The listener
     */
    un: un,
    /**
     * Checks for the presence of the JSON object.
     * If it is not present it will use the supplied path to load the JSON2 library.
     * This should be called in the documents head right after the easyXDM script tag.
     * http://json.org/json2.js
     * @param {String} path A valid path to json2.js
     */
    requiresJSON: function(path){
        if (!isHostObject(window, "JSON")) {
            document.write('<script type="text/javascript" src="' + path + '"></script>');
        }
    }
};
/*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
/*global easyXDM, window, escape, unescape, debug */
//
// easyXDM
// http://easyxdm.net/
// Copyright(c) 2009, Øyvind Sean Kinsey, oyvind@kinsey.no.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

(function(){
    // The map containing the stored functions
    var _map = {};
    
    /**
     * @class easyXDM.Fn
     * This contains methods related to function handling, such as storing callbacks.
     * @singleton
     * @namespace easyXDM
     */
    easyXDM.Fn = {
        /**
         * Stores a function using the given name for reference
         * @param {String} name The name that the function should be referred by
         * @param {Function} fn The function to store
         * @namespace easyXDM.fn
         */
        set: function(name, fn){
            _map[name] = fn;
        },
        /**
         * Retrieves the function referred to by the given name
         * @param {String} name The name of the function to retrieve
         * @param {Boolean} del If the function should be deleted after retrieval
         * @return {Function} The stored function
         * @namespace easyXDM.fn
         */
        get: function(name, del){
            var fn = _map[name];
            
            if (del) {
                delete _map[name];
            }
            return fn;
        }
    };
    
}());
/*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
/*global easyXDM, window, escape, unescape, chainStack, prepareTransportStack, getLocation, debug */
//
// easyXDM
// http://easyxdm.net/
// Copyright(c) 2009, Øyvind Sean Kinsey, oyvind@kinsey.no.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

/**
 * @class easyXDM.Socket
 * This class creates a transport channel between two domains that is usable for sending and receiving string-based messages.<br/>
 * The channel is reliable, supports queueing, and ensures that the message originates from the expected domain.<br/>
 * Internally different stacks will be used depending on the browsers features and the available parameters.
 * <h2>How to set up</h2>
 * Setting up the provider:
 * <pre><code>
 * var socket = new easyXDM.Socket({
 * &nbsp; local: "name.html",
 * &nbsp; onReady: function(){
 * &nbsp; &nbsp; &#47;&#47; you need to wait for the onReady callback before using the socket
 * &nbsp; &nbsp; socket.postMessage("foo-message");
 * &nbsp; },
 * &nbsp; onMessage: function(message, origin) {
 * &nbsp;&nbsp; alert("received " + message + " from " + origin);
 * &nbsp; }
 * });
 * </code></pre>
 * Setting up the consumer:
 * <pre><code>
 * var socket = new easyXDM.Socket({
 * &nbsp; remote: "http:&#47;&#47;remotedomain/page.html",
 * &nbsp; remoteHelper: "http:&#47;&#47;remotedomain/name.html",
 * &nbsp; onReady: function(){
 * &nbsp; &nbsp; &#47;&#47; you need to wait for the onReady callback before using the socket
 * &nbsp; &nbsp; socket.postMessage("foo-message");
 * &nbsp; },
 * &nbsp; onMessage: function(message, origin) {
 * &nbsp;&nbsp; alert("received " + message + " from " + origin);
 * &nbsp; }
 * });
 * </code></pre>
 * If you are unable to upload the <code>name.html</code> file to the consumers domain then remove the <code>remoteHelper</code> property
 * and easyXDM will fall back to using the HashTransport instead of the NameTransport when not able to use any of the primary transports.
 * @namespace easyXDM
 * @constructor
 * @cfg {String/Window} local The url to the local name.html document, a local static file, or a reference to the local window.
 * @cfg {Boolean} lazy (Consumer only) Set this to true if you want easyXDM to defer creating the transport until really needed. 
 * @cfg {String} remote (Consumer only) The url to the providers document.
 * @cfg {String} remoteHelper (Consumer only) The url to the remote name.html file. This is to support NameTransport as a fallback. Optional.
 * @cfg {Number} delay The number of milliseconds easyXDM should try to get a reference to the local window.  Optional, defaults to 2000.
 * @cfg {Number} interval The interval used when polling for messages. Optional, defaults to 300.
 * @cfg {String} channel (Consumer only) The name of the channel to use. Can be used to set consistent iframe names. Must be unique. Optional.
 * @cfg {Function} onMessage The method that should handle incoming messages.<br/> This method should accept two arguments, the message as a string, and the origin as a string. Optional.
 * @cfg {Function} onReady A method that should be called when the transport is ready. Optional.
 * @cfg {DOMElement|String} container (Consumer only) The element, or the id of the element that the primary iframe should be inserted into. If not set then the iframe will be positioned off-screen. Optional.
 * @cfg {Array/String} acl (Provider only) Here you can specify which '[protocol]://[domain]' patterns that should be allowed to act as the consumer towards this provider.<br/>
 * This can contain the wildcards ? and *.  Examples are 'http://example.com', '*.foo.com' and '*dom?.com'. If you want to use reqular expressions then you pattern needs to start with ^ and end with $.
 * If none of the patterns match an Error will be thrown.  
 * @cfg {Object} props (Consumer only) Additional properties that should be applied to the iframe. This can also contain nested objects e.g: <code>{style:{width:"100px", height:"100px"}}</code>. 
 * Properties such as 'name' and 'src' will be overrided. Optional.
 */
easyXDM.Socket = function(config){
    
    // create the stack
    var stack = chainStack(prepareTransportStack(config).concat([{
        incoming: function(message, origin){
            config.onMessage(message, origin);
        },
        callback: function(success){
            if (config.onReady) {
                config.onReady(success);
            }
        }
    }])), recipient = getLocation(config.remote);
    
    // set the origin
    this.origin = getLocation(config.remote);
	
    /**
     * Initiates the destruction of the stack.
     */
    this.destroy = function(){
        stack.destroy();
    };
    
    /**
     * Posts a message to the remote end of the channel
     * @param {String} message The message to send
     */
    this.postMessage = function(message){
        stack.outgoing(message, recipient);
    };
    
    stack.init();
};
/*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
/*global easyXDM, window, escape, unescape, undef,, chainStack, prepareTransportStack, debug, getLocation */
//
// easyXDM
// http://easyxdm.net/
// Copyright(c) 2009, Øyvind Sean Kinsey, oyvind@kinsey.no.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

/** 
 * @class easyXDM.Rpc
 * Creates a proxy object that can be used to call methods implemented on the remote end of the channel, and also to provide the implementation
 * of methods to be called from the remote end.<br/>
 * The instantiated object will have methods matching those specified in <code>config.remote</code>.<br/>
 * This requires the JSON object present in the document, either natively, using json.org's json2 or as a wrapper around library spesific methods.
 * <h2>How to set up</h2>
 * <pre><code>
 * var rpc = new easyXDM.Rpc({
 * &nbsp; &#47;&#47; this configuration is equal to that used by the Socket.
 * &nbsp; remote: "http:&#47;&#47;remotedomain/...",
 * &nbsp; onReady: function(){
 * &nbsp; &nbsp; &#47;&#47; you need to wait for the onReady callback before using the proxy
 * &nbsp; &nbsp; rpc.foo(...
 * &nbsp; }
 * },{
 * &nbsp; local: {..},
 * &nbsp; remote: {..}
 * });
 * </code></pre>
 * 
 * <h2>Exposing functions (procedures)</h2>
 * <pre><code>
 * var rpc = new easyXDM.Rpc({
 * &nbsp; ...
 * },{
 * &nbsp; local: {
 * &nbsp; &nbsp; nameOfMethod: {
 * &nbsp; &nbsp; &nbsp; method: function(arg1, arg2, success, error){
 * &nbsp; &nbsp; &nbsp; &nbsp; ...
 * &nbsp; &nbsp; &nbsp; }
 * &nbsp; &nbsp; },
 * &nbsp; &nbsp; &#47;&#47; with shorthand notation 
 * &nbsp; &nbsp; nameOfAnotherMethod:  function(arg1, arg2, success, error){
 * &nbsp; &nbsp; }
 * &nbsp; },
 * &nbsp; remote: {...}
 * });
 * </code></pre>

 * The function referenced by  [method] will receive the passed arguments followed by the callback functions <code>success</code> and <code>error</code>.<br/>
 * To send a successfull result back you can use
 *     <pre><code>
 *     return foo;
 *     </pre></code>
 * or
 *     <pre><code>
 *     success(foo);
 *     </pre></code>
 *  To return an error you can use
 *     <pre><code>
 *     throw new Error("foo error");
 *     </code></pre>
 * or
 *     <pre><code>
 *     error("foo error");
 *     </code></pre>
 *
 * <h2>Defining remotely exposed methods (procedures/notifications)</h2>
 * The definition of the remote end is quite similar:
 * <pre><code>
 * var rpc = new easyXDM.Rpc({
 * &nbsp; ...
 * },{
 * &nbsp; local: {...},
 * &nbsp; remote: {
 * &nbsp; &nbsp; nameOfMethod: {}
 * &nbsp; }
 * });
 * </code></pre>
 * To call a remote method use
 * <pre><code>
 * rpc.nameOfMethod("arg1", "arg2", function(value) {
 * &nbsp; alert("success: " + value);
 * }, function(message) {
 * &nbsp; alert("error: " + message + );
 * });
 * </code></pre>
 * Both the <code>success</code> and <code>errror</code> callbacks are optional.<br/>
 * When called with no callback a JSON-RPC 2.0 notification will be executed.
 * Be aware that you will not be notified of any errors with this method.
 * <br/>
 * <h2>Specifying a custom serializer</h2>
 * If you do not want to use the JSON2 library for non-native JSON support, but instead capabilities provided by some other library
 * then you can specify a custom serializer using <code>serializer: foo</code>
 * <pre><code>
 * var rpc = new easyXDM.Rpc({
 * &nbsp; ...
 * },{
 * &nbsp; local: {...},
 * &nbsp; remote: {...},
 * &nbsp; serializer : {
 * &nbsp; &nbsp; parse: function(string){ ... },
 * &nbsp; &nbsp; stringify: function(object) {...}
 * &nbsp; }
 * });
 * </code></pre>
 * If <code>serializer</code> is set then the class will not attempt to use the native implementation.
 * @namespace easyXDM
 * @constructor
 * @param {Object} config The underlying transports configuration. See easyXDM.Socket for available parameters.
 * @param {Object} jsonRpcConfig The description of the interface to implement.
 */
easyXDM.Rpc = function(config, jsonRpcConfig){
    
    // expand shorthand notation
    if (jsonRpcConfig.local) {
        for (var method in jsonRpcConfig.local) {
            if (jsonRpcConfig.local.hasOwnProperty(method)) {
                var member = jsonRpcConfig.local[method];
                if (typeof member === "function") {
                    jsonRpcConfig.local[method] = {
                        method: member
                    };
                }
            }
        }
    }
	
    // create the stack
    var stack = chainStack(prepareTransportStack(config).concat([new easyXDM.stack.RpcBehavior(this, jsonRpcConfig), {
        callback: function(success){
            if (config.onReady) {
                config.onReady(success);
            }
        }
    }]));
	
    // set the origin 
    this.origin = getLocation(config.remote);
	
    
    /**
     * Initiates the destruction of the stack.
     */
    this.destroy = function(){
        stack.destroy();
    };
    
    stack.init();
};
/*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
/*global easyXDM, window, escape, unescape, getLocation, appendQueryParameters, createFrame, debug, un, on, apply, whenReady, getParentObject, IFRAME_PREFIX*/
//
// easyXDM
// http://easyxdm.net/
// Copyright(c) 2009, Øyvind Sean Kinsey, oyvind@kinsey.no.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

/**
 * @class easyXDM.stack.SameOriginTransport
 * SameOriginTransport is a transport class that can be used when both domains have the same origin.<br/>
 * This can be useful for testing and for when the main application supports both internal and external sources.
 * @namespace easyXDM.stack
 * @constructor
 * @param {Object} config The transports configuration.
 * @cfg {String} remote The remote document to communicate with.
 */
easyXDM.stack.SameOriginTransport = function(config){
    var pub, frame, send, targetOrigin;
    
    return (pub = {
        outgoing: function(message, domain, fn){
            send(message);
            if (fn) {
                fn();
            }
        },
        destroy: function(){
            if (frame) {
                frame.parentNode.removeChild(frame);
                frame = null;
            }
        },
        onDOMReady: function(){
            targetOrigin = getLocation(config.remote);
            
            if (config.isHost) {
                // set up the iframe
                apply(config.props, {
                    src: appendQueryParameters(config.remote, {
                        xdm_e: location.protocol + "//" + location.host + location.pathname,
                        xdm_c: config.channel,
                        xdm_p: 4 // 4 = SameOriginTransport
                    }),
                    name: IFRAME_PREFIX + config.channel + "_provider"
                });
                frame = createFrame(config);
                easyXDM.Fn.set(config.channel, function(sendFn){
                    send = sendFn;
                    setTimeout(function(){
                        pub.up.callback(true);
                    }, 0);
                    return function(msg){
                        pub.up.incoming(msg, targetOrigin);
                    };
                });
            }
            else {
                send = getParentObject().Fn.get(config.channel, true)(function(msg){
                    pub.up.incoming(msg, targetOrigin);
                });
                setTimeout(function(){
                    pub.up.callback(true);
                }, 0);
            }
        },
        init: function(){
            whenReady(pub.onDOMReady, pub);
        }
    });
};
/*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
/*global easyXDM, window, escape, unescape, getLocation, appendQueryParameters, createFrame, debug, un, on, apply, whenReady, IFRAME_PREFIX*/
//
// easyXDM
// http://easyxdm.net/
// Copyright(c) 2009, Øyvind Sean Kinsey, oyvind@kinsey.no.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

/**
 * @class easyXDM.stack.PostMessageTransport
 * PostMessageTransport is a transport class that uses HTML5 postMessage for communication.<br/>
 * <a href="http://msdn.microsoft.com/en-us/library/ms644944(VS.85).aspx">http://msdn.microsoft.com/en-us/library/ms644944(VS.85).aspx</a><br/>
 * <a href="https://developer.mozilla.org/en/DOM/window.postMessage">https://developer.mozilla.org/en/DOM/window.postMessage</a>
 * @namespace easyXDM.stack
 * @constructor
 * @param {Object} config The transports configuration.
 * @cfg {String} remote The remote domain to communicate with.
 */
easyXDM.stack.PostMessageTransport = function(config){
    var pub, // the public interface
 frame, // the remote frame, if any
 callerWindow, // the window that we will call with
 targetOrigin; // the domain to communicate with
    /**
     * Resolves the origin from the event object
     * @private
     * @param {Object} event The messageevent
     * @return {String} The scheme, host and port of the origin
     */
    function _getOrigin(event){
        if (event.origin) {
            // This is the HTML5 property
            return event.origin;
        }
        if (event.uri) {
            // From earlier implementations 
            return getLocation(event.uri);
        }
        if (event.domain) {
            // This is the last option and will fail if the 
            // origin is not using the same schema as we are
            return location.protocol + "//" + event.domain;
        }
        throw "Unable to retrieve the origin of the event";
    }
    
    /**
     * This is the main implementation for the onMessage event.<br/>
     * It checks the validity of the origin and passes the message on if appropriate.
     * @private
     * @param {Object} event The messageevent
     */
    function _window_onMessage(event){
        var origin = _getOrigin(event);
        if (origin == targetOrigin && event.data.substring(0, config.channel.length + 1) == config.channel + " ") {
            pub.up.incoming(event.data.substring(config.channel.length + 1), origin);
        }
    }
    
    return (pub = {
        outgoing: function(message, domain, fn){
            callerWindow.postMessage(config.channel + " " + message, domain || targetOrigin);
            if (fn) {
                fn();
            }
        },
        destroy: function(){
            un(window, "message", _window_onMessage);
            if (frame) {
                callerWindow = null;
                frame.parentNode.removeChild(frame);
                frame = null;
            }
        },
        onDOMReady: function(){
            targetOrigin = getLocation(config.remote);
            if (config.isHost) {
                // add the event handler for listening
                on(window, "message", function waitForReady(event){
                    if (event.data == config.channel + "-ready") {
                        // replace the eventlistener
                        callerWindow = ("postMessage" in frame.contentWindow) ? frame.contentWindow : frame.contentWindow.document;
                        un(window, "message", waitForReady);
                        on(window, "message", _window_onMessage);
                        setTimeout(function(){
                            pub.up.callback(true);
                        }, 0);
                    }
                });
                
                // set up the iframe
                apply(config.props, {
                    src: appendQueryParameters(config.remote, {
                        xdm_e: location.protocol + "//" + location.host,
                        xdm_c: config.channel,
                        xdm_p: 1 // 1 = PostMessage
                    }),
                    name: IFRAME_PREFIX + config.channel + "_provider"
                });
                frame = createFrame(config);
            }
            else {
                // add the event handler for listening
                on(window, "message", _window_onMessage);
                callerWindow = ("postMessage" in window.parent) ? window.parent : window.parent.document;
                callerWindow.postMessage(config.channel + "-ready", targetOrigin);
                
                setTimeout(function(){
                    pub.up.callback(true);
                }, 0);
            }
        },
        init: function(){
            whenReady(pub.onDOMReady, pub);
        }
    });
};
/*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
/*global easyXDM, window, escape, unescape, getLocation, appendQueryParameters, createFrame, debug, apply, query, whenReady, IFRAME_PREFIX*/
//
// easyXDM
// http://easyxdm.net/
// Copyright(c) 2009, Øyvind Sean Kinsey, oyvind@kinsey.no.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

/**
 * @class easyXDM.stack.FrameElementTransport
 * FrameElementTransport is a transport class that can be used with Gecko-browser as these allow passing variables using the frameElement property.<br/>
 * Security is maintained as Gecho uses Lexical Authorization to determine under which scope a function is running.
 * @namespace easyXDM.stack
 * @constructor
 * @param {Object} config The transports configuration.
 * @cfg {String} remote The remote document to communicate with.
 */
easyXDM.stack.FrameElementTransport = function(config){
    var pub, frame, send, targetOrigin;
    
    return (pub = {
        outgoing: function(message, domain, fn){
            send.call(this, message);
            if (fn) {
                fn();
            }
        },
        destroy: function(){
            if (frame) {
                frame.parentNode.removeChild(frame);
                frame = null;
            }
        },
        onDOMReady: function(){
            targetOrigin = getLocation(config.remote);
            
            if (config.isHost) {
                // set up the iframe
                apply(config.props, {
                    src: appendQueryParameters(config.remote, {
                        xdm_e: location.protocol + "//" + location.host + location.pathname + location.search,
                        xdm_c: config.channel,
                        xdm_p: 5 // 5 = FrameElementTransport
                    }),
                    name: IFRAME_PREFIX + config.channel + "_provider"
                });
                frame = createFrame(config);
                frame.fn = function(sendFn){
                    delete frame.fn;
                    send = sendFn;
                    setTimeout(function(){
                        pub.up.callback(true);
                    }, 0);
                    // remove the function so that it cannot be used to overwrite the send function later on
                    return function(msg){
                        pub.up.incoming(msg, targetOrigin);
                    };
                };
            }
            else {
                // This is to mitigate origin-spoofing
                window.parent.location = query.xdm_e + "#";
                send = window.frameElement.fn(function(msg){
                    pub.up.incoming(msg, targetOrigin);
                });
                pub.up.callback(true);
            }
        },
        init: function(){
            whenReady(pub.onDOMReady, pub);
        }
    });
};
/*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
/*global global, getNixProxy, easyXDM, window, escape, unescape, getLocation, appendQueryParameters, createFrame, debug, un, on, isHostMethod, apply, query, whenReady, IFRAME_PREFIX*/
//
// easyXDM
// http://easyxdm.net/
// Copyright(c) 2009, Øyvind Sean Kinsey, oyvind@kinsey.no.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

/**
 * @class easyXDM.stack.NixTransport
 * NixTransport is a transport class that uses the strange fact that in IE <8, the window.opener property can be written to and read from all windows.<br/>
 * This is used to pass methods that are able to relay messages back and forth. To avoid context-leakage a VBScript (COM) object is used to relay all the strings.<br/>
 * This transport is loosely based on the work done by <a href="https://issues.apache.org/jira/browse/SHINDIG-416">Shindig</a>
 * @namespace easyXDM.stack
 * @constructor
 * @param {Object} config The transports configuration.
 * @cfg {String} remote The remote domain to communicate with.
 * @cfg {String} secret the pre-shared secret used to secure the communication.
 */
easyXDM.stack.NixTransport = function(config){
    var pub, // the public interface
 frame, send, targetOrigin, proxy;
    
    return (pub = {
        outgoing: function(message, domain, fn){
            send(message);
            if (fn) {
                fn();
            }
        },
        destroy: function(){
            proxy = null;
            if (frame) {
                frame.parentNode.removeChild(frame);
                frame = null;
            }
        },
        onDOMReady: function(){
            targetOrigin = getLocation(config.remote);
            if (config.isHost) {
                try {
                    if (!isHostMethod(window, "getNixProxy")) {
                        window.execScript('Class NixProxy\n' +
                        '    Private m_parent, m_child, m_Auth\n' +
                        '\n' +
                        '    Public Sub SetParent(obj, auth)\n' +
                        '        If isEmpty(m_Auth) Then m_Auth = auth\n' +
                        '        SET m_parent = obj\n' +
                        '    End Sub\n' +
                        '    Public Sub SetChild(obj)\n' +
                        '        SET m_child = obj\n' +
                        '        m_parent.ready()\n' +
                        '    End Sub\n' +
                        '\n' +
                        // The auth string, which is a pre-shared key between the parent and the child, 
                        // and that can only be set once by the parent, secures the communication, and also serves to provide
                        // 'proof' of the origin of the messages.
                        // Before passing the message on to the recipent we convert the message into a primitive, 
                        // this mitigates modifying .toString as an attack vector.
                        '    Public Sub SendToParent(data, auth)\n' +
                        '        If m_Auth = auth Then m_parent.send(CStr(data))\n' +
                        '    End Sub\n' +
                        '    Public Sub SendToChild(data, auth)\n' +
                        '        If m_Auth = auth Then m_child.send(CStr(data))\n' +
                        '    End Sub\n' +
                        'End Class\n' +
                        'Function getNixProxy()\n' +
                        '    Set GetNixProxy = New NixProxy\n' +
                        'End Function\n', 'vbscript');
                    }
                    proxy = getNixProxy();
                    proxy.SetParent({
                        send: function(msg){
                            pub.up.incoming(msg, targetOrigin);
                        },
                        ready: function(){
                            setTimeout(function(){
                                pub.up.callback(true);
                            }, 0);
                        }
                    }, config.secret);
                    send = function(msg){
                        proxy.SendToChild(msg, config.secret);
                    };
                } 
                catch (e1) {
                    throw new Error("Could not set up VBScript NixProxy:" + e1.message);
                }
                // set up the iframe
                apply(config.props, {
                    src: appendQueryParameters(config.remote, {
                        xdm_e: location.protocol + "//" + location.host + location.pathname + location.search,
                        xdm_c: config.channel,
                        xdm_s: config.secret,
                        xdm_p: 3 // 3 = NixTransport
                    }),
                    name: IFRAME_PREFIX + config.channel + "_provider"
                });
                frame = createFrame(config);
                frame.contentWindow.opener = proxy;
            }
            else {
                // This is to mitigate origin-spoofing
                window.parent.location = query.xdm_e + "#";
                try {
                    // by storing this in a variable we negate replacement attacks
                    proxy = window.opener;
                } 
                catch (e2) {
                    throw new Error("Cannot access window.opener");
                }
                proxy.SetChild({
                    send: function(msg){
                        // the timeout is necessary to have execution continue in the correct context
                        global.setTimeout(function(){
                            pub.up.incoming(msg, targetOrigin);
                        }, 0);
                    }
                });
                
                send = function(msg){
                    proxy.SendToParent(msg, config.secret);
                };
                setTimeout(function(){
                    pub.up.callback(true);
                }, 0);
            }
        },
        init: function(){
            whenReady(pub.onDOMReady, pub);
        }
    });
};
/*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
/*global easyXDM, window, escape, unescape, undef, getLocation, appendQueryParameters, resolveUrl, createFrame, debug, un, apply, whenReady, IFRAME_PREFIX*/
//
// easyXDM
// http://easyxdm.net/
// Copyright(c) 2009, Øyvind Sean Kinsey, oyvind@kinsey.no.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

/**
 * @class easyXDM.stack.NameTransport
 * NameTransport uses the window.name property to relay data.
 * The <code>local</code> parameter needs to be set on both the consumer and provider,<br/>
 * and the <code>remoteHelper</code> parameter needs to be set on the consumer.
 * @constructor
 * @param {Object} config The transports configuration.
 * @cfg {String} remoteHelper The url to the remote instance of hash.html - this is only needed for the host.
 * @namespace easyXDM.stack
 */
easyXDM.stack.NameTransport = function(config){
    
    var pub; // the public interface
    var isHost, callerWindow, remoteWindow, readyCount, callback, remoteOrigin, remoteUrl;
    
    function _sendMessage(message){
        var url = config.remoteHelper + (isHost ? "#_3" : "#_2") + config.channel;
        callerWindow.contentWindow.sendMessage(message, url);
    }
    
    function _onReady(){
        if (isHost) {
            if (++readyCount === 2 || !isHost) {
                pub.up.callback(true);
            }
        }
        else {
            _sendMessage("ready");
            pub.up.callback(true);
        }
    }
    
    function _onMessage(message){
        pub.up.incoming(message, remoteOrigin);
    }
    
    function _onLoad(){
        if (callback) {
            setTimeout(function(){
                callback(true);
            }, 0);
        }
    }
    
    return (pub = {
        outgoing: function(message, domain, fn){
            callback = fn;
            _sendMessage(message);
        },
        destroy: function(){
            callerWindow.parentNode.removeChild(callerWindow);
            callerWindow = null;
            if (isHost) {
                remoteWindow.parentNode.removeChild(remoteWindow);
                remoteWindow = null;
            }
        },
        onDOMReady: function(){
            isHost = config.isHost;
            readyCount = 0;
            remoteOrigin = getLocation(config.remote);
            config.local = resolveUrl(config.local);
            
            if (isHost) {
                // Register the callback
                easyXDM.Fn.set(config.channel, function(message){
                    if (isHost && message === "ready") {
                        // Replace the handler
                        easyXDM.Fn.set(config.channel, _onMessage);
                        _onReady();
                    }
                });
                
                // Set up the frame that points to the remote instance
                remoteUrl = appendQueryParameters(config.remote, {
                    xdm_e: config.local,
                    xdm_c: config.channel,
                    xdm_p: 2
                });
                apply(config.props, {
                    src: remoteUrl + '#' + config.channel,
                    name: IFRAME_PREFIX + config.channel + "_provider"
                });
                remoteWindow = createFrame(config);
            }
            else {
                config.remoteHelper = config.remote;
                easyXDM.Fn.set(config.channel, _onMessage);
            }
            // Set up the iframe that will be used for the transport
            
            callerWindow = createFrame({
                props: {
                    src: config.local + "#_4" + config.channel
                },
                onLoad: function onLoad(){
                    // Remove the handler
                    un(callerWindow, "load", onLoad);
                    easyXDM.Fn.set(config.channel + "_load", _onLoad);
                    (function test(){
                        if (typeof callerWindow.contentWindow.sendMessage == "function") {
                            _onReady();
                        }
                        else {
                            setTimeout(test, 50);
                        }
                    }());
                }
            });
        },
        init: function(){
            whenReady(pub.onDOMReady, pub);
        }
    });
};
/*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
/*global easyXDM, window, escape, unescape, getLocation, createFrame, debug, un, on, apply, whenReady, IFRAME_PREFIX*/
//
// easyXDM
// http://easyxdm.net/
// Copyright(c) 2009, Øyvind Sean Kinsey, oyvind@kinsey.no.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

/**
 * @class easyXDM.stack.HashTransport
 * HashTransport is a transport class that uses the IFrame URL Technique for communication.<br/>
 * <a href="http://msdn.microsoft.com/en-us/library/bb735305.aspx">http://msdn.microsoft.com/en-us/library/bb735305.aspx</a><br/>
 * @namespace easyXDM.stack
 * @constructor
 * @param {Object} config The transports configuration.
 * @cfg {String/Window} local The url to the local file used for proxying messages, or the local window.
 * @cfg {Number} delay The number of milliseconds easyXDM should try to get a reference to the local window.
 * @cfg {Number} interval The interval used when polling for messages.
 */
easyXDM.stack.HashTransport = function(config){
    var pub;
    var me = this, isHost, _timer, pollInterval, _lastMsg, _msgNr, _listenerWindow, _callerWindow;
    var useParent, _remoteOrigin;
    
    function _sendMessage(message){
        if (!_callerWindow) {
            return;
        }
        var url = config.remote + "#" + (_msgNr++) + "_" + message;
        ((isHost || !useParent) ? _callerWindow.contentWindow : _callerWindow).location = url;
    }
    
    function _handleHash(hash){
        _lastMsg = hash;
        pub.up.incoming(_lastMsg.substring(_lastMsg.indexOf("_") + 1), _remoteOrigin);
    }
    
    /**
     * Checks location.hash for a new message and relays this to the receiver.
     * @private
     */
    function _pollHash(){
        if (!_listenerWindow) {
            return;
        }
        var href = _listenerWindow.location.href, hash = "", indexOf = href.indexOf("#");
        if (indexOf != -1) {
            hash = href.substring(indexOf);
        }
        if (hash && hash != _lastMsg) {
            _handleHash(hash);
        }
    }
    
    function _attachListeners(){
        _timer = setInterval(_pollHash, pollInterval);
    }
    
    return (pub = {
        outgoing: function(message, domain){
            _sendMessage(message);
        },
        destroy: function(){
            window.clearInterval(_timer);
            if (isHost || !useParent) {
                _callerWindow.parentNode.removeChild(_callerWindow);
            }
            _callerWindow = null;
        },
        onDOMReady: function(){
            isHost = config.isHost;
            pollInterval = config.interval;
            _lastMsg = "#" + config.channel;
            _msgNr = 0;
            useParent = config.useParent;
            _remoteOrigin = getLocation(config.remote);
            if (isHost) {
                config.props = {
                    src: config.remote,
                    name: IFRAME_PREFIX + config.channel + "_provider"
                };
                if (useParent) {
                    config.onLoad = function(){
                        _listenerWindow = window;
                        _attachListeners();
                        pub.up.callback(true);
                    };
                }
                else {
                    var tries = 0, max = config.delay / 50;
                    (function getRef(){
                        if (++tries > max) {
                            throw new Error("Unable to reference listenerwindow");
                        }
                        try {
                            _listenerWindow = _callerWindow.contentWindow.frames[IFRAME_PREFIX + config.channel + "_consumer"];
                        } 
                        catch (ex) {
                        }
                        if (_listenerWindow) {
                            _attachListeners();
                            pub.up.callback(true);
                        }
                        else {
                            setTimeout(getRef, 50);
                        }
                    }());
                }
                _callerWindow = createFrame(config);
            }
            else {
                _listenerWindow = window;
                _attachListeners();
                if (useParent) {
                    _callerWindow = parent;
                    pub.up.callback(true);
                }
                else {
                    apply(config, {
                        props: {
                            src: config.remote + "#" + config.channel + new Date(),
                            name: IFRAME_PREFIX + config.channel + "_consumer"
                        },
                        onLoad: function(){
                            pub.up.callback(true);
                        }
                    });
                    _callerWindow = createFrame(config);
                }
            }
        },
        init: function(){
            whenReady(pub.onDOMReady, pub);
        }
    });
};
/*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
/*global easyXDM, window, escape, unescape, debug */
//
// easyXDM
// http://easyxdm.net/
// Copyright(c) 2009, Øyvind Sean Kinsey, oyvind@kinsey.no.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

/**
 * @class easyXDM.stack.ReliableBehavior
 * This is a behavior that tries to make the underlying transport reliable by using acknowledgements.
 * @namespace easyXDM.stack
 * @constructor
 * @param {Object} config The behaviors configuration.
 */
easyXDM.stack.ReliableBehavior = function(config){
    var pub, // the public interface
 callback; // the callback to execute when we have a confirmed success/failure
    var idOut = 0, idIn = 0, currentMessage = "";
    
    return (pub = {
        incoming: function(message, origin){
            var indexOf = message.indexOf("_"), ack = message.substring(0, indexOf).split(",");
            message = message.substring(indexOf + 1);
            
            if (ack[0] == idOut) {
                currentMessage = "";
                if (callback) {
                    callback(true);
                }
            }
            if (message.length > 0) {
                pub.down.outgoing(ack[1] + "," + idOut + "_" + currentMessage, origin);
                if (idIn != ack[1]) {
                    idIn = ack[1];
                    pub.up.incoming(message, origin);
                }
            }
            
        },
        outgoing: function(message, origin, fn){
            currentMessage = message;
            callback = fn;
            pub.down.outgoing(idIn + "," + (++idOut) + "_" + message, origin);
        }
    });
};
/*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
/*global easyXDM, window, escape, unescape, debug, undef, removeFromStack*/
//
// easyXDM
// http://easyxdm.net/
// Copyright(c) 2009, Øyvind Sean Kinsey, oyvind@kinsey.no.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

/**
 * @class easyXDM.stack.QueueBehavior
 * This is a behavior that enables queueing of messages. <br/>
 * It will buffer incoming messages and dispach these as fast as the underlying transport allows.
 * This will also fragment/defragment messages so that the outgoing message is never bigger than the
 * set length.
 * @namespace easyXDM.stack
 * @constructor
 * @param {Object} config The behaviors configuration. Optional.
 * @cfg {Number} maxLength The maximum length of each outgoing message. Set this to enable fragmentation.
 */
easyXDM.stack.QueueBehavior = function(config){
    var pub, queue = [], waiting = true, incoming = "", destroying, maxLength = 0, lazy = false, doFragment = false;
    
    function dispatch(){
        if (config.remove && queue.length === 0) {
            removeFromStack(pub);
            return;
        }
        if (waiting || queue.length === 0 || destroying) {
            return;
        }
        waiting = true;
        var message = queue.shift();
        
        pub.down.outgoing(message.data, message.origin, function(success){
            waiting = false;
            if (message.callback) {
                setTimeout(function(){
                    message.callback(success);
                }, 0);
            }
            dispatch();
        });
    }
    return (pub = {
        init: function(){
            if (undef(config)) {
                config = {};
            }
            if (config.maxLength) {
                maxLength = config.maxLength;
                doFragment = true;
            }
            if (config.lazy) {
                lazy = true;
            }
            else {
                pub.down.init();
            }
        },
        callback: function(success){
            waiting = false;
            var up = pub.up; // in case dispatch calls removeFromStack
            dispatch();
            up.callback(success);
        },
        incoming: function(message, origin){
            if (doFragment) {
                var indexOf = message.indexOf("_"), seq = parseInt(message.substring(0, indexOf), 10);
                incoming += message.substring(indexOf + 1);
                if (seq === 0) {
                    if (config.encode) {
                        incoming = decodeURIComponent(incoming);
                    }
                    pub.up.incoming(incoming, origin);
                    incoming = "";
                }
            }
            else {
                pub.up.incoming(message, origin);
            }
        },
        outgoing: function(message, origin, fn){
            if (config.encode) {
                message = encodeURIComponent(message);
            }
            var fragments = [], fragment;
            if (doFragment) {
                // fragment into chunks
                while (message.length !== 0) {
                    fragment = message.substring(0, maxLength);
                    message = message.substring(fragment.length);
                    fragments.push(fragment);
                }
                // enqueue the chunks
                while ((fragment = fragments.shift())) {
                    queue.push({
                        data: fragments.length + "_" + fragment,
                        origin: origin,
                        callback: fragments.length === 0 ? fn : null
                    });
                }
            }
            else {
                queue.push({
                    data: message,
                    origin: origin,
                    callback: fn
                });
            }
            if (lazy) {
                pub.down.init();
            }
            else {
                dispatch();
            }
        },
        destroy: function(){
            destroying = true;
            pub.down.destroy();
        }
    });
};
/*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
/*global easyXDM, window, escape, unescape, undef, debug */
//
// easyXDM
// http://easyxdm.net/
// Copyright(c) 2009, Øyvind Sean Kinsey, oyvind@kinsey.no.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

/**
 * @class easyXDM.stack.VerifyBehavior
 * This behavior will verify that communication with the remote end is possible, and will also sign all outgoing,
 * and verify all incoming messages. This removes the risk of someone hijacking the iframe to send malicious messages.
 * @namespace easyXDM.stack
 * @constructor
 * @param {Object} config The behaviors configuration.
 * @cfg {Boolean} initiate If the verification should be initiated from this end.
 */
easyXDM.stack.VerifyBehavior = function(config){
    var pub, mySecret, theirSecret, verified = false;
    
    function startVerification(){
        mySecret = Math.random().toString(16).substring(2);
        pub.down.outgoing(mySecret);
    }
    
    return (pub = {
        incoming: function(message, origin){
            var indexOf = message.indexOf("_");
            if (indexOf === -1) {
                if (message === mySecret) {
                    pub.up.callback(true);
                }
                else if (!theirSecret) {
                    theirSecret = message;
                    if (!config.initiate) {
                        startVerification();
                    }
                    pub.down.outgoing(message);
                }
            }
            else {
                if (message.substring(0, indexOf) === theirSecret) {
                    pub.up.incoming(message.substring(indexOf + 1), origin);
                }
            }
        },
        outgoing: function(message, origin, fn){
            pub.down.outgoing(mySecret + "_" + message, origin, fn);
        },
        callback: function(success){
            if (config.initiate) {
                startVerification();
            }
        }
    });
};
/*jslint evil: true, browser: true, immed: true, passfail: true, undef: true, newcap: true*/
/*global easyXDM, window, escape, unescape, undef, getJSON, debug, emptyFn, isArray */
//
// easyXDM
// http://easyxdm.net/
// Copyright(c) 2009, Øyvind Sean Kinsey, oyvind@kinsey.no.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

/**
 * @class easyXDM.stack.RpcBehavior
 * This uses JSON-RPC 2.0 to expose local methods and to invoke remote methods and have responses returned over the the string based transport stack.<br/>
 * Exposed methods can return values synchronous, asyncronous, or bet set up to not return anything.
 * @namespace easyXDM.stack
 * @constructor
 * @param {Object} proxy The object to apply the methods to.
 * @param {Object} config The definition of the local and remote interface to implement.
 * @cfg {Object} local The local interface to expose.
 * @cfg {Object} remote The remote methods to expose through the proxy.
 * @cfg {Object} serializer The serializer to use for serializing and deserializing the JSON. Should be compatible with the HTML5 JSON object. Optional, will default to JSON.
 */
easyXDM.stack.RpcBehavior = function(proxy, config){
    var pub, serializer = config.serializer || getJSON();
    var _callbackCounter = 0, _callbacks = {};
    
    /**
     * Serializes and sends the message
     * @private
     * @param {Object} data The JSON-RPC message to be sent. The jsonrpc property will be added.
     */
    function _send(data){
        data.jsonrpc = "2.0";
        pub.down.outgoing(serializer.stringify(data));
    }
    
    /**
     * Creates a method that implements the given definition
     * @private
     * @param {Object} The method configuration
     * @param {String} method The name of the method
     * @return {Function} A stub capable of proxying the requested method call
     */
    function _createMethod(definition, method){
        var slice = Array.prototype.slice;
        
        return function(){
            var l = arguments.length, callback, message = {
                method: method
            };
            
            if (l > 0 && typeof arguments[l - 1] === "function") {
                //with callback, procedure
                if (l > 1 && typeof arguments[l - 2] === "function") {
                    // two callbacks, success and error
                    callback = {
                        success: arguments[l - 2],
                        error: arguments[l - 1]
                    };
                    message.params = slice.call(arguments, 0, l - 2);
                }
                else {
                    // single callback, success
                    callback = {
                        success: arguments[l - 1]
                    };
                    message.params = slice.call(arguments, 0, l - 1);
                }
                _callbacks["" + (++_callbackCounter)] = callback;
                message.id = _callbackCounter;
            }
            else {
                // no callbacks, a notification
                message.params = slice.call(arguments, 0);
            }
            if (definition.namedParams && message.params.length === 1) {
                message.params = message.params[0];
            }
            // Send the method request
            _send(message);
        };
    }
    
    /**
     * Executes the exposed method
     * @private
     * @param {String} method The name of the method
     * @param {Number} id The callback id to use
     * @param {Function} method The exposed implementation
     * @param {Array} params The parameters supplied by the remote end
     */
    function _executeMethod(method, id, fn, params){
        if (!fn) {
            if (id) {
                _send({
                    id: id,
                    error: {
                        code: -32601,
                        message: "Procedure not found."
                    }
                });
            }
            return;
        }
        
        var success, error;
        if (id) {
            success = function(result){
                success = emptyFn;
                _send({
                    id: id,
                    result: result
                });
            };
            error = function(message, data){
                error = emptyFn;
                var msg = {
                    id: id,
                    error: {
                        code: -32099,
                        message: message
                    }
                };
                if (data) {
                    msg.error.data = data;
                }
                _send(msg);
            };
        }
        else {
            success = error = emptyFn;
        }
        // Call local method
        if (!isArray(params)) {
            params = [params];
        }
        try {
            var result = fn.method.apply(fn.scope, params.concat([success, error]));
            if (!undef(result)) {
                success(result);
            }
        } 
        catch (ex1) {
            error(ex1.message);
        }
    }
    
    return (pub = {
        incoming: function(message, origin){
            var data = serializer.parse(message);
            if (data.method) {
                // A method call from the remote end
                if (config.handle) {
                    config.handle(data, _send);
                }
                else {
                    _executeMethod(data.method, data.id, config.local[data.method], data.params);
                }
            }
            else {
                // A method response from the other end
                var callback = _callbacks[data.id];
                if (data.error) {
                    if (callback.error) {
                        callback.error(data.error);
                    }
                }
                else if (callback.success) {
                    callback.success(data.result);
                }
                delete _callbacks[data.id];
            }
        },
        init: function(){
            if (config.remote) {
                // Implement the remote sides exposed methods
                for (var method in config.remote) {
                    if (config.remote.hasOwnProperty(method)) {
                        proxy[method] = _createMethod(config.remote[method], method);
                    }
                }
            }
            pub.down.init();
        },
        destroy: function(){
            for (var method in config.remote) {
                if (config.remote.hasOwnProperty(method) && proxy.hasOwnProperty(method)) {
                    delete proxy[method];
                }
            }
            pub.down.destroy();
        }
    });
};
global.easyXDM = easyXDM;
})(window, document, location, window.setTimeout, decodeURIComponent, encodeURIComponent);
;
(function ($, Carnival) {

    if (!Carnival) Carnival = {};

    if (!Carnival.Widgets) Carnival.Widgets = {};

    if (!Carnival.Widgets.AdTile) Carnival.Widgets.AdTile = {};
    if (!Carnival.Widgets.Extensions) Carnival.Widgets.Extensions = {};

    var cclTiles = {};

    cclTiles.touch = Modernizr.touch; 

    cclTiles.initTouts = function () {
        var $pars = $(".ccl-tout-wrap"),
            $touts = $pars.find(".ccl-tout:not(.activated,>.ccl-tout-image)").addClass("activated"),
            $mobileTouts = $pars.find(".ccl-ad-tile").addClass("activated");

        $mobileTouts.each(function() {
            var $this = $(this);

            var title = $this.find('.ccl-ad-tile-banner__desc > span').text().trim();
            var buttonText = $this.find('.ccl-button-link').text().trim();
            var linkTextWithTitle = title.concat(' ', buttonText);

            var div = document.createElement("div");
            div.innerHTML = linkTextWithTitle;
            linkTextWithTitle = div.textContent || div.innerText || "";

            $this.find("a").attr('aria-label', linkTextWithTitle);
        });

        $touts.each(function() {
            var $this = $(this),
                o = $this.find(".ccl-tout-front"),
                disableFlipSide = false,
                img = o.find("img").attr("src");

            if(img)
               o.css("background-image", "url('" + img + "')");

            if (!img && $(o).attr('data-bgcolor')) {
                o.css("background-color", o.attr('data-bgcolor'));
            }
            
            if ($this.attr('data-disable-flipside')) {
                disableFlipSide = $this.attr('data-disable-flipside');
                if (disableFlipSide == 'True') {
                    $this.css("cursor", "pointer");
                    var clickthroughurl = $(o).attr('data-clickthroughurl');
                    if (clickthroughurl) {
                        $(o).click(function () {
                            window.location.href = clickthroughurl;
                        });
                    }
                    return true;
                }
            }

           
            var back = $this.find(".ccl-tout-back"),
                overlay = back.find('.overlay'),
                backimg = back.find("img"),
                bttn2 = back.find('.overlay .cta');

            if (backimg && backimg.length > 0) {
                var src = backimg.attr('src');
                if (src) {
                    back.css("background-image", "url('" + src + "')");
                }
            } else if (overlay) {
                /* This if checks that we this logis is ommited for the
                 * https://dev.carnival.com/cruise-deals page because the
                 * the inline styling here was an issue for the mobile
                 * theme after the unmobification
                 */
                if (back.closest('#ccl-specials').length == 0) {
                    back.css("background-color", overlay.attr('data-bgcolor'));
                }
            }
            if (bttn2) {
                bttn2.hover(function() {
                        $(this).css("background-color", bttn2.attr('data-hoverColor'));
                    },
                    function() {
                        $(this).css("background-color", bttn2.attr('data-bgcolor'));
                    });
            }

            var $link = back.find('> a.overlay');
            if ($link.data('ada-applied') == undefined && $link.data('ada-applied') !== 'true') {
                var titleDescription = o.find('div.overlay > h2').text();
                var learnText = o && o.find(".learn-more-text").length ? o.find(".learn-more-text").html() : '';
                var linkText = $link.attr('aria-label');
                var $overlayText = $link.find('.overlay-text');
                if ($overlayText.length > 0) {
                    var div = document.createElement("div");
                    div.innerHTML = linkText;
                    linkText = div.textContent || div.innerText || "";
                }
                var linkTextWithTitle = learnText.concat(' ', titleDescription.concat(' ', linkText));
                $link.attr('aria-label', linkTextWithTitle);
                o.find("a").attr('aria-label', linkTextWithTitle);
                $link.data('ada-applied', 'true');
            }

            $this.data("mouseenter", function(_this) {
                $this.addClass("flipped");
            }).data("mouseleave", function(_this) {
                $this.removeClass("flipped");
            }).bind("mouseenter", function() {
                $this.data("mouseenter")(this);
            }).bind("mouseleave", function() {
                $this.data("mouseleave")(this);
            });
        

        });

        if (cclTiles.touch) {
            $pars.unbind("mouseenter mouseleave").on("click", function () {
                var thisTout = $(this).find(".ccl-tout");

                $pars.find(".flipped").not(thisTout).removeClass("flipped");
                thisTout.toggleClass("flipped");
            });

            $touts.find("a").on("click", function (e) { e.stopPropagation(); });
        }
        ///count down clock initialization
        cclTiles.initCountdownClockForAdtile();
    };

    cclTiles.initCountdownClockForAdtile = function () {
        //if courtesy hold expiration exist from cookie start the countdown
        if ($(".col-1-3 .countdown-clock") && $(".col-1-3 .countdown-clock").length > 0) {
            var estOffSet = 5 * 60 * 60 * 1000; //time in ms //Eastern standard time zone offset
            /*Adtile expiration date and time is always in EST time. 
            Here we are converting both EST and local time to UTC in order to calculate accurate remaing time.*/
            $(".col-1-3 .countdown-clock").each(function () {
                var $clock = $(this);
                var expDate = $clock.find('.expirationDate').val();
                if (!expDate) return true;

                var split = expDate.split('T');
                var expires = Date.UTC(parseInt(split[0].split('-')[0]), parseInt(split[0].split('-')[1]) - 1, parseInt(split[0].split('-')[2]), parseInt(split[1].split(':')[0]), parseInt(split[1].split(':')[1]), parseInt(split[1].split(':')[2]));//month starts from 0
                expires = expires - estOffSet;
                var timespaninseconds = cclTiles.getUTCTimeUntilExpiration(expires); //Remaining time span in seconds  

                var cdSectionBgcolor = $clock.attr('data-clockbgcolor');
                var cdTimeleftFontColor = $clock.attr('data-timeleft-fontcolor');
                var cdTxtFontColor = $clock.attr('data-text-fontcolor');
                var time = timespaninseconds,

                layout = '<span class="countdown-row countdown-show4"><span style="background-color:' + cdSectionBgcolor + '"' + ' class="countdown-section"><span style="color:' + cdTimeleftFontColor + '"' + ' class="countdown-amount">{hnn}</span><span style="color:' + cdTxtFontColor + '"' + ' class="countdown-period">' + Carnival.AppResources.Core.GetResourceString("ccl-homepage-init.js", 'CountdownClockHrsTxt') + '</span></span><span class="points">:</span> \
						    <span style="background-color:' + cdSectionBgcolor + '"' + ' class="countdown-section"><span style="color:' + cdTimeleftFontColor + '"' + ' class="countdown-amount">{mnn}</span><span style="color:' + cdTxtFontColor + '"' + ' class="countdown-period">' + Carnival.AppResources.Core.GetResourceString("ccl-homepage-init.js", 'CountdownClockMinsTxt') + '</span></span><span class="points">:</span> \
						    <span style="background-color:' + cdSectionBgcolor + '"' + ' class="countdown-section"><span style="color:' + cdTimeleftFontColor + '"' + ' class="countdown-amount">{snn}</span><span style="color:' + cdTxtFontColor + '"' + ' class="countdown-period">' + Carnival.AppResources.Core.GetResourceString("ccl-homepage-init.js", 'CountdownClockSecsTxt') + '</span></span></span>';
                $clock.find(".clock").countdown({
                    until: time,
                    layout: layout,
                    format: "HMS"
                });

            });
        }
    };
    cclTiles.getUTCTimeUntilExpiration = function (expires) {
        var now = new Date(); //Local time
        var nowutcinms = now.valueOf() - (now.getTimezoneOffset() * 60000); //Number of ms since 1970 Utc

        ////////////////////////////////////////////////////////////////////////
        // Correct offset difference between timezones            
        var currentTimezoneOffset = cclTiles.getCurrentTimezoneOffset();
        var diff = (currentTimezoneOffset - now.getTimezoneOffset()) * 60000;
        expires += diff;
        ////////////////////////////////////////////////////////////////////////

        var timespaninseconds = ((expires - nowutcinms) / 1000) | 0; //Remaining time span in seconds   

        return timespaninseconds;
    };
    cclTiles.getCurrentTimezoneOffset = function () {
        var currDate = new Date();
        var dstStartDateInUTC = Carnival.AppResources.Core.GetResourceString("ccl-homepage-init.js", 'DSTStartDateInUTC'),
            dstEndDateInUTC = Carnival.AppResources.Core.GetResourceString("ccl-homepage-init.js", 'DSTEndDateInUTC'),
            startDateSplit = dstStartDateInUTC.split('.'),
            endDateSplit = dstEndDateInUTC.split('.'),
            startDateInUTC = Date.UTC(parseInt(startDateSplit[0]), parseInt(startDateSplit[1]) - 1, parseInt(startDateSplit[2]), parseInt(startDateSplit[3]), parseInt(startDateSplit[4]), parseInt(startDateSplit[5])),
            endDateInUTC = Date.UTC(parseInt(endDateSplit[0]), parseInt(endDateSplit[1]) - 1, parseInt(endDateSplit[2]), parseInt(endDateSplit[3]), parseInt(endDateSplit[4]), parseInt(endDateSplit[5])),
            now = currDate.getTime(),
            currentTimezoneOffset = 240;

        if (!isNaN(startDateInUTC) && !isNaN(endDateInUTC)) {
            var isDaylightSavingsTime = now >= startDateInUTC && now < endDateInUTC;
            if (isDaylightSavingsTime) {
                currentTimezoneOffset = parseInt(Carnival.AppResources.Core.GetResourceString("ccl-homepage-init.js", 'DSTTimezoneOffset'));
            }
            else {
                currentTimezoneOffset = parseInt(Carnival.AppResources.Core.GetResourceString("ccl-homepage-init.js", 'StdTimezoneOffset'));
            }
        }
        return currentTimezoneOffset;
    };

    Carnival.Widgets.AdTile = $.extend(cclTiles, Carnival.Widgets.AdTile);

    window.Carnival = Carnival;

    $(function () {

        if (!Carnival.Personalizer) {
            cclTiles.initTouts();
        }
        
    });

})(jQuery, window.Carnival);
$(document).trigger("CCL-Widgets.AdTile-loaded");;
