/* Modernizr 2.5.3 (Custom Build) | MIT & BSD
* Build: http://www.modernizr.com/download/#-csstransforms-csstransforms3d-shiv-cssclasses-teststyles-testprop-testallprops-prefixes-domprefixes-load
*/
;window.Modernizr=function(a,b,c){function z(a){j.cssText=a}function A(a,b){return z(m.join(a+";")+(b||""))}function B(a,b){return typeof a===b}function C(a,b){return!!~(""+a).indexOf(b)}function D(a,b){for(var d in a)if(j[a[d]]!==c)return b=="pfx"?a[d]:!0;return!1}function E(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:B(f,"function")?f.bind(d||b):f}return!1}function F(a,b,c){var d=a.charAt(0).toUpperCase()+a.substr(1),e=(a+" "+o.join(d+" ")+d).split(" ");return B(b,"string")||B(b,"undefined")?D(e,b):(e=(a+" "+p.join(d+" ")+d).split(" "),E(e,b,c))}var d="2.5.3",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k,l={}.toString,m=" -webkit- -moz- -o- -ms- ".split(" "),n="Webkit Moz O ms",o=n.split(" "),p=n.toLowerCase().split(" "),q={},r={},s={},t=[],u=t.slice,v,w=function(a,c,d,e){var f,i,j,k=b.createElement("div"),l=b.body,m=l?l:b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),k.appendChild(j);return f=["",""].join(""),k.id=h,(l?k:m).innerHTML+=f,m.appendChild(k),l||(m.style.background="",g.appendChild(m)),i=c(k,a),l?k.parentNode.removeChild(k):m.parentNode.removeChild(m),!!i},x={}.hasOwnProperty,y;!B(x,"undefined")&&!B(x.call,"undefined")?y=function(a,b){return x.call(a,b)}:y=function(a,b){return b in a&&B(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=u.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(u.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(u.call(arguments)))};return e});var G=function(a,c){var d=a.join(""),f=c.length;w(d,function(a,c){var d=b.styleSheets[b.styleSheets.length-1],g=d?d.cssRules&&d.cssRules[0]?d.cssRules[0].cssText:d.cssText||"":"",h=a.childNodes,i={};while(f--)i[h[f].id]=h[f];e.csstransforms3d=(i.csstransforms3d&&i.csstransforms3d.offsetLeft)===9&&i.csstransforms3d.offsetHeight===3},f,c)}([,["@media (",m.join("transform-3d),("),h,")","{#csstransforms3d{left:9px;position:absolute;height:3px;}}"].join("")],[,"csstransforms3d"]);q.csstransforms=function(){return!!F("transform")},q.csstransforms3d=function(){var a=!!F("perspective");return a&&"webkitPerspective"in g.style&&(a=e.csstransforms3d),a};for(var H in q)y(q,H)&&(v=H.toLowerCase(),e[v]=q[H](),t.push((e[v]?"":"no-")+v));return z(""),i=k=null,function(a,b){function g(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function h(){var a=k.elements;return typeof a=="string"?a.split(" "):a}function i(a){var b={},c=a.createElement,e=a.createDocumentFragment,f=e();a.createElement=function(a){var e=(b[a]||(b[a]=c(a))).cloneNode();return k.shivMethods&&e.canHaveChildren&&!d.test(a)?f.appendChild(e):e},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+h().join().replace(/\w+/g,function(a){return b[a]=c(a),f.createElement(a),'c("'+a+'")'})+");return n}")(k,f)}function j(a){var b;return a.documentShived?a:(k.shivCSS&&!e&&(b=!!g(a,"article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio{display:none}canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden]{display:none}audio[controls]{display:inline-block;*display:inline;*zoom:1}mark{background:#FF0;color:#000}")),f||(b=!i(a)),b&&(a.documentShived=b),a)}var c=a.html5||{},d=/^<|^(?:button|form|map|select|textarea)$/i,e,f;(function(){var a=b.createElement("a");a.innerHTML="",e="hidden"in a,f=a.childNodes.length==1||function(){try{b.createElement("a")}catch(a){return!0}var c=b.createDocumentFragment();return typeof c.cloneNode=="undefined"||typeof c.createDocumentFragment=="undefined"||typeof c.createElement=="undefined"}()})();var k={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:j};a.html5=k,j(b)}(this,b),e._version=d,e._prefixes=m,e._domPrefixes=p,e._cssomPrefixes=o,e.testProp=function(a){return D([a])},e.testAllProps=F,e.testStyles=w,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+t.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return o.call(a)=="[object Function]"}function e(a){return typeof a=="string"}function f(){}function g(a){return!a||a=="loaded"||a=="complete"||a=="uninitialized"}function h(){var a=p.shift();q=1,a?a.t?m(function(){(a.t=="c"?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){a!="img"&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l={},o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};y[c]===1&&(r=1,y[c]=[],l=b.createElement(a)),a=="object"?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),a!="img"&&(r||y[c]===2?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i(b=="c"?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),p.length==1&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&o.call(a.opera)=="[object Opera]",l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return o.call(a)=="[object Array]"},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;fopera.version()?
new Audio(null):new Audio).canPlayType!==g}catch(xb){Wa=!1}this.hasHTML5=Wa;this.setup=function(b){var d=!c.url;b!==g&&q&&u&&c.ok()&&(b.flashVersion!==g||b.url!==g||b.html5Test!==g)&&K(t("setupLate"));Aa(b);if(!B)if(va){if(!c.setupOptions.ignoreMobileRestrictions||c.setupOptions.forceUseGlobalHTML5Audio)L.push(z.globalHTML5),B=!0}else c.setupOptions.forceUseGlobalHTML5Audio&&(L.push(z.globalHTML5),B=!0);if(!Pa&&va)if(c.setupOptions.ignoreMobileRestrictions)L.push(z.ignoreMobile);else if(c.setupOptions.useHTML5Audio&&
!c.setupOptions.preferFlash||c._wD(z.mobileUA),c.setupOptions.useHTML5Audio=!0,c.setupOptions.preferFlash=!1,Qa)c.ignoreFlash=!0;else if(Ra&&!v.match(/android\s2\.3/i)||!Ra)c._wD(z.globalHTML5),B=!0;b&&(d&&Z&&b.url!==g&&c.beginDelayedInit(),Z||b.url===g||"complete"!==m.readyState||setTimeout(P,1));Pa=!0;return c};this.supported=this.ok=function(){return u?q&&!y:c.useHTML5Audio&&c.hasHTML5};this.getMovie=function(c){return E(c)||m[c]||h[c]};this.createSound=function(b,d){function e(){f=oa(f);c.sounds[f.id]=
new V(f);c.soundIDs.push(f.id);return c.sounds[f.id]}var a,f;a=null;a="soundManager.createSound(): "+t(q?"notOK":"notReady");if(!q||!c.ok())return K(a),!1;d!==g&&(b={id:b,url:d});f=A(b);f.url=ra(f.url);f.id===g&&(f.id=c.setupOptions.idPrefix+nb++);f.id.toString().charAt(0).match(/^[0-9]$/)&&c._wD("soundManager.createSound(): "+t("badID",f.id),2);c._wD("soundManager.createSound(): "+f.id+(f.url?" ("+f.url+")":""),1);if(w(f.id,!0))return c._wD("soundManager.createSound(): "+f.id+" exists",1),c.sounds[f.id];
if(sa(f))a=e(),c.html5Only||c._wD(f.id+": Using HTML5"),a._setup_html5(f);else{if(c.html5Only)return c._wD(f.id+": No HTML5 support for this sound, and no Flash. Exiting."),e();if(c.html5.usingFlash&&f.url&&f.url.match(/data:/i))return c._wD(f.id+": data: URIs not supported via Flash. Exiting."),e();8a.instanceCount?(m(),e=a._setup_html5(),a.setPosition(a._iO.position),e.play()):(c._wD(a.id+": Cloning Audio() for instance #"+a.instanceCount+"..."),k=new Audio(a._iO.url),F=function(){x.remove(k,"ended",F);a._onfinish(a);ta(k);k=null},h=function(){x.remove(k,"canplay",h);try{k.currentTime=a._iO.position/
1E3}catch(c){K(a.id+": multiShot play() failed to apply position of "+a._iO.position/1E3)}k.play()},x.add(k,"ended",F),a._iO.volume!==g&&(k.volume=Math.max(0,Math.min(1,a._iO.volume/100))),a.muted&&(k.muted=!0),a._iO.position?x.add(k,"canplay",h):k.play()):(f=l._start(a.id,a._iO.loops||1,9===n?a.position:a.position/1E3,a._iO.multiShot||!1),9!==n||f||(c._wD(e+"No sound hardware, or 32-sound ceiling hit",2),a._iO.onplayerror&&a._iO.onplayerror.apply(a))));return a};this.stop=function(b){var d=a._iO;
1===a.playState&&(c._wD(a.id+": stop()"),a._onbufferchange(0),a._resetOnPosition(0),a.paused=!1,a.isHTML5||(a.playState=0),Xa(),d.to&&a.clearOnPosition(d.to),a.isHTML5?a._a&&(b=a.position,a.setPosition(0),a.position=b,a._a.pause(),a.playState=0,a._onTimer(),F()):(l._stop(a.id,b),d.serverURL&&a.unload()),a.instanceCount=0,a._iO={},d.onstop&&d.onstop.apply(a));return a};this.setAutoPlay=function(b){c._wD(a.id+": Autoplay turned "+(b?"on":"off"));a._iO.autoPlay=b;a.isHTML5||(l._setAutoPlay(a.id,b),b&&
!a.instanceCount&&1===a.readyState&&(a.instanceCount++,c._wD(a.id+": Incremented instance count to "+a.instanceCount)))};this.getAutoPlay=function(){return a._iO.autoPlay};this.setPlaybackRate=function(b){var d=Math.max(.5,Math.min(4,b));d!==b&&c._wD(a.id+": setPlaybackRate("+b+"): limiting rate to "+d,2);if(a.isHTML5)try{a._iO.playbackRate=d,a._a.playbackRate=d}catch(e){c._wD(a.id+": setPlaybackRate("+d+") failed: "+e.message,2)}return a};this.setPosition=function(b){b===g&&(b=0);var d=a.isHTML5?
Math.max(b,0):Math.min(a.duration||a._iO.duration,Math.max(b,0));a.position=d;b=a.position/1E3;a._resetOnPosition(a.position);a._iO.position=d;if(!a.isHTML5)b=9===n?a.position:b,a.readyState&&2!==a.readyState&&l._setPosition(a.id,b,a.paused||!a.playState,a._iO.multiShot);else if(a._a){if(a._html5_canplay){if(a._a.currentTime.toFixed(3)!==b.toFixed(3)){c._wD(a.id+": setPosition("+b+")");try{a._a.currentTime=b,(0===a.playState||a.paused)&&a._a.pause()}catch(e){c._wD(a.id+": setPosition("+b+") failed: "+
e.message,2)}}}else if(b)return c._wD(a.id+": setPosition("+b+"): Cannot seek yet, sound not ready",2),a;a.paused&&a._onTimer(!0)}return a};this.pause=function(b){if(a.paused||0===a.playState&&1!==a.readyState)return a;c._wD(a.id+": pause()");a.paused=!0;a.isHTML5?(a._setup_html5().pause(),F()):(b||b===g)&&l._pause(a.id,a._iO.multiShot);a._iO.onpause&&a._iO.onpause.apply(a);return a};this.resume=function(){var b=a._iO;if(!a.paused)return a;c._wD(a.id+": resume()");a.paused=!1;a.playState=1;a.isHTML5?
(a._setup_html5().play(),m()):(b.isMovieStar&&!b.serverURL&&a.setPosition(a.position),l._pause(a.id,b.multiShot));!r&&b.onplay?(b.onplay.apply(a),r=!0):b.onresume&&b.onresume.apply(a);return a};this.togglePause=function(){c._wD(a.id+": togglePause()");if(0===a.playState)return a.play({position:9!==n||a.isHTML5?a.position/1E3:a.position}),a;a.paused?a.resume():a.pause();return a};this.setPan=function(b,c){b===g&&(b=0);c===g&&(c=!1);a.isHTML5||l._setPan(a.id,b);a._iO.pan=b;c||(a.pan=b,a.options.pan=
b);return a};this.setVolume=function(b,d){b===g&&(b=100);d===g&&(d=!1);a.isHTML5?a._a&&(c.muted&&!a.muted&&(a.muted=!0,a._a.muted=!0),a._a.volume=Math.max(0,Math.min(1,b/100))):l._setVolume(a.id,c.muted&&!a.muted||a.muted?0:b);a._iO.volume=b;d||(a.volume=b,a.options.volume=b);return a};this.mute=function(){a.muted=!0;a.isHTML5?a._a&&(a._a.muted=!0):l._setVolume(a.id,0);return a};this.unmute=function(){a.muted=!1;var b=a._iO.volume!==g;a.isHTML5?a._a&&(a._a.muted=!1):l._setVolume(a.id,b?a._iO.volume:
a.options.volume);return a};this.toggleMute=function(){return a.muted?a.unmute():a.mute()};this.onposition=this.onPosition=function(b,c,d){D.push({position:parseInt(b,10),method:c,scope:d!==g?d:a,fired:!1});return a};this.clearOnPosition=function(a,b){var c;a=parseInt(a,10);if(!isNaN(a))for(c=0;c=b)return!1;for(--b;0<=b;b--)c=D[b],!c.fired&&
a.position>=c.position&&(c.fired=!0,v++,c.method.apply(c.scope,[c.position]));return!0};this._resetOnPosition=function(a){var b,c;b=D.length;if(!b)return!1;for(--b;0<=b;b--)c=D[b],c.fired&&a<=c.position&&(c.fired=!1,v--);return!0};y=function(){var b=a._iO,d=b.from,e=b.to,f,g;g=function(){c._wD(a.id+': "To" time of '+e+" reached.");a.clearOnPosition(e,g);a.stop()};f=function(){c._wD(a.id+': Playing "from" '+d);if(null!==e&&!isNaN(e))a.onPosition(e,g)};null===d||isNaN(d)||(b.position=d,b.multiShot=
!1,f());return b};q=function(){var b,c=a._iO.onposition;if(c)for(b in c)if(c.hasOwnProperty(b))a.onPosition(parseInt(b,10),c[b])};Xa=function(){var b,c=a._iO.onposition;if(c)for(b in c)c.hasOwnProperty(b)&&a.clearOnPosition(parseInt(b,10))};m=function(){a.isHTML5&&eb(a)};F=function(){a.isHTML5&&fb(a)};f=function(b){b||(D=[],v=0);r=!1;a._hasTimer=null;a._a=null;a._html5_canplay=!1;a.bytesLoaded=null;a.bytesTotal=null;a.duration=a._iO&&a._iO.duration?a._iO.duration:null;a.durationEstimate=null;a.buffered=
[];a.eqData=[];a.eqData.left=[];a.eqData.right=[];a.failures=0;a.isBuffering=!1;a.instanceOptions={};a.instanceCount=0;a.loaded=!1;a.metadata={};a.readyState=0;a.muted=!1;a.paused=!1;a.peakData={left:0,right:0};a.waveformData={left:[],right:[]};a.playState=0;a.position=null;a.id3={}};f();this._onTimer=function(b){var c,f=!1,g={};(a._hasTimer||b)&&a._a&&(b||(0opera.version()?new Audio(null):new Audio,c=a._a,c._called_load=!1,B&&(Ya=c);a.isHTML5=!0;a._a=c;c._s=a;h();a._apply_loop(c,b.loops);b.autoLoad||b.autoPlay?a.load():(c.autobuffer=!1,c.preload="auto");return c};h=function(){if(a._a._added_events)return!1;var b;a._a._added_events=
!0;for(b in I)I.hasOwnProperty(b)&&a._a&&a._a.addEventListener(b,I[b],!1);return!0};k=function(){var b;c._wD(a.id+": Removing event listeners");a._a._added_events=!1;for(b in I)I.hasOwnProperty(b)&&a._a&&a._a.removeEventListener(b,I[b],!1)};this._onload=function(b){var d=!!b||!a.isHTML5&&8===n&&a.duration;b=a.id+": ";c._wD(b+(d?"onload()":"Failed to load / invalid sound?"+(a.duration?" -":" Zero-length duration reported.")+" ("+a.url+")"),d?1:2);d||a.isHTML5||(!0===c.sandbox.noRemote&&c._wD(b+t("noNet"),
1),!0===c.sandbox.noLocal&&c._wD(b+t("noLocal"),1));a.loaded=d;a.readyState=d?3:2;a._onbufferchange(0);d||a.isHTML5||a._onerror();a._iO.onload&&fa(a,function(){a._iO.onload.apply(a,[d])});return!0};this._onerror=function(b,c){a._iO.onerror&&fa(a,function(){a._iO.onerror.apply(a,[b,c])})};this._onbufferchange=function(b){if(0===a.playState||b&&a.isBuffering||!b&&!a.isBuffering)return!1;a.isBuffering=1===b;a._iO.onbufferchange&&(c._wD(a.id+": Buffer state change: "+b),a._iO.onbufferchange.apply(a,[b]));
return!0};this._onsuspend=function(){a._iO.onsuspend&&(c._wD(a.id+": Playback suspended"),a._iO.onsuspend.apply(a));return!0};this._onfailure=function(b,d,e){a.failures++;c._wD(a.id+": Failure ("+a.failures+"): "+b);if(a._iO.onfailure&&1===a.failures)a._iO.onfailure(b,d,e);else c._wD(a.id+": Ignoring failure")};this._onwarning=function(b,c,d){if(a._iO.onwarning)a._iO.onwarning(b,c,d)};this._onfinish=function(){var b=a._iO.onfinish;a._onbufferchange(0);a._resetOnPosition(0);a.instanceCount&&(a.instanceCount--,
a.instanceCount||(Xa(),a.playState=0,a.paused=!1,a.instanceCount=0,a.instanceOptions={},a._iO={},F(),a.isHTML5&&(a.position=0)),a.instanceCount&&!a._iO.multiShotEvents||!b||(c._wD(a.id+": onfinish()"),fa(a,function(){b.apply(a)})))};this._whileloading=function(b,c,d,e){var f=a._iO;a.bytesLoaded=b;a.bytesTotal=c;a.duration=Math.floor(d);a.bufferLength=e;a.durationEstimate=a.isHTML5||f.isMovieStar?a.duration:f.duration?a.duration>f.duration?a.duration:f.duration:parseInt(a.bytesTotal/a.bytesLoaded*
a.duration,10);a.isHTML5||(a.buffered=[{start:0,end:a.duration}]);(3!==a.readyState||a.isHTML5)&&f.whileloading&&f.whileloading.apply(a)};this._whileplaying=function(b,c,d,e,f){var k=a._iO;if(isNaN(b)||null===b)return!1;a.position=Math.max(0,b);a._processOnPosition();!a.isHTML5&&8opera.version()?
new Audio(null):new Audio:null,e,a,f={},h,k;h=c.audioFormats;for(e in h)if(h.hasOwnProperty(e)&&(a="audio/"+e,f[e]=b(h[e].type),f[a]=f[e],e.match(pb)?(c.flash[e]=!0,c.flash[a]=!0):(c.flash[e]=!1,c.flash[a]=!1),h[e]&&h[e].related))for(k=h[e].related.length-1;0<=k;k--)f["audio/"+h[e].related[k]]=f[e],c.html5[h[e].related[k]]=f[e],c.flash[h[e].related[k]]=f[e];f.canPlayType=d?b:null;c.html5=A(c.html5,f);c.html5.usingFlash=hb();u=c.html5.usingFlash;return!0};z={notReady:"Unavailable - wait until onready() has fired.",
notOK:"Audio support is not available.",domError:"soundManagerexception caught while appending SWF to DOM.",spcWmode:"Removing wmode, preventing known SWF loading issue(s)",swf404:"soundManager: Verify that %s is a valid path.",tryDebug:"Try soundManager.debugFlash = true for more security details (output goes to SWF.)",checkSWF:"See SWF output for more debug info.",localFail:"soundManager: Non-HTTP page ("+m.location.protocol+" URL?) Review Flash player security settings for this special case:\nhttp://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html\nMay need to add/allow path, eg. c:/sm2/ or /users/me/sm2/",
waitFocus:"soundManager: Special case: Waiting for SWF to load with window focus...",waitForever:"soundManager: Waiting indefinitely for Flash (will recover if unblocked)...",waitSWF:"soundManager: Waiting for 100% SWF load...",needFunction:"soundManager: Function object expected for %s",badID:'Sound ID "%s" should be a string, starting with a non-numeric character',currentObj:"soundManager: _debug(): Current sound objects",waitOnload:"soundManager: Waiting for window.onload()",docLoaded:"soundManager: Document already loaded",
onload:"soundManager: initComplete(): calling soundManager.onload()",onloadOK:"soundManager.onload() complete",didInit:"soundManager: init(): Already called?",secNote:"Flash security note: Network/internet URLs will not load due to security restrictions. Access can be configured via Flash Player Global Security Settings Page: http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html",badRemove:"soundManager: Failed to remove Flash node.",shutdown:"soundManager.disable(): Shutting down",
queue:"soundManager: Queueing %s handler",smError:"SMSound.load(): Exception: JS-Flash communication failed, or JS error.",fbTimeout:"No flash response, applying .swf_timedout CSS...",fbLoaded:"Flash loaded",fbHandler:"soundManager: flashBlockHandler()",manURL:"SMSound.load(): Using manually-assigned URL",onURL:"soundManager.load(): current URL already assigned.",badFV:'soundManager.flashVersion must be 8 or 9. "%s" is invalid. Reverting to %s.',as2loop:"Note: Setting stream:false so looping can work (flash 8 limitation)",
noNSLoop:"Note: Looping not implemented for MovieStar formats",needfl9:"Note: Switching to flash 9, required for MP4 formats.",mfTimeout:"Setting flashLoadTimeout = 0 (infinite) for off-screen, mobile flash case",needFlash:"soundManager: Fatal error: Flash is needed to play some required formats, but is not available.",gotFocus:"soundManager: Got window focus.",policy:"Enabling usePolicyFile for data access",setup:"soundManager.setup(): allowed parameters: %s",setupError:'soundManager.setup(): "%s" cannot be assigned with this method.',
setupUndef:'soundManager.setup(): Could not find option "%s"',setupLate:"soundManager.setup(): url, flashVersion and html5Test property changes will not take effect until reboot().",noURL:"soundManager: Flash URL required. Call soundManager.setup({url:...}) to get started.",sm2Loaded:"SoundManager 2: Ready. "+String.fromCharCode(10003),reset:"soundManager.reset(): Removing event callbacks",mobileUA:"Mobile UA detected, preferring HTML5 by default.",globalHTML5:"Using singleton HTML5 Audio() pattern for this device.",
ignoreMobile:"Ignoring mobile restrictions for this device."};t=function(){var b,c,e,a;b=kb.call(arguments);c=b.shift();if((a=z&&z[c]?z[c]:"")&&b&&b.length)for(c=0,e=b.length;cn&&(c._wD(t("needfl9")),c.flashVersion=n=9);c.version=c.versionNumber+(c.html5Only?" (HTML5-only mode)":9===n?" (AS3/Flash 9)":" (AS2/Flash 8)");8'}if(W&&X)return!1;if(c.html5Only)return Da(),e(),c.oMC=E(c.movieID),ya(),X=W=!0,!1;var f=d||c.url,h=c.altURL||f,k=ma(),l=U(),n=null,n=m.getElementsByTagName("html")[0],p,r,q,n=n&&n.dir&&n.dir.match(/rtl/i);b=b===g?c.id:b;Da();c.url=cb(ga?f:h);d=c.url;c.wmode=!c.wmode&&c.useHighPerformance?"transparent":c.wmode;null!==c.wmode&&(v.match(/msie 8/i)||!N&&!c.useHighPerformance)&&navigator.platform.match(/win32|win64/i)&&(L.push(z.spcWmode),c.wmode=null);k=
{name:b,id:b,src:d,quality:"high",allowScriptAccess:c.allowScriptAccess,bgcolor:c.bgColor,pluginspage:vb+"www.macromedia.com/go/getflashplayer",title:"JS/Flash audio component (SoundManager 2)",type:"application/x-shockwave-flash",wmode:c.wmode,hasPriority:"true"};c.debugFlash&&(k.FlashVars="debug=1");c.wmode||delete k.wmode;if(N)f=m.createElement("div"),r=['"].join("");else for(p in f=m.createElement("embed"),k)k.hasOwnProperty(p)&&f.setAttribute(p,k[p]);Fa();l=U();if(k=ma())if(c.oMC=E(c.movieID)||m.createElement("div"),c.oMC.id)q=c.oMC.className,c.oMC.className=(q?q+" ":"movieContainer")+(l?" "+l:""),c.oMC.appendChild(f),N&&(p=c.oMC.appendChild(m.createElement("div")),
p.className="sm2-object-box",p.innerHTML=r),X=!0;else{c.oMC.id=c.movieID;c.oMC.className="movieContainer "+l;p=l=null;c.useFlashBlock||(c.useHighPerformance?l={position:"fixed",width:"8px",height:"8px",bottom:"0px",left:"0px",overflow:"hidden"}:(l={position:"absolute",width:"6px",height:"6px",top:"-9999px",left:"-9999px"},n&&(l.left=Math.abs(parseInt(l.left,10))+"px")));ub&&(c.oMC.style.zIndex=1E4);if(!c.debugFlash)for(q in l)l.hasOwnProperty(q)&&(c.oMC.style[q]=l[q]);try{N||c.oMC.appendChild(f),
k.appendChild(c.oMC),N&&(p=c.oMC.appendChild(m.createElement("div")),p.className="sm2-object-box",p.innerHTML=r),X=!0}catch(u){throw Error(t("domError")+" \n"+u.toString());}}W=!0;e();return!0};la=function(){if(c.html5Only)return na(),!1;if(l)return!1;if(!c.url)return p("noURL"),!1;l=c.getMovie(c.id);l||(aa?(N?c.oMC.innerHTML=Ia:c.oMC.appendChild(aa),aa=null,W=!0):na(c.id,c.url),l=c.getMovie(c.id));"function"===typeof c.oninitmovie&&setTimeout(c.oninitmovie,1);Oa();return!0};S=function(){setTimeout($a,
1E3)};Ca=function(){h.setTimeout(function(){K("soundManager: useFlashBlock is false, 100% HTML5 mode is possible. Rebooting with preferFlash: false...");c.setup({preferFlash:!1}).reboot();c.didFlashBlock=!0;c.beginDelayedInit()},1)};$a=function(){var b,d=!1;c.url&&!ba&&(ba=!0,x.remove(h,"load",S),G&&wa&&!Va?p("waitFocus"):(q||(b=c.getMoviePercent(),0b&&(d=!0)),setTimeout(function(){b=c.getMoviePercent();d?(ba=!1,c._wD(t("waitSWF")),h.setTimeout(S,1)):(q||(c._wD("soundManager: No Flash response within expected time. Likely causes: "+
(0===b?"SWF load failed, ":"")+"Flash blocked or JS-Flash security error."+(c.debugFlash?" "+t("checkSWF"):""),2),!ga&&b&&(p("localFail",2),c.debugFlash||p("tryDebug",2)),0===b&&c._wD(t("swf404",c.url),1),C("flashtojs",!1,": Timed out"+(ga?" (Check flash security or flash blockers)":" (No plugin/missing SWF?)"))),!q&&ob&&(null===b?c.useFlashBlock||0===c.flashLoadTimeout?(c.useFlashBlock&&Ja(),p("waitForever")):!c.useFlashBlock&&da?Ca():(p("waitForever"),O({type:"ontimeout",ignoreInit:!0,error:{type:"INIT_FLASHBLOCK"}})):
0===c.flashLoadTimeout?p("waitForever"):!c.useFlashBlock&&da?Ca():Ha(!0)))},c.flashLoadTimeout)))};ka=function(){if(Va||!wa)return x.remove(h,"focus",ka),!0;Va=ob=!0;p("gotFocus");ba=!1;S();x.remove(h,"focus",ka);return!0};Oa=function(){L.length&&(c._wD("SoundManager 2: "+L.join(" "),1),L=[])};mb=function(){Oa();var b,d=[];if(c.useHTML5Audio&&c.hasHTML5){for(b in c.audioFormats)c.audioFormats.hasOwnProperty(b)&&d.push(b+" = "+c.html5[b]+(!c.html5[b]&&u&&c.flash[b]?" (using flash)":c.preferFlash&&
c.flash[b]&&u?" (preferring flash)":c.html5[b]?"":" ("+(c.audioFormats[b].required?"required, ":"")+"and no flash support)"));c._wD("SoundManager 2 HTML5 support: "+d.join(", "),1)}};Y=function(b){if(q)return!1;if(c.html5Only)return p("sm2Loaded",1),q=!0,R(),C("onload",!0),!0;var d=!0,e;c.useFlashBlock&&c.flashLoadTimeout&&!c.getMoviePercent()||(q=!0);e={type:!G&&u?"NO_FLASH":"INIT_TIMEOUT"};c._wD("SoundManager 2 "+(y?"failed to load":"loaded")+" ("+(y?"Flash security/load error":"OK")+") "+String.fromCharCode(y?
10006:10003),y?2:1);y||b?(c.useFlashBlock&&c.oMC&&(c.oMC.className=U()+" "+(null===c.getMoviePercent()?"swf_timedout":"swf_error")),O({type:"ontimeout",error:e,ignoreInit:!0}),C("onload",!1),T(e),d=!1):C("onload",!0);y||(c.waitForWindowLoad&&!ja?(p("waitOnload"),x.add(h,"load",R)):(c.waitForWindowLoad&&ja&&p("docLoaded"),R()));return d};Za=function(){var b,d=c.setupOptions;for(b in d)d.hasOwnProperty(b)&&(c[b]===g?c[b]=d[b]:c[b]!==d[b]&&(c.setupOptions[b]=c[b]))};ya=function(){if(q)return p("didInit"),
!1;if(c.html5Only)return q||(x.remove(h,"load",c.beginDelayedInit),c.enabled=!0,Y()),!0;la();try{l._externalInterfaceTest(!1),ab(!0,c.flashPollingInterval||(c.useHighPerformance?10:50)),c.debugMode||l._disableDebug(),c.enabled=!0,C("jstoflash",!0),c.html5Only||x.add(h,"unload",xa)}catch(b){return c._wD("js/flash exception: "+b.toString()),C("jstoflash",!1),T({type:"JS_TO_FLASH_EXCEPTION",fatal:!0}),Ha(!0),Y(),!1}Y();x.remove(h,"load",c.beginDelayedInit);return!0};P=function(){if(Z)return!1;Z=!0;Za();
Fa();!G&&c.hasHTML5&&(c._wD("SoundManager 2: No Flash detected"+(c.useHTML5Audio?". Trying HTML5-only mode.":", enabling HTML5."),1),c.setup({useHTML5Audio:!0,preferFlash:!1}));jb();!G&&u&&(L.push(z.needFlash),c.setup({flashLoadTimeout:1}));m.removeEventListener&&m.removeEventListener("DOMContentLoaded",P,!1);la();return!0};La=function(){"complete"===m.readyState&&(P(),m.detachEvent("onreadystatechange",La));return!0};Ea=function(){ja=!0;P();x.remove(h,"load",Ea)};Na();x.add(h,"focus",ka);x.add(h,
"load",S);x.add(h,"load",Ea);m.addEventListener?m.addEventListener("DOMContentLoaded",P,!1):m.attachEvent?m.attachEvent("onreadystatechange",La):(C("onload",!1),T({type:"NO_DOM2_EVENTS",fatal:!0}))}if(!h||!h.document)throw Error("SoundManager requires a browser with window and document objects.");var V=null;h.SM2_DEFER!==g&&SM2_DEFER||(V=new J);"object"===typeof module&&module&&"object"===typeof module.exports?(module.exports.SoundManager=J,module.exports.soundManager=V):"function"===typeof define&&
define.amd&&define(function(){return{constructor:J,getInstance:function(g){!h.soundManager&&g instanceof Function&&(g=g(J),g instanceof J&&(h.soundManager=g));return h.soundManager}}});h.SoundManager=J;h.soundManager=V})(window);/**
* Used for adding Audio captcha to existing captcha inputs.
*/
YUI().add("scriptlibrary.input.AudioCaptcha", function (Y) {
"use strict";
var attributeConfig = function () {
return {
contextPath: {},
sequenceNumber: {},
resourceName: {},
resources: {
value: null,
setter: function(resources) {
return resources && resources.CaptchaInput
? resources.CaptchaInput
: resources;
}
}
};
};
// @formatter:off
var MODE_HTML =
'{{textModeLabel}}' +
'{{audioModeLabel}}',
AUDIO_HTML = '{{replayButtonLabel}}';
// @formatter:on
/**
* Initializes the state selector.
* @param {type} parameters Initialization parameters.
*/
var AudioCaptcha = function(parameters) {
this.addAttrs(attributeConfig(), parameters);
var me = this,
resources = this.get("resources"),
contextPath = this.get("contextPath"),
resourceName = this.get("resourceName"),
audioModeButton,
textModeButton,
modeContainer,
audioContainer,
currentMode = "text",
managerReady = false,
initialized = false,
language,
image,
sound;
var initialize = function(imageContainer) {
if (initialized) {
return;
}
language = Y.one("html").getAttribute("lang") || "en-US";
image = imageContainer.one("img");
me.after("sequenceNumberChange", refreshAudio);
var template = new Y.Template(Y.Handlebars);
audioContainer = imageContainer.one(".captcha-audio-container");
if (!audioContainer) {
audioContainer = Y.Node.create("");
audioContainer.setHTML(template.render(AUDIO_HTML, resources));
imageContainer.appendChild(audioContainer);
}
modeContainer = imageContainer.one(".captcha-mode-options");
if (!modeContainer) {
modeContainer = Y.Node.create("");
modeContainer.setHTML(template.render(MODE_HTML, resources));
imageContainer.appendChild(modeContainer);
}
modeContainer.show();
audioContainer.hide();
audioModeButton = modeContainer.one(".captcha-audio-mode");
textModeButton = modeContainer.one(".captcha-text-mode");
audioModeButton.on("click", audioMode);
textModeButton.on("click", textMode);
audioContainer.one(".captcha-replay-audio").on("click", replayAudio);
initializeAudio();
initialized = true;
};
var initializeAudio = function() {
soundManager.setup({
url: contextPath + "/files/scriptlibrary/js/audio/",
debugMode: false,
ontimeout: function() {
alert("Error initializing audio");
},
onready: function() {
managerReady = true;
if (currentMode === "audio") {
initializeSound();
sound.play();
}
}
});
};
var textMode = function() {
if (sound) {
sound.stop();
}
currentMode = "text";
audioContainer.hide();
image.show();
textModeButton.hide();
audioModeButton.show();
};
var replayAudio = function() {
if (!sound) {
initializeSound();
}
sound.stop();
sound.play();
};
var audioMode = function() {
image.hide();
audioContainer.show();
audioModeButton.hide();
textModeButton.show();
currentMode = "audio";
if (!sound) {
initializeSound();
}
sound.stop();
sound.play();
};
var initializeSound = function() {
if (!managerReady) {
return;
}
sound = new CaptchaSound(resourceName, me.get("sequenceNumber"), language);
};
var refreshAudio = function() {
if (sound) {
sound.destruct();
sound.stop();
}
sound = null;
if (currentMode == "audio") {
initializeSound();
sound.play();
}
};
/**
* Resets to text mode.
*/
this.resetToTextMode = function() {
if (!initialized) {
return;
}
textMode();
};
/**
* Renders the state selector.
*
* @param {Node} imageContainer Image container.
* @param {Node} refreshButton Refresh button.
*/
this.render = function(imageContainer) {
if (!imageContainer) {
return;
}
initialize(imageContainer);
};
};
var CaptchaSound = function(resourceName, sequenceNumber, languageTag) {
var me = this,
index = 0,
current,
stopped = false;
var playNext = function() {
if (index > 4) {
return;
}
current = soundManager.createSound({
url: contextPath + "/captcha.mp3?index=" + index + "&languageTag=" + languageTag + "&resourceName=" + resourceName + "&sequenceNumber=" + sequenceNumber,
onfinish: function() {
index++;
playNext();
}
});
current.play();
};
this.play = function() {
stopped = false;
index = 0;
playNext();
};
this.destruct = function() {
if (current) {
current.destruct();
}
}
this.stop = function() {
stopped = true;
if (current) {
current.stop();
}
};
};
Y.augment(AudioCaptcha, Y.Attribute);
Y.scriptlibrary = Y.scriptlibrary || {};
Y.scriptlibrary.input = Y.scriptlibrary.input || {};
Y.scriptlibrary.input.AudioCaptcha = AudioCaptcha;
});YUI().add("scriptlibrary.ErrorHandlers", function (Y) {
Y.scriptlibrary = Y.scriptlibrary || {};
var extractError = function(error) {
if (Y.Lang.isString(error)) {
return error;
}
else if (Y.Lang.isFunction(error)) {
return error();
}
return null;
};
Y.scriptlibrary.ErrorHandlers = {
/**
* Gets error handler that will show message in a node.
*
* @param {Node|String} errorNode Node to display error message in.
* @param {String} fallbackMessage Fall back message if the error is not a string.
* @param {Function} [afterErrorFn] Called after the error reporting is complete.
* @returns {Function} Error handler.
*/
handleErrorInNode: function(errorNode, fallbackMessage, afterErrorFn) {
return function(error) {
if (!error) {
return;
}
var node = Y.one(errorNode);
node.set("text", extractError(error) || fallbackMessage);
if (Y.scriptlibrary.DynamicWindow) {
Y.scriptlibrary.DynamicWindow.HideWaitMessage();
}
node.show();
if (console && console.error) {
console.error(error);
}
if (afterErrorFn) {
afterErrorFn();
}
};
},
/**
* Gets error handler that will show message in a modal popup.
*
* @param {String} fallbackMessage Fall back message if the error is not a string.
* @param {Number} [zIndex] Z-index to use.
* @param {Function} [afterErrorFn] Function to call after the error is handled.
* @returns {Function} Error handler.
*/
handleErrorInPopup: function(fallbackMessage, zIndex, afterErrorFn) {
return function(error) {
if (!error) {
return;
}
var message = extractError(error) || fallbackMessage;
if (Y.scriptlibrary.DynamicWindow) {
Y.scriptlibrary.DynamicWindow.HideWaitMessage();
Y.scriptlibrary.DynamicWindow.ShowCompletedMessage(message, "OK", zIndex);
}
else {
alert(message);
}
if (console && console.error) {
console.error(error);
}
if (afterErrorFn) {
afterErrorFn();
}
};
}
};
});
/**
* Contains internationialization helpers
*/
YUI().add("scriptlibrary.i18n.Locale", function (Y) {
"use strict";
var getFormat = function(locale, precision, symbol, noThousands) {
var format = "";
switch(normalizeTag(locale)) {
case "fr_CA":
format = {
decimalPlaces: precision,
decimalSeparator: ",",
thousandsSeparator: noThousands ? "" : " ",
suffix: symbol ? " " + symbol : ""
};
break;
case "nl_NL":
format = {
decimalPlaces: precision,
decimalSeparator: ",",
thousandsSeparator: noThousands ? "" : " ",
prefix: symbol ? symbol : ""
};
break;
default:
format = {
decimalPlaces: precision,
decimalSeparator: ".",
thousandsSeparator: noThousands ? "" : ",",
prefix: symbol ? symbol : ""
};
};
return format;
};
var normalizeTag = function(locale){
if (locale) {
return locale.replace("-","_");
}
else {
return null;
}
};
Y.scriptlibrary = Y.scriptlibrary || {};
Y.scriptlibrary.i18n = Y.scriptlibrary.i18n|| {};
Y.scriptlibrary.i18n.Locale = {
/**
* Normalizes the given tag.
* @param {String} locale Locale.
* @return {String} normalized tag.
*/
normalize: function(locale) {
return normalizeTag(locale);
},
/**
* Formats the given number to the locale.
* @param {String} locale Locale to use.
* @param {Number} precision Number of decimal places
* @param {String} symbol Currency symbol
* @param {Boolean} noThousands True if no thousands separator should be used.
* @returns {String} precision Precision.
*/
getNumberFormat: function(locale, precision, symbol, noThousands) {
if (!precision) {
precision = 2;
}
return getFormat(locale, precision, symbol, noThousands);
}
};
});/**
* Contains number formatter.
*/
YUI().add("scriptlibrary.formatters.NumberFormatter", function (Y) {
"use strict";
var getFormattedNumber = function(number, locale, precision, noThousands) {
var formattedNumber;
if (number !== null && number !== "") {
formattedNumber = Y.DataType.Number.format(number, Y.scriptlibrary.i18n.Locale.getNumberFormat(locale, precision, null, noThousands));
}
else {
formattedNumber = "";
}
return formattedNumber;
};
Y.scriptlibrary = Y.scriptlibrary || {};
Y.scriptlibrary.formatters = Y.scriptlibrary.formatters || {};
Y.scriptlibrary.formatters.NumberFormatter = {
/**
* Formats the given number to the locale.
* @param {type} number Number to format.
* @param {type} locale Locale to use.
* @returns {String} precision Precision.
*/
format: function(number, locale, precision, noThousands) {
if (!precision) {
precision = 2;
}
return getFormattedNumber(number, locale, precision, noThousands);
},
getParsedNumber: function(number, locale, symbol, suffix){
var formattedNumber;
if (number !== null && number !== "") {
if(suffix) {
number = number.replace(suffix, "");
}
formattedNumber = Y.DataType.Number.parse(number, Y.scriptlibrary.i18n.Locale.getNumberFormat(locale, 2, symbol));
}
else {
formattedNumber = "";
}
return formattedNumber;
}
};
});/**
* Contains currency formatter.
*/
YUI().add("scriptlibrary.formatters.CurrencyFormatters", function (Y) {
"use strict";
var getFormattedPrice = function(price, locale, symbol, suffix) {
var formattedPrice;
if (price !== null && price !== "") {
formattedPrice = Y.DataType.Number.format(price, Y.scriptlibrary.i18n.Locale.getNumberFormat(locale, 2, symbol));
if(suffix) {
formattedPrice += " " + suffix;
}
}
else {
formattedPrice = "";
}
return formattedPrice;
};
Y.scriptlibrary = Y.scriptlibrary || {};
Y.scriptlibrary.formatters = Y.scriptlibrary.formatters || {};
Y.scriptlibrary.formatters.CurrencyFormatters = {
/**
* Formats the given value as currency.
* @param {Number} price Price to format.
* @param {String} locale Locale to use.
* @returns {String} Formatted price.
*/
format: function(price, locale, symbol, suffix) {
var currencySymbol = symbol ? symbol : "$";
return getFormattedPrice(price, locale, currencySymbol, suffix);
},
/**
* Reverses the formatting on currency
* @param {String} number Number to parse
* @param {String} locale Locale to parse from
* @param {String} symbol Symbol used
* @param {String} suffix Suffix if there is one
* @returns Number string
*/
parse: function(number, locale, symbol, suffix) {
var currencySymbol = symbol ? symbol : "$";
return Y.scriptlibrary.formatters.NumberFormatter.getParsedNumber(number, locale, currencySymbol, suffix);
}
};
});YUI().add("scriptlibrary.ValidationHelpers", function (Y) {
Y.scriptlibrary = Y.scriptlibrary || {};
var ZipCodeRegexes = {
US: /^\d{5}(?:[-\s]\d{4})?$/,
CA: /^[a-zA-Z]{1}[0-9]{1}[a-zA-Z]{1}[\s]*[0-9]{1}[a-zA-Z]{1}[0-9]{1}$/,
UK: /^(((([A-PR-UWYZ][0-9][0-9A-HJKS-UW]?)|([A-PR-UWYZ][A-HK-Y][0-9][0-9ABEHMNPRV-Y]?))\s{0,2}[0-9]([ABD-HJLNP-UW-Z]{2}))|(GIR\s{0,2}0AA))$/,
IE: /^[AC-FHKNPRTV-Y][0-9][0-9W][A-Z0-9]{4}$/,
AU: /^\d{4}$/,
NZ: /^\d{4}$/
},
PhoneRegexes = {
US: /^([(]?[2-9]\d{2}[)]?)[ ]*-?[ ]*(\d{3})[ ]*-?[ ]*(\d{4})$/,
CA: /^([(]?[2-9]\d{2}[)]?)[ ]*-?[ ]*(\d{3})[ ]*-?[ ]*(\d{4})$/
},
DoubleRegex = /(^-?\d\d*\.\d+$)|(^-?\d\d*$)|(^-?\.\d\d*$)/,
EmojiDetectionRegex = /([\uD800-\uDBFF][\uDC00-\uDFFF])/,
PasswordRegex = /^(?=.*\d)(?=.*[a-zA-Z])[A-Za-z0-9!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?\s]{8,}$/,
PhoneValid = function(value, country) {
var regex = PhoneRegexes[country];
if (regex) {
return regex.test(value);
}
else if (value === "AU" || value === "NZ") {
var number = value.replace(eval('/[)(\\- ]/g'),'');
/^\d*$/.test(number) && number.length >= 6 && number <= 10;
}
else {
var number = value.replace(eval('/[)(\\- ]/g'),'');
return /^\d*$/.test(number) && number.length >= 10;
}
},
CreditCardTypes = [
{
matches: function(cardType) { return cardType === "VISA"; },
cardType:"VISA",
cardRegex: /^4[0-9]{12}(?:[0-9]{3})?$/,
secretCodeRegex: /^[0-9]{3}$/
},
{
matches: function(cardType) { return cardType === "MASTERCARD"; },
cardType: "MASTERCARD",
cardRegex: /^5[1-5][0-9]{14}$/,
secretCodeRegex: /^[0-9]{3}$/
},
{
matches: function(cardType) { return cardType === "AMEX" || cardType === "AMERICANEXPRESS"; },
cardType: "AMEX",
cardRegex: /^3[47][0-9]{13}$/,
secretCodeRegex: /^[0-9]{4}$/
},
{
matches: function(cardType) { return cardType === "DISCOVER"; },
cardType: "DISCOVER",
cardRegex: /^6(?:011|5[0-9]{2})[0-9]{12}$/,
secretCodeRegex: /^[0-9]{3}$/
},
{
matches: function(cardType) { return cardType === "JCB"; },
cardType: "JCB",
cardRegex: /^(?:2131|1800|35\d{3})\d{11}$/,
secretCodeRegex: /^[0-9]{3}$/
}
],
PasswordErrors = {
CORRECT: 0,
MISMATCH: 1,
EMPTY: 2,
WEAK: 3
},
getDecimalSeparator = function(locale) {
var separator = "";
switch (locale) {
case "nl-NL":
case "fr-CA":
separator = "(\\,|\\.)";
break;
default:
separator = "\\.";
}
return separator;
};
Y.scriptlibrary.ValidationHelpers = {
IsValidEmail: function(email, optional) {
var trimmedEmail = email ? email.trim() : null;
if (optional && !trimmedEmail) {
return true;
}
return /^(?!\.)(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]|\.(?![.@]))+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/.test(trimmedEmail);
},
ContainsEmoji: function(value) {
return EmojiDetectionRegex.test(value);
},
IsLatitude: function(value) {
if (!DoubleRegex.test(value)) {
return false;
}
var lat = parseFloat(value, 10);
return lat >= -90 && lat <= 90;
},
IsLongitude: function(value) {
if (!DoubleRegex.test(value)) {
return false;
}
var lng = parseFloat(value, 10);
return lng <= 180 && lng >= -180;
},
IsValidInteger: function(value, min, max) {
if (!/^-?\d\d*$/.test(value)) {
return false;
}
var number = parseInt(value, 10);
if ((min || min === 0) && number < min) {
return false;
}
else if ((max || max === 0) && number > max) {
return false;
}
return true;
},
IsValidDouble: function(value, min, max, maxDecimalPlaces, locale) {
var pattern,
decimalSeparator = getDecimalSeparator(locale);
if (!value) {
return false;
}
if (maxDecimalPlaces) {
pattern = new RegExp("^\\-?\\d*" + decimalSeparator + "?\\d{0,"+maxDecimalPlaces+"}$");
}
else {
pattern = new RegExp("^\\-?\\d*" + decimalSeparator + "?\\d*$");
}
if (!pattern.test(value)) {
return false;
}
var number = parseFloat(value);
if ((min || min === 0) && number < min) {
return false;
}
else if ((max || max === 0) && number > max) {
return false;
}
return true;
},
IsPhoneValid: PhoneValid,
IsPhoneValidAnyCountry: function(value) {
for (var country in PhoneRegexes) {
if (PhoneValid(value, function() { return country; })) {
return true;
}
}
return false;
},
GetPostalCodeRegex: function(country) {
return ZipCodeRegexes[country];
},
IsValidCode: function(code, country) {
var regex = ZipCodeRegexes[country];
if (regex) {
return regex.test(code);
}
else {
return true;
}
},
anySecretCode: function(secretNumber) {
var valid = false;
if (secretNumber === "***" || secretNumber === "****") {
return true;
}
Y.Array.each(CreditCardTypes, function(ccType) {
valid = valid || ccType.secretCodeRegex.test(secretNumber);
});
return valid;
},
IsSecretCodeValid: function(secretNumber, cardType) {
var creditCard = this.GetCreditCardByCardType(cardType);
if(creditCard) {
return creditCard.secretCodeRegex.test(secretNumber);
}
return false;
},
GetCreditCardByCardType: function(cardType) {
for(var i = 0; i < CreditCardTypes.length; ++i) {
if(CreditCardTypes[i].matches(cardType)) {
return CreditCardTypes[i];
}
}
return null;
},
GetCreditCardType: function(cardNumber) {
for(var i = 0; i < CreditCardTypes.length; ++i) {
if(CreditCardTypes[i].cardRegex.test(cardNumber)) {
return CreditCardTypes[i].cardType;
}
}
return null;
},
IsValidCreditCard: function(cardNumber, cardType) {
cardNumber = cardNumber.replace(/[^0-9]*/g, "");
var creditCard = this.GetCreditCardByCardType(cardType);
if(creditCard) {
return creditCard.cardRegex.test(cardNumber);
}
return false;
},
/**
* True if the value contains only alpha numeric characters.
* @param {type} value Value to check.
* @returns {boolean} True if the value only contains alpha numeric characters.
*/
isAlphaNumeric: function(value) {
return /^[a-zA-Z0-9]*$/.test(value);
},
/**
* True if the value contains only symbols allowed for variable declaration.
* @param {type} value Value to check.
* @returns {boolean} True if the value only contains valid variable characters.
*/
isVariableName: function(value) {
return /^[a-zA-Z][a-zA-Z_0-9]*$/.test(value);
},
PasswordErrors: PasswordErrors,
ValidatePassword: function (password, confirmPassword, canBeEmpty) {
if(!password && !confirmPassword && canBeEmpty) {
return {valid: true, error: PasswordErrors.CORRECT};
}
else if((!password || !confirmPassword) && !canBeEmpty) {
return {valid: false, error: PasswordErrors.EMPTY};
}
else if (password !== confirmPassword) {
return {valid: false, error: PasswordErrors.MISMATCH};
}
else if (!PasswordRegex.test(password)) {
return {valid: false, error: PasswordErrors.WEAK};
}
else {
return {valid: true, error: PasswordErrors.CORRECT};
}
}
};
});YUI().add("scriptlibrary.ArrayExtensions", function (Y) {
if (!Array.prototype.filter) {
Array.prototype.filter = function(fn /*, scope*/) {
var len = this.length,
res = new Array(),
scope = arguments[1];
for (var i = 0; i < len; i++) {
if (i in this) {
var val = this[i];
if (fn.call(scope, val, i, this)) {
res.push(val);
}
}
}
return res;
};
}
if (!Array.prototype.findFirst) {
Array.prototype.findFirst = function(fn, scope) {
var len = this.length;
return Y.Array.find(this, function(value) {
return fn.call(scope, value);
});
};
}
if (!Array.prototype.containsAll) {
Array.prototype.containsAll = function(otherArray, toMapKeyFn) {
var len = this.length,
mapKeyFn = toMapKeyFn || function(val) { return val; },
me = this,
thisMap = {};
Y.Array.each(this, function(value) {
thisMap[mapKeyFn(value)] = true;
});
return Y.Array.every(otherArray, function(otherValue) {
return thisMap[mapKeyFn(otherValue)];
});
};
}
});YUI().add("scriptlibrary.StringExtensions", function (Y) {
String.prototype.trim = String.prototype.trim || function(){ return this.replace(/^\s+|\s+$/g, ''); };
/**
* Appends the given value to this string if it is not empty.
* @param {String} delimiter (DEFAULT " ") Delimiter for the values.
* @param {String} value Value to append with delimiter.
* @return String with value appended, this string if value is empty.
*/
String.prototype.appendNonEmpty = function(delimiter, value) {
var delim = delimiter || " ";
if (this.trim() === "") {
return value || "";
}
if (value) {
return this + delim + value;
}
return this;
};
Y.scriptlibrary = Y.scriptlibrary || {};
Y.scriptlibrary.StringExtensions = {
EscapeHtml: function(value) {
return value
.replace(/&/g, '&')
.replace(/>/g, '>')
.replace(/= max) {
return false;
}
return true;
}
};
fields.push(registration);
};
/**
* Registers the given validator as the nested validator.
* @param {Node} node Container or input represented by the validator.
* @param {Validator} validator Validator to nest.
* @param {Boolean} optional True if optional.
* @param {Function} beforeValidation Called before validation occurs.
* @param {Function} isEmpty Optional method that determines if the validator is empty or not.
*/
this.nestedValidator = function(node, validator, optional, beforeValidation, isEmpty) {
if (this === validator) {
throw "Cannot nest validator in itself.";
}
var isEmptyFn = isEmpty || function() {
return validator.isFormEmpty();
};
this.nonInputCustom(
node,
function() { return isEmptyFn() ? null : { valid: validator.isValid() }; },
function(value) { return value && value.valid; },
optional,
beforeValidation || function() { validator.clear(); },
isEmptyFn);
};
this.nonInputCustom = function(node, getValuesFn, isValidFn, optional, beforeValidation, isEmpty) {
var registration = {
node: node,
isValidFn: isValidFn,
optional: optional,
getValueFn: getValuesFn,
emptyFn: isEmpty,
beforeValidation: beforeValidation,
maxLength: -1
};
fields.push(registration);
};
this.double = function(node, min, max, maxDecimalPlaces, optional, languageTag) {
var registration = {
node: node,
isValidFn: function(value) {
return Y.scriptlibrary.ValidationHelpers.IsValidDouble(value, min, max, maxDecimalPlaces, languageTag);
},
optional: optional
};
fields.push(registration);
};
this.customField = function(node, validFn, maxLength, optional, onValidation, onMaxLengthCheck) {
var registration = {
node: node,
isValidFn: validFn,
optional: optional,
maxLength: maxLength,
onValidation: onValidation,
onMaxLengthCheck: onMaxLengthCheck
};
fields.push(registration);
};
this.cvv2Code = function(node) {
var registration = {
node: node,
isValidFn: function(value) { return Y.scriptlibrary.ValidationHelpers.anySecretCode(value); }
};
fields.push(registration);
};
this.creditCardSecretCode = function(node, getCardTypeFn, onValidation, existingHiddenValue) {
var registration = {
node: node,
isValidFn: function(value) { return Y.scriptlibrary.ValidationHelpers.IsSecretCodeValid(value, getCardTypeFn()); },
onValidation: onValidation
};
if (existingHiddenValue) {
registration.isValidFn = handleHiddenExistingValue(node, registration.isValidFn);
}
fields.push(registration);
};
this.creditCardField = function(node, getCardTypeFn, onValidation, existingHiddenValue) {
var registration = {
node: node,
isValidFn: function(value) { return Y.scriptlibrary.ValidationHelpers.IsValidCreditCard(value, getCardTypeFn()); },
onValidation: onValidation
};
if (existingHiddenValue) {
registration.isValidFn = handleHiddenExistingValue(node, registration.isValidFn);
}
fields.push(registration);
};
this.acceptCheckbox = function(node) {
var registration = {
node: node,
getValueFn: function(node) { return node.getDOMNode().checked; },
isValidFn: function(value) {return value; },
optional: false
};
fields.push(registration);
};
this.emailField = function(node, maxLength, optional, onValidation, onMaxLengthCheck) {
var registration = {
node: node,
isValidFn: Y.scriptlibrary.ValidationHelpers.IsValidEmail,
optional: optional,
maxLength: maxLength,
onValidation: onValidation,
onMaxLengthCheck: onMaxLengthCheck
};
fields.push(registration);
};
/**
* Email list validator.
* @param {String|Node} node Input node.
* @param {Boolean} optional True if optional.
* @param {Function} onValidation Called when validation occurs.
* @param {String} delimiter Delimiter for splitting the email addresses.
* @param {Boolean} filterOutBlanks True if blank entries can be ignored.
*/
this.emailList = function(node, optional, onValidation, delimiter, filterOutBlanks) {
var listDelimiter = delimiter || ",",
registration = {
node: node,
isValidFn: function(value) {
if (!value) {
return true;
}
var parts = value.split(listDelimiter);
if (filterOutBlanks) {
var newParts = [];
for (var i = 0; i < parts.length; ++i) {
if (parts[i].trim()) {
newParts.push(parts[i]);
}
}
parts = newParts;
}
for (var i = 0; i < parts.length; ++i) {
if (!Y.scriptlibrary.ValidationHelpers.IsValidEmail(parts[i].trim())) {
return false;
}
else if (parts[i].length > SHORT_TEXT) {
return false;
}
}
return true;
},
optional: optional,
onValidation: onValidation
};
fields.push(registration);
this.setFieldOption(node, "maxLength", LONG_TEXT);
};
this.zipField = function(node, maxLength, optional, getCountryFn, onValidation, onMaxLengthCheck) {
var registration = {
node: node,
isValidFn: function(value) { return Y.scriptlibrary.ValidationHelpers.IsValidCode(value, getCountryFn()); },
optional: optional,
maxLength: maxLength,
onValidation: onValidation,
onMaxLengthCheck: onMaxLengthCheck
};
fields.push(registration);
};
this.phoneFieldAnyCountry = function(node, optional) {
var registration = {
node: node,
isValidFn: function(value) { return Y.scriptlibrary.ValidationHelpers.IsPhoneValidAnyCountry(value); },
optional: optional
};
fields.push(registration);
};
/**
* Configures validation on an input to ensure north american phone numbers only.
*
* @param node Current node.
* @param optional True if optional.
*/
this.northAmericanPhone = function(node, optional) {
var registration = {
node: node,
isValidFn: function(value) {return Y.scriptlibrary.ValidationHelpers.IsPhoneValid(value, function() { return "US"; }); },
getValueFn: function(input) {
var value = input.get("value");
if (!value) {
return value;
}
return value.replace(/\D/g,'').trim();
},
optional: optional,
maxLength: 11
};
fields.push(registration);
};
this.phoneField = function(node, maxLength, optional, getCountryFn, onValidation, onMaxLengthCheck) {
var registration = {
node: node,
isValidFn: function(value) { return Y.scriptlibrary.ValidationHelpers.IsPhoneValid(value, getCountryFn()); },
optional: optional,
maxLength: maxLength,
onValidation: onValidation,
onMaxLengthCheck: onMaxLengthCheck
};
fields.push(registration);
};
/**
* Checks whether all the given nodes have valid lengths.
* @param {Node[]} nodes List of nodes.
* @returns {Boolean} True if they all have valid lengths.
*/
this.hasValidLengths = function(nodes) {
for (var i = 0; i < nodes.length; ++i) {
if (!this.hasValidLength(nodes[i])) {
return false;
}
}
return true;
};
/**
* Checks whether the given node has a value that is a valid length.
* @param {Node} node Node to check.
* @returns {Boolean} True if field is valid length.
*/
this.hasValidLength = function(node) {
var field = getFieldByNode(node),
maxLength = field ? field.maxLength || SHORT_TEXT : null;
if (!maxLength) {
return true;
}
var getValueFn = field.getValueFn || defaultGetValueFn,
value = getValueFn(node);
// BUG: string length in JS is the number of utf-16 code units.
// e.g.: '𠜎'.length == 2, despite requiring 4 UTF-8 bytes.
if (Y.Lang.isString(value) || Y.Lang.isArray(value)) {
return maxLength === -1 || value.length <= maxLength;
}
return true;
};
this.partialAddress = function(address1, address2, city, countrySelector, zip, phone) {
this.addressWithCountrySelector(
address1,
address2,
city,
countrySelector,
zip,
null,
true,
null,
true,
null,
true);
};
this.addressWithCountrySelector = function(address1, address2, city, countrySelector, zip, phone, optional, container, phoneOptional, additionalFields, allowPartial) {
this.nonEmptyField(address1, null, optional);
if (address2) {
this.nonEmptyField(address2, null, true);
}
this.nonEmptyField(city, null, optional);
this.countrySelector(countrySelector, optional);
if (additionalFields) {
for (var i = 0; i < additionalFields.length; ++i) {
this.nonEmptyField(additionalFields[i], null, optional);
}
}
this.zipField(zip, null, optional, function() { return countrySelector.getCountry(); });
if (phone) {
this.phoneField(phone, 15, optional || phoneOptional, function() { return countrySelector.getCountry(); });
}
if (optional && !allowPartial) {
this.nonInputCustom(
container,
function() {
var requiredFieldEmpty = false,
oneFieldFilledIn = false,
checkField = function(node, required) {
if (node.getDOMNode().value !== "") {
oneFieldFilledIn = true;
}
else {
requiredFieldEmpty = requiredFieldEmpty || required;
}
};
if (additionalFields) {
for (var i = 0; i < additionalFields.length; ++i) {
checkField(additionalFields[i], true);
}
}
checkField(address1, true);
checkField(address2, false);
checkField(city, true);
checkField(zip, true);
if (phone) {
checkField(phone);
}
if (!countrySelector.isEmpty()) {
oneFieldFilledIn = true;
}
else {
requiredFieldEmpty = requiredFieldEmpty || (!countrySelector.getCountry() && !countrySelector.getState());
}
return { empty: !oneFieldFilledIn, valid: !oneFieldFilledIn || !requiredFieldEmpty };
},
function(result) { return result.valid; },
null,
null,
function(value) { return value.empty; });
}
};
this.removeCountrySelector = function(countrySelector) {
fields = fields.filter(function(field) {
return field.selector !== countrySelector;
});
};
this.countrySelector = function(countrySelector, optional) {
var stateRegistration = {
selector: countrySelector,
nodeFn: function() {
return countrySelector.getCurrentStateInput();
},
emptyFn: function() {
return countrySelector.isEmpty();
},
optional: optional
},
countryRegistration = {
selector: countrySelector,
nodeFn: function() {
return countrySelector.getCountryNode();
},
emptyFn: function() {
return countrySelector.isEmpty();
},
optional: optional
};
fields.push(stateRegistration);
fields.push(countryRegistration);
};
this.address = function(address1, address2, city, state, country, zip, phone) {
this.nonEmptyField(address1);
if (address2) {
this.nonEmptyField(address2, null, true);
}
this.nonEmptyField(city, null);
this.nonEmptyField(state, null);
this.nonEmptyField(country, null);
this.zipField(zip, null, true, function() { return Y.one(country).getDOMNode().value; });
if (phone) {
this.phoneField(phone, 15, true, function() { return Y.one(country).getDOMNode().value; });
}
};
/**
* Removes date picker from the validator.
* @param {scriptlibrary.DatePicker} datePicker Date picker to remove.
*/
this.removeDate = function(datePicker) {
this.remove(datePicker.getDisplayNode());
};
/**
* Removes time picker from the validator.
* @param {scriptlibrary.TimePicker} timePicker Time picker to remove.
*/
this.removeTime = function(timePicker) {
this.remove(timePicker.getContainer());
};
this.date = function(datePicker, timePicker, optional) {
var getValueFn = function() {
return datePicker.getInputNode() ? datePicker.getInputNode().get("value") : datePicker.getDisplayNode().get("text");
},
registration = {
node: datePicker.validationNode(),
getValueFn: getValueFn,
optional: function() { return optional && (!timePicker || timePicker.isEmpty()); }
};
fields.push(registration);
};
this.time = function(timePicker, datePicker, optional) {
var registration = {
node: timePicker.getContainer(),
beforeValidation: function() { timePicker.clearError(); },
getValueFn: function() { return timePicker.getTime(); },
emptyFn: function() { return timePicker.isEmpty(); },
isValidFn: function(value, silent) { return timePicker.isValid(datePicker && datePicker.isEmpty(), silent); },
optional: function() { return datePicker && datePicker.isEmpty() || optional; }
};
fields.push(registration);
};
this.password = function(node, confirmNode, canBeEmpty) {
var firstInput = Y.one(node),
secondInput = Y.one(confirmNode),
registration = {
node: node,
isValidFn: function(value) {
return secondInput.getDOMNode().value === value;
},
optional: canBeEmpty
},
confirmRegistration = {
node: confirmNode,
isValidFn: function(value) {
return firstInput.getDOMNode().value === value;
},
optional: canBeEmpty
};
fields.push(registration);
fields.push(confirmRegistration);
};
this.strongPassword = function(node, confirmNode, canBeEmpty, callback) {
var firstInput = Y.one(node),
secondInput = Y.one(confirmNode),
registration = {
node: node,
beforeValidation: function () {
var validationResult = Y.scriptlibrary.ValidationHelpers.ValidatePassword(firstInput.getDOMNode().value, secondInput.getDOMNode().value, canBeEmpty);
callback(validationResult);
},
isValidFn: function() {
return Y.scriptlibrary.ValidationHelpers.ValidatePassword(firstInput.getDOMNode().value, secondInput.getDOMNode().value, canBeEmpty).valid;
},
optional: canBeEmpty
};
confirmRegistration = {
node: confirmNode,
beforeValidation: function () {
var validationResult = Y.scriptlibrary.ValidationHelpers.ValidatePassword(firstInput.getDOMNode().value, secondInput.getDOMNode().value, canBeEmpty);
callback(validationResult);
},
isValidFn: function() {
return Y.scriptlibrary.ValidationHelpers.ValidatePassword(firstInput.getDOMNode().value, secondInput.getDOMNode().value, canBeEmpty).valid;
},
optional: canBeEmpty
};
fields.push(registration);
fields.push(confirmRegistration);
};
this.gpsCoordinates = function(latitude, longitude, onValidation, required) {
var latRegistration,
longRegistration,
latValid = false;
latRegistration = {
node: latitude,
isValidFn: Y.scriptlibrary.ValidationHelpers.IsLatitude,
onValidation: function(value) {
latValid = value;
if (onValidation) {
onValidation(value);
}
},
optional: function() { return inputIsEmpty(longRegistration) && !required; }
};
longRegistration = {
node: longitude,
isValidFn: Y.scriptlibrary.ValidationHelpers.IsLongitude,
onValidation: function(value) {
if (onValidation) {
onValidation(value && latValid);
}
},
optional: function() { return inputIsEmpty(latRegistration); }
};
fields.push(latRegistration);
fields.push(longRegistration);
};
/**
* Validates a file input's file extension.
* @param {DOMNode} node The node to validate the value of.
* @param {array} validExtensions An array of valid file extensions.
* @param {boolean} optional True if the input can be empty.
*/
this.fileExtension = function(node, validExtensions, optional) {
var validExtensionHashTable = {};
for (var i = validExtensions.length - 1; i >= 0; i--) {
validExtensionHashTable[validExtensions[i]] = true;
}
var registration = {
node: node,
isValidFn: function(fileName) {
var extension = fileName.substring(fileName.lastIndexOf(".") + 1);
return (true === validExtensionHashTable[extension.toLowerCase()]);
},
optional: optional
};
fields.push(registration);
};
this.attachErrorMessage = function(node, errorMessageSelector) {
var errorNode = Y.one(errorMessageSelector);
this.setFieldOption(node, "onValidation", function(valid) {
if (valid) {
errorNode.hide();
}
else {
errorNode.show();
}
});
};
this.remove = function(node) {
fields = fields.filter(function(field) {
var fieldNode = getNode(field);
return Y.one(node).getDOMNode() !== Y.one(fieldNode).getDOMNode();
});
};
Y.scriptlibrary = Y.scriptlibrary || {};
Y.scriptlibrary.Validator = Validator;
};
Y.scriptlibrary = Y.scriptlibrary || {};
Y.scriptlibrary.Validator = Validator;
}, '0.0.1', {
requires: ["yui-base", "node", "event", "scriptlibrary.ValidationHelpers", "scriptlibrary.StringExtensions"]
});YUI().add("arrangement.TributeDirectionsController", function (Y) {
"use strict";
var attributeConfig = function() {
return {
view: {
value: null
},
request: {
value: null
},
contextPath: {
value: null,
validator: Y.Lang.isString
},
eventId: {
value: null
},
eventSource: {
value: null
},
deliveryMode: {}
};
};
var ErrorHandlers = Y.scriptlibrary.ErrorHandlers,
Validator = Y.scriptlibrary.Validator,
Request = Y.scriptlibrary.Request,
DynamicWindow = Y.scriptlibrary.DynamicWindow;
var TributeDirectionsController = function(parameters) {
this.addAttrs(attributeConfig(), parameters);
var me = this,
configurationData = me.get("request").get("data"),
container = Y.one(this.get("view").getContainer()),
recipientInput = container.one(".recipient-input"),
captchaImage = container.one(".captcha-image"),
refreshButton = container.one(".refresh-captcha"),
captchaInput = container.one(".guess"),
sendButton = container.one(".send-directions"),
directionsContainer = container.one(".tribute-directions-panel-container"),
closeWindowButton = container.one(".close-window"),
directionsSentPage = container.one(".directions-sent-container"),
recipientError = container.one(".recipient-error"),
sendDirectionsError = container.one(".send-directions-error"),
contextPath = me.get("contextPath"),
mode = me.get("deliveryMode"),
captchaSequenceNumber = 0,
audioCaptcha = new Y.scriptlibrary.input.AudioCaptcha({
resources: {},
resourceName: "DIRECTIONS",
contextPath: contextPath,
sequenceNumber: 0
}),
validator = new Validator();
var sendDirections = function() {
recipientError.hide();
if (!validator.isValid()) {
recipientError.show();
return;
}
if (mode === "email") {
sendDirectionsByEmail();
}
else {
sendDirectionsByText();
}
};
var sendDirectionsByText = function() {
var data = {
eventId: me.get("eventId"),
eventSource: me.get("eventSource"),
phoneNumber: recipientInput.get("value")
};
sendButton.set("disabled", true);
new Request(contextPath + "/tribute/text-directions.html")
.postJson(data)
.then(Request.processCmsResult)
.then(function() {
sendButton.set("disabled", false);
showNextPage();
})
.then(undefined, function(e) {
sendButton.set("disabled", false);
ErrorHandlers.handleErrorInNode(sendDirectionsError, "Unexpected error")(e);
});
};
var sendDirectionsByEmail = function() {
var emails = Y.Array.map(recipientInput.get("value").split(","), function(email) {
return email.trim();
});
var data = {
guess: captchaInput.get("value"),
captchaSequenceNumber: captchaSequenceNumber,
eventId: me.get("eventId"),
eventSource: me.get("eventSource"),
emails: emails
};
new Request(contextPath + "/tribute/email-directions.html")
.postJson(data)
.then(Request.processCmsResult)
.then(showNextPage)
.then(undefined, ErrorHandlers.handleErrorInNode(
sendDirectionsError,
"Unexpected error",
refreshCaptcha));
};
var showNextPage = function() {
directionsContainer.hide();
directionsSentPage.show();
};
var refreshCaptcha = function(e) {
e.preventDefault();
++captchaSequenceNumber;
var url = contextPath + "/captcha.html"
+ "?resourceName=" + configurationData.captchaResourceName
+ "&sequenceNumber=" + captchaSequenceNumber
+ "&rand=" + Math.random();
captchaImage.setAttribute("src", url);
audioCaptcha.set("sequenceNumber", captchaSequenceNumber);
};
var initialize = function() {
container.show();
if (mode === "email") {
directionsContainer.one(".captcha-row").show();
directionsContainer.one(".captcha-info").show();
validator.emailList(recipientInput);
}
else {
validator.northAmericanPhone(recipientInput);
directionsContainer.one(".captcha-row").hide();
directionsContainer.one(".captcha-info").hide();
}
sendButton.on("click", sendDirections);
refreshButton.on("click", refreshCaptcha);
closeWindowButton.on("click", function() { container.hide() });
audioCaptcha.render(container.one(".captcha-row"));
};
initialize();
};
Y.augment(TributeDirectionsController, Y.Attribute);
Y.arrangement = Y.arrangement || {};
Y.arrangement.TributeDirectionsController = TributeDirectionsController;
});
YUI().add("scriptlibrary.NodeExtensions", function (Y) {
var parseToInt = function(dimension) {
if (!dimension) {
return 0;
}
return parseInt(dimension.replace("px", ""), 10);
};
/**
* Gets the width of the item on the screen.
*/
Y.Node.prototype.getClientWidth = function () {
var element = this.getDOMNode();
return element.clientWidth || element.scrollWidth;
};
/**
* Gets the height of the item on the screen.
*/
Y.Node.prototype.getClientHeight = function () {
var element = this.getDOMNode();
return element.clientHeight || element.scrollHeight;
};
/**
* Parses a style with a value in pixels and returns the numeric property.
* @param {String} styleProperty Name of the style property e.g. paddingLeft, paddingTop, marginLeft.
* @returns {Number} Numerical value of that style property.
*/
Y.Node.prototype.parseStylePx = function(styleProperty) {
var computed = this.getComputedStyle(styleProperty);
return computed
? parseInt(computed.replace("px", ""), 10)
: 0;
};
/**
* Gets the horizontal spacing.
* @returns {Number} Horizontal spacing in pixels.
*/
Y.Node.prototype.getHorizontalSpacing = function() {
var padding = this.parseStylePx("paddingLeft") + this.parseStylePx("paddingRight"),
margin = this.parseStylePx("marginLeft") + this.parseStylePx("marginRight"),
border = this.parseStylePx("borderWidth") / 2;
return padding + margin + border;
};
/**
* Gets the vertical spacing.
* @returns {Number} Vertical spacing in pixels.
*/
Y.Node.prototype.getVerticalSpacing = function() {
var padding = this.parseStylePx("paddingTop") + this.parseStylePx("paddingBottom"),
margin = this.parseStylePx("marginTop") + this.parseStylePx("marginBottom"),
border = this.parseStylePx("borderWidth") / 2;
return padding + margin + border;
};
});var allWindows = [];
YUI().add("scriptlibrary.DynamicWindow", function (Y) {
var elSetter = function (val) {
if (Y.Lang.isString(val)){
return Y.one(val);
}
return val;
},
elValidator = function (val) {return Y.Lang.isObject(val) || Y.Lang.isString(val);};
function getAttributeConfig() {
return {
id: {
value: null,
validator: Y.Lang.isString
},
containerCss: {
value: null,
validator: Y.Lang.isString
},
viewContainer: {
value: null,
validator: elValidator,
setter: elSetter
},
top: {
value: 100,
validator: Y.Lang.isNumber
},
width: {
value: null,
validator: Y.Lang.isNumber
},
height: {
value: null,
validator: Y.Lang.isNumber
},
zIndex: {
value: null,
validator: Y.Lang.isNumber
},
maskZIndex: {
value: null,
validator: Y.Lang.isNumber
},
hideCloseButton: {
value: false,
validator: Y.Lang.isBoolean
},
maskCss: {
value: null,
validator: Y.Lang.isString
},
container: { value: null },
positionManually: { value: false }
};
}
function DynamicWindow(config){
this.addAttrs(getAttributeConfig(), config);
initializeMembers.call(this);
allWindows.push(this);
}
DynamicWindow.CloseAllWindows = function () {
for (var i = 0; i < allWindows.length; ++i) {
allWindows[i].hide();
}
};
function updateEmbeddedContent() {
for (var i = 0; i < allWindows.length; ++i) {
if (allWindows[i].isVisible()) {
return;
}
}
showEmbeddedContent();
}
function hideEmbeddedContent() {
Y.all("iframe.video-display").each(function(node) { node.getDOMNode().style.visibility = "hidden"; });
}
function showEmbeddedContent() {
Y.all("iframe.video-display").each(function(node) { node.getDOMNode().style.visibility = ""; });
}
var initializeMembers = function() {
var me = this,
onHideHandlers = [],
container,
closeButton,
content,
mask,
positionWindow = function () {
var viewPortWidth = document.body.clientWidth || document.body.scrollWidth,
left = Math.round((viewPortWidth - me.get("width"))/2);
container.style.left = left + "px";
if (!me.get("positionManually")) {
updateY();
}
},
setInitialYPosition = function() {
var doc = document.documentElement,
body = document.body,
scrollTop = (doc && doc.scrollTop || body && body.scrollTop || 0),
top = (doc && doc.scrollTop || body && body.scrollTop || 0);
container.style.top = (top + scrollTop) + "px";
},
showMask = function () {
updateMask();
mask.style.display = "";
},
updateMask = function () {
var winHeight = Y.one("body").get("winHeight"),
bodyHeight = Y.one("body").get("docHeight"),
maskHeight = Math.max(winHeight, bodyHeight);
mask.style.height = maskHeight + "px";
},
updateY = function() {
var winHeight = Y.one("body").get("winHeight"),
containerHeight = Y.one(container).getClientHeight(),
doc = document.documentElement,
body = document.body,
scrollTop = (doc && doc.scrollTop || body && body.scrollTop || 0),
top = me.get("top");
if (winHeight < containerHeight) {
return;
}
else if (winHeight < (containerHeight + top * 2)) {
top = Math.round((winHeight - containerHeight)/2);
top = Math.max(0, top);
}
container.style.top = (top + scrollTop) + "px";
},
initializeDom = function () {
container = document.createElement("DIV");
var zIndex = me.get("zIndex"),
id = me.get("id"),
height = me.get("height"),
width = me.get("width"),
containerCss = me.get("containerCss");
if (width) {
container.style.width = width + "px";
}
if (id) {
container.id = id;
}
if (containerCss) {
container.className = "popup-container " + containerCss;
}
else {
container.className = "popup-container";
}
if (zIndex) {
container.style.zIndex = zIndex;
}
if (height) {
container.style.height = height + "px";
}
if (!me.get("hideCloseButton")) {
closeButton = document.createElement("DIV");
closeButton.className = "close-button";
closeButton.innerHTML = "X";
container.appendChild(closeButton);
}
content = document.createElement("DIV");
content.className = "content";
container.appendChild(content);
mask = document.createElement("DIV");
var maskCss = "mask",
maskCssSuffix = me.get("maskCss");
if (maskCssSuffix) {
maskCss += " " + maskCssSuffix;
}
mask.className = maskCss;
if (me.get("maskZIndex")) {
mask.style.zIndex = me.get("maskZIndex");
}
var viewContainer = me.get("viewContainer");
viewContainer.appendChild(container);
viewContainer.appendChild(mask);
if (closeButton) {
Y.on("click", function () { me.hide(); }, closeButton);
}
},
executeScriptBlocks = function (request) {
var scriptBlocks = Y.one(container).all("script"),
executeBlock = function (node){
if (node.getAttribute("type") === "text/javascript") {
var fn = eval(node.getHTML());
fn(me, request);
}
};
scriptBlocks.each(executeBlock);
};
Y.one("window").on("resize", function () {
if (mask && mask.style.display == ""){
updateMask();
if (!me.get("positionManually")) {
positionWindow();
}
}
});
Y.one("window").on("scroll", function() {
if (container && container.style.display !== "none" && !me.get("positionManually")) {
updateY();
}
});
this.onHide = function (fn, scope, clearOnHide){
onHideHandlers.push({ fn: fn, scope: scope, clearOnHide: clearOnHide });
};
this.isVisible = function() {
return container && container.style.display !== "none";
};
this.hide = function () {
if (!container) {
return;
}
Y.one(container).remove(true);
Y.one(mask).remove(true);
container = null;
content = null;
mask = null;
var newHideHandlers = [];
for (var i = 0; i < onHideHandlers.length; ++i){
onHideHandlers[i].fn.call(onHideHandlers[i].scope);
if (!onHideHandlers[i].clearOnHide){
newHideHandlers.push(onHideHandlers[i]);
}
}
onHideHandlers = newHideHandlers;
updateEmbeddedContent();
};
this.setWidth = function(width) {
this.set("width", width);
container.style.width = width + "px";
if (!me.get("positionManually")) {
positionWindow();
}
},
this.updateWindowPosition = function() {
updateY();
};
this.listenTo = function (dataRequest) {
dataRequest.addHtmlHandler(function (html) {this.render(html, dataRequest);}, this);
// NOTE: This could cause an issue if there are multiple windows listening to the data requests. As long
// as only one window is open at a time, this should not be an issue.
this.onHide(function () { dataRequest.resetUrl(); }, this);
};
this.getContainer = function() {
return container;
};
this.getContent = function() {
return content;
};
/**
* Renders the given html in the popup.
* @param {string} popupHtml Html to render in the popup.
* @param {object} data Data.
* @param {object[]} [resources] Additional resources to include in the data.
* @param {function} [scriptFn] Function to call afterwards.
*/
this.renderTemplate = function(popupHtml, data, resources, scriptFn) {
var templateHtml =
'
' +
'
' +
'
{{popupTitle}}
' +
'
' + popupHtml + '
' +
'' +
'
' +
'',
template = new Y.Template(Y.Handlebars);
data.id = data.id || "";
Y.Array.each(resources || [], function(resource) {
Y.Object.each(resource, function(value, key) {
if (!data[key]) {
data[key] = value;
}
});
});
this.render(template.render(templateHtml, data));
if (scriptFn) {
scriptFn(me);
}
};
this.render = function(html, request){
if (!content) {
initializeDom();
}
Y.one(content).empty();
content.innerHTML = html;
var redirectElement = Y.one(content).one("*[data-dynamic-window-redirect]");
if (redirectElement) {
window.location = redirectElement.getAttribute("data-dynamic-window-redirect");
return;
}
if (!me.get("positionManually")) {
setInitialYPosition();
positionWindow();
}
showMask();
if (request) {
executeScriptBlocks(request);
}
hideEmbeddedContent();
container.style.display = "";
};
};
var waitMessagePopup,
confirmationPopup;
/**
* Shows a wait message in a modal popup.
* @param {String} title Please wait message title.
* @param {String} message Message to display.
*/
DynamicWindow.ShowWaitMessage = function (title, message) {
if (!waitMessagePopup) {
waitMessagePopup = new DynamicWindow({ id: "global-wait-popup", viewContainer: "#popup-container", width: 400, hideCloseButton: true, zIndex: 100000, maskZIndex: 99999 });
}
var html = "
" + title + "
";
html += "
" + message + "
";
waitMessagePopup.render(html);
};
/**
* Hides the wait message popup.
*/
DynamicWindow.HideWaitMessage = function () {
if (waitMessagePopup) {
waitMessagePopup.hide();
}
};
/**
* Shows a confirmation message
* @param {string} message
*/
DynamicWindow.ShowCompletedMessage = function (message, buttonLabel, zIndex) {
DynamicWindow.HideWaitMessage();
if (!confirmationPopup) {
var maskZIndex = zIndex ? zIndex - 1 : null;
confirmationPopup = new DynamicWindow({ id: "global-complete-popup", viewContainer: "#popup-container", width: 400, zIndex: zIndex, maskZIndex: maskZIndex });
}
var html = "
";
html += "
" + message + "
";
confirmationPopup.render(html);
Y.one("#global-complete-ok").on("click", function () { confirmationPopup.hide(); });
};
/**
* Gets a prompt displaying the given options.
* @param {String} message Message to display.
* @param {object[]} options List of option objects which have the format { label: "My Label", fn: function() {} }.
* @param {type} [zIndex] z-index of window.
* @param {int} [width] Window width.
* @param {string} [id] Dynamic Window id.
* @param {boolean} [positionManually=false] true if a position should not be automatically set.
* @returns {_L2.DynamicWindow} Dynamic window created.
*/
DynamicWindow.promptWithOptions = function(message, options, zIndex, width, id, positionManually) {
var html = "
";
var prompt = new DynamicWindow({
id: id || "global-prompt-popup",
viewContainer: "#popup-container",
width: width || 400,
hideCloseButton: true,
zIndex: zIndex,
maskZIndex: zIndex - 1,
positionManually: positionManually || false
});
html += "
";
prompt.render(html);
var container = Y.one(prompt.getContainer()),
optionContainer = container.one(".prompt-with-options-container");
container.one(".prompt-message").set("text", message);
for (var i = 0; i < options.length; ++i) {
var button = Y.Node.create("");
button.set("value", options[i].label);
if (options[i].fn) {
button.on("click", options[i].fn);
}
button.on("click", function() { prompt.hide(); });
optionContainer.appendChild(button);
}
return prompt;
};
DynamicWindow.ShowPrompt = function(message, option1Label, option2Label, option1Fn, option2Fn) {
var option1Id = "option1-button",
option2Id = "option2-button",
html = "
",
prompt = new DynamicWindow({ id: "global-prompt-popup", viewContainer: "#popup-container", width: 400, hideCloseButton: true });
html += "