home *** CD-ROM | disk | FTP | other *** search
/ developer.apple.com / developer.apple.com.tar / developer.apple.com / global / scripts / ac_media.js next >
Text File  |  2010-06-09  |  150KB  |  4,413 lines

  1. // = Apple Gracefully Degrading Media Playback =
  2. //
  3. // This script provides functionality for both creating video players
  4. // that will use modern technology if possible, but fall back on QuickTime.
  5. //
  6. // Part of the functionality included herein is also video controls similar 
  7. // to those in Show Leopard's QuickTime X Player.
  8. //
  9.  
  10. /*jsl:ignoreall*/
  11.  
  12. var existingVideo = false,
  13.     existingVideoSrc = false,
  14.     playExistingVideo = false,
  15.     ac_media_language = false;
  16.  
  17. var MediaLanguage = {
  18.     translationDictionary: {
  19.         "en": "en.json",
  20.         "en-US": "en-US.json",
  21.         "en-CA": "en-CA.json",
  22.         "en-KR": "en-KR.json",
  23.         "es": "es.json",
  24.         "es-LA": "es-LA.json",
  25.         "es-MX": "es-MX.json",
  26.         "fr": "fr.json",
  27.         "fr-CA": "fr-CA.json",
  28.         "ja": "ja.json",
  29.         "ja-JP": "ja-JP.json",
  30.         "pt": "pt.json",
  31.         "pt-BR": "pt-BR.json",
  32.         "zh": "zh.json",
  33.         "zh-CN": "zh-CN.json",
  34.         "zh-HK": "zh-HK.json",
  35.         "zh-TW": "zh-TW.json"
  36.     },
  37.     
  38.     getLangFromAttr: function(attr) {
  39.         if(!attr) {
  40.             return 'en-US';
  41.         }
  42.         switch (attr.toLowerCase()) {
  43.             case 'en-us':
  44.                 return 'en-US';
  45.             case 'en-ca':
  46.                 return 'en-CA';
  47.             case 'en-kr':
  48.                 return 'en-KR';
  49.             case 'ja-jp':
  50.                 return 'ja-JP';
  51.             case 'pt':
  52.             case 'pt-br':
  53.                 return 'pt-BR';
  54.             case 'es-419':
  55.             case 'es-la':
  56.                 return 'es-LA';
  57.             case 'es-mx':
  58.                 return 'es-MX';
  59.             case 'fr-ca':
  60.                 return 'fr-CA';
  61.             case 'ja-jp':
  62.                 return 'ja-JP';
  63.             case 'zh-cn':
  64.                 return 'zh-CN';
  65.             case 'zh-hk':
  66.                 return 'zh-HK';
  67.             case 'zh-tw':
  68.                 return 'zh-TW';
  69.             default:
  70.                 return attr;
  71.         }
  72.     },
  73.     
  74.     getTranslations: function() {
  75.         var html = document.getElementsByTagName('html').item(0),
  76.             langAttr = html.getAttribute('lang'),
  77.             lang = this.getLangFromAttr(langAttr),
  78.             langFile = this.langDictionary(lang);
  79.  
  80.  
  81.         new Ajax.Request('/global/scripts/ac_media_languages/'+langFile, {
  82.             method:'get',
  83.             requestHeaders: {Accept: 'application/json'},
  84.             onSuccess: function(transport){
  85.                 ac_media_language = new Function("return "+transport.responseText)();
  86.                 //func.call(((self) ? self : window),json);
  87.             }.bind(this),
  88.             evalJS: false
  89.         });
  90.     },
  91.     
  92.     langDictionary: function(locale) {
  93.         var language = locale.toLowerCase().split('-')[0],
  94.             localeInfo = this.translationDictionary[locale] || false;
  95.  
  96.         if (!localeInfo) {
  97.             localeInfo = this.translationDictionary[language];
  98.         }
  99.         if (!localeInfo) {
  100.             localeInfo = this.translationDictionary['en'];
  101.         }
  102.  
  103.         return localeInfo;
  104.     }
  105. };
  106.  
  107. MediaLanguage.getTranslations();
  108.  
  109. var Media = {
  110.     VERSION: '3.5',
  111.     MIN_QUICKTIME_VERSION: '7.4',
  112.     CAPTIONS_NS: 'http://www.w3.org/2006/04/ttaf1',
  113.  
  114.     create: function(container, src, options) {
  115.         var element, innerface, controls, controller, 
  116.             shouldBuildMediaSpecVideo = true, 
  117.             shouldBuildMediaSpecQuickTime = true,
  118.             shouldBuildMediaSpecSBVDP = true,
  119.             ipad = AC.Detector.isiPad();
  120.        
  121.         // Do some browser-specific setup
  122.         switch(true) {
  123.             case Media.Detection.Firefox():
  124.                 Element.addClassName(container, 'mozilla');
  125.                 break;
  126.             case Media.Detection.Opera():
  127.                 Element.addClassName(container, 'opera');
  128.                 break;
  129.             case Media.Detection.IE():
  130.                 Media._createEventSource();
  131.                 break;
  132.             default:
  133.                 break;
  134.         }
  135.         if (options.target === 'quicktimeplayer') {
  136.             options.spec = 'qt';
  137.         }
  138.  
  139.         if (options.spec) {
  140.             switch(options.spec) {
  141.                 case 'qt':
  142.                     shouldBuildMediaSpecVideo = false;
  143.                     shouldBuildMediaSpecSBVDP = false;
  144.                     break;
  145.                 case 'video': case 'audio':
  146.                     shouldBuildMediaSpecQuickTime = false;
  147.                     shouldBuildMediaSpecSBVDP = false;
  148.                     break;
  149.                 case 'sbvdp':
  150.                     shouldBuildMediaSpecVideo = false;
  151.                     shouldBuildMediaSpecQuickTime = false;
  152.                     break;
  153.                 default:
  154.                     break;
  155.             }
  156.         }
  157.  
  158.         var iPhoneOSVersion = (Media.Detection.Mobile()) ? Media.Detection.iPhoneOSVersion() : null;
  159.  
  160.         if (iPhoneOSVersion && iPhoneOSVersion[0] < 3) {
  161.             shouldBuildMediaSpecVideo = false;
  162.             shouldBuildMediaSpecQuickTime = true;
  163.         }
  164.  
  165.         switch(true) {
  166.             case (ipad || (shouldBuildMediaSpecVideo && Media._isHTML5VideoAvailable() && !Media.Detection.Firefox() && !Media.Detection.Mobile() && !Media.Detection.Chrome() && !Media.Detection.Opera() && !!(Media.Detection.Safari() && Media.Detection.SnowLeopard()))):
  167.                 // Create <video> player
  168.                 if(options.audio == true && typeof Media.Spec.Audio !== undefined) {
  169.                     return build(Media.Spec.Audio);
  170.                 }
  171.                 return build(Media.Spec.Video);
  172.                 break;
  173.             case (shouldBuildMediaSpecQuickTime && Media._isQuickTimeAvailable(Media.MIN_QUICKTIME_VERSION)):
  174.             case Media.Detection.Mobile():
  175.                 // Create QuickTime player
  176.                 return build(Media.Spec.QuickTime);
  177.                 break;
  178.             case (shouldBuildMediaSpecSBVDP && Media._isSBVDPAvailable(Media.MIN_SBVDP_VERSION)):
  179.                 // Create SBVDP player
  180.                 return build(Media.Spec.SBVDP);
  181.                 break;
  182.             case Media._shouldShowDownloadPrompt():
  183.             default:
  184.                 // At this point we've determined there will be no video, 
  185.                 // so show a download prompt if we need to, then return false;
  186.                 Media.createDownloadPrompt(container, src, options);
  187.                 break;
  188.         }
  189.         
  190.         function build(Spec) {
  191.     
  192.             // First, create a new controller...
  193.             controller = Media.Controller(container);
  194.  
  195.             // ...then a video player (with a corresponding video interface)...
  196.             element = Spec.create(container, src, options);
  197.             innerface = Media.VideoInterface(element, controller);
  198.  
  199.  
  200.  
  201.             
  202.             //Got to fake autolay for iPad:
  203.             if(ipad && (options.autoplay === true || options.autostart === true)) {
  204.                 //element.forcePlay();
  205.                 // alert("ipad = "+ipad+", options.autoplay = "+options.autoplay+", options.autostart = "+options.autostart);
  206.                 // var link = document.createElement("a"),
  207.                 //     forcePlay = function(event) {
  208.                 //         event.preventDefault();
  209.                 //         element.play();
  210.                 //     },
  211.                 //     triggerEvent;
  212.                 //     link.addEventListener("click",forcePlay,false);
  213.                 //     document.body.appendChild(link);
  214.                 //     triggerEvent = document.createEvent("MouseEvents");
  215.                 //     if (triggerEvent.initMouseEvent) {
  216.                 //         triggerEvent.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
  217.                 //         link.dispatchEvent(triggerEvent);
  218.                 //     }
  219.                 //     document.body.removeChild(link);
  220.                 // 
  221.             }
  222.  
  223.             // Now, customize the interface with events and/or polling, and custom methods.
  224.             var eventsToRegister = Spec.eventsToRegister;
  225.             for (var event in eventsToRegister) {
  226.                 var name = eventsToRegister[event].name || eventsToRegister[event],
  227.                     fn = eventsToRegister[event].callback;
  228.                 
  229.                 innerface.registerEvent(event, name, fn);
  230.             }
  231.             
  232.             if (Spec.pollForChanges) {
  233.                 innerface.pollForChanges(Spec.pollForChanges);
  234.             }
  235.                 
  236.             if (Spec.interfaceMethods) {
  237.                 innerface.override(Spec.interfaceMethods);
  238.             }
  239.  
  240.             innerface.setup();
  241.             
  242.             // Finally, attach the video interface to the controller
  243.             controller.setVideo(innerface);
  244.             controller.setVideoSrc(src);
  245.             //controller.configureSettingsControls(src);
  246.  
  247.             controller.container = container;
  248.             controller.movieLoadingPanelClass = 'movie-loading-panel';
  249.             if (typeof options.width != 'undefined' && typeof options.height != 'undefined') {
  250.                 if (typeof controller.currentWidth == 'undefined' && typeof controller.currentHeight == 'undefined') {
  251.                     controller.currentWidth = options.width;
  252.                     controller.currentHeight = options.height;
  253.                 }
  254.                 controller.movieLoadingPanelClass = 'movie-loading-panel_' + options.width + 'x' + options.height;
  255.             }
  256.             Element.addClassName(container, controller.movieLoadingPanelClass);
  257.             
  258.             return controller;
  259.         }
  260.         
  261.         return false;
  262.     },    
  263.     
  264.     createDownloadPrompt: function (container, src, options)
  265.     {
  266.         Element2.Methods.removeAllChildNodes(container);
  267.     
  268.         var downloadNotice = document.createElement('a'),
  269.             downloadNoticeTitle = document.createElement('span'),
  270.             downloadNoticeText = document.createElement('span'),
  271.             downloadNoticeButton = document.createElement('span'),
  272.             downloadNoticeUrl = options.downloadUrl || ac_media_language.downloadquicktimeurl || 'http://www.apple.com/quicktime/download/';
  273.  
  274.         Element.addClassName(downloadNotice, 'quicktime-download');
  275.         if (typeof options.width !== 'undefined' && typeof options.height !== 'undefined') {
  276.             Element.addClassName(downloadNotice, 'size' + options.width + 'x' + options.height);
  277.         }
  278.  
  279.         downloadNotice.setAttribute('href', downloadNoticeUrl);
  280.         
  281.         Element.addClassName(downloadNoticeTitle, 'quicktime-download-title');
  282.         Element.addClassName(downloadNoticeText, 'quicktime-download-text');
  283.         Element.addClassName(downloadNoticeButton, 'quicktime-download-button');
  284.         
  285.         downloadNoticeTitle.innerHTML = options.downloadTitle || ac_media_language.downloadquicktimetitle || 'Get QuickTime.';
  286.         downloadNoticeText.innerHTML = options.downloadText || ac_media_language.downloadquicktimetext || 'Download QuickTime to view this video.<br />QuickTime is free for Mac + PC.';
  287.         downloadNoticeButton.innerHTML = options.downloadButton || ac_media_language.downloadquicktimebutton || 'Download';
  288.         
  289.         downloadNotice.appendChild(downloadNoticeTitle);
  290.         downloadNotice.appendChild(downloadNoticeText);
  291.         downloadNotice.appendChild(downloadNoticeButton);
  292.  
  293.         container.appendChild(downloadNotice);
  294.  
  295.         if ('fire' in Element) {
  296.             Element.fire(document.body, 
  297.                 "QuickTime:noCompatibleQTAvailable", 
  298.                 {controller: this, minVersion: Media.MIN_QUICKTIME_VERSION});
  299.         }
  300.         
  301.         return downloadNotice;
  302.     },
  303.     
  304.     _isHTML5VideoAvailable: function ()
  305.     {
  306.         return Media.Detection.HTML5();
  307.     },
  308.     
  309.     _isQuickTimeAvailable: function ()
  310.     {
  311.        return Media.Detection.QuickTime(Media.MIN_QUICKTIME_VERSION);
  312.     },
  313.     
  314.     _isSBVDPAvailable: function ()
  315.     {
  316.         return Media.Detection.SBVDP(Media.MIN_SBVDP_VERSION);
  317.     },
  318.     
  319.     _shouldShowDownloadPrompt: function ()
  320.     {
  321.         return !Media.Detection.Mobile();
  322.     },
  323.     
  324.     _createEventSource: function()
  325.     {
  326.         var source_id = "qt_event_source",
  327.             behavior,
  328.             head;
  329.  
  330.         // Don't recreate it if we already have one by this id
  331.         if (document.getElementById(source_id)) {
  332.             return;
  333.         }
  334.  
  335.         behavior = document.createElement('object');
  336.         behavior.id = source_id;
  337.         behavior.setAttribute('clsid', 'CB927D12-4FF7-4a9e-A169-56E4B8A75598');
  338.  
  339.         head = document.getElementsByTagName('head')[0];
  340.         head.appendChild(behavior);
  341.     }
  342. };
  343.  
  344. Media.Detection = {
  345.     HTML5: function () {
  346.         if (!('HTMLMediaElement' in window)){
  347.             return false;
  348.         }
  349.         
  350.         var video = document.createElement('video');
  351.         return (video.canPlayType && video.canPlayType('video/mp4')!=='');
  352.     },
  353.     QuickTime: function(version) {
  354.         return AC.Detector.isValidQTAvailable(version);
  355.     },
  356.     SBVDP: function(version) {
  357.         return AC.Detector.isSBVDPAvailable(version);
  358.     },
  359.     Mobile: function () {
  360.         return (AC.Detector.isiPad()) ? true : AC.Detector.isMobile();
  361.     },
  362.     iPhoneOSVersion: function() {
  363.         return AC.Detector.iPhoneOSVersion();
  364.     },
  365.     iPad: function () {
  366.         return AC.Detector.isiPad();
  367.     },
  368.     Safari: function () {
  369.         return AC.Detector.isSafari2();
  370.     },
  371.     IE: function () {
  372.         return AC.Detector.isIEStrict();
  373.     },
  374.     Firefox: function () {
  375.         return AC.Detector.isFirefox();
  376.     },
  377.     Opera: function () {
  378.         return AC.Detector.isOpera();
  379.     },
  380.     Chrome: function () {
  381.         return AC.Detector.isChrome();
  382.     },
  383.     SnowLeopard: function () {
  384.         return AC.Detector.isSnowLeopard();
  385.     },
  386.     SnowLeopard1062: function () {
  387.         var agent = AC.Detector.getAgent(),
  388.             match = agent.match(/mac\sos\sx\D*([\.\w]*)/i),
  389.             version = false;
  390.  
  391.         if (match && match[1]) {
  392.             version = match[1];
  393.         }
  394.  
  395.         return (AC.Detector.isWebKit() && (version === '10_6_2' || version === '10_6_1' || version === '10_6'));
  396.     },
  397.     CSSTransitions: function () {
  398.         try {
  399.             var temp = document.createElement('div').style;
  400.             temp.setProperty('-webkit-transition', 'inherit', null);
  401.             temp.setProperty('-moz-transition', 'inherit', null);
  402.             temp.setProperty('-o-transition', 'inherit', null);
  403.             temp.setProperty('transition', 'inherit', null);
  404.  
  405.             return (temp.getPropertyValue('-webkit-transition') == 'inherit' || 
  406.                     temp.getPropertyValue('-moz-transition') == 'inherit' || 
  407.                     temp.getPropertyValue('-o-transition') == 'inherit' ||
  408.                     temp.getPropertyValue('transition') == 'inherit');
  409.         } catch(e) {
  410.             return false;
  411.         }
  412.     },
  413.     CSSBorderRadius: function () {
  414.         try {
  415.             var temp = document.createElement('div').style;
  416.             temp.setProperty('-webkit-border-radius', 'inherit', null);
  417.             temp.setProperty('-moz-border-radius', 'inherit', null);
  418.             temp.setProperty('-o-border-radius', 'inherit', null);
  419.             temp.setProperty('border-radius', 'inherit', null);
  420.             
  421.             return (temp.getPropertyValue('-webkit-border-radius').match('inherit') ||
  422.                     temp.getPropertyValue('-moz-border-radius').match('inherit') ||
  423.                     temp.getPropertyValue('-o-border-radius').match('inherit') ||
  424.                     temp.getPropertyValue('border-radius').match('inherit'));
  425.         } catch(e) {
  426.             return false;
  427.         }
  428.     }
  429. };
  430.  
  431. // == Media.Spec ==
  432. //
  433. // Media.Spec is a list of the types of media that we can support, with
  434. // specs on how to create and interact with each.
  435. // 
  436. // The create function is in charge of generating DOM elements, and appending 
  437. // them to the container.
  438. Media.Spec = {
  439.     
  440.     Video: {
  441.         create: function (container, src, options) {
  442.             var tagName =  ( options && options.audio ) ? 'audio' : 'video',
  443.                 video,
  444.                 videoSrc = (src.indexOf('?') > 0) ? src.substring(0, src.lastIndexOf('?')): src,
  445.                 qtSource,
  446.                 dotLastIndex = videoSrc.lastIndexOf("."),
  447.                 pathExtension = ( dotLastIndex > 0 ) ? videoSrc.substring(dotLastIndex+1,src.length) : null,
  448.                 type =  'video/mp4';
  449.  
  450.                 if(pathExtension) {
  451.                     pathExtension = pathExtension.split("#")[0];
  452.                     type = tagName+'/'+pathExtension;
  453.                 }
  454.  
  455.             //Not re-using the video for iPad takes care of rdar://problem/8065412, tha forces a reload of the movie
  456.             if (!AC.Detector.isiPad() && existingVideo != false) {                
  457.             //if (existingVideo != false) {                
  458.                 if (existingVideoSrc == videoSrc) {
  459.                     //console.log('using existing video');
  460.                     video = existingVideo;
  461.                     container.appendChild(video);
  462.                     playExistingVideo = true;
  463.                     return video;
  464.                 } else {
  465.                     existingVideoSrc = false;
  466.                 }
  467.             }
  468.  
  469.             video = document.createElement(tagName);
  470.             qtSource = document.createElement('source');
  471.     
  472.             video.playerType = tagName;
  473.             if ((video.playerType === "video" && (video.canPlayType('video/mp4') || video.canPlayType('application/x-mpegURL'))) || (video.playerType === "audio" && ( ((AC.Detector.isWebKit() ||  AC.Detector.isMobile() || AC.Detector.isiPad()) && pathExtension === "mov") || video.canPlayType(type)) )) {
  474.                     
  475.                 if(video.playerType === "video") {
  476.                     type =  'video/mp4';
  477.                 }
  478.                 
  479.                 var id = options.id || (container.id ? container.id+'_video' : ''),
  480.                     fileExtension = (src.indexOf('?') > 0) ? src.substring(src.lastIndexOf('.'),src.lastIndexOf('?')) : src.substring(src.lastIndexOf('.'),src.length);
  481.  
  482.                 video.setAttribute('id', id);
  483.  
  484.                 Element.addClassName(video, video.playerType);
  485.  
  486.                 if(video.playerType === "video") {
  487.                     qtSource.setAttribute('src', videoSrc);
  488.  
  489.                     switch(fileExtension) {
  490.                         case '.m3u8':
  491.                             video.setAttribute('src', src);
  492.                             break;
  493.                         default:
  494.                             qtSource.setAttribute('type', type);
  495.                             video.appendChild(qtSource);
  496.                             break;
  497.                     }
  498.                 }
  499.                 else {
  500.                     video.setAttribute('src', src);
  501.                 }
  502.            
  503.  
  504.                this._configure(video, videoSrc, options);
  505.  
  506.                 Event.observe(window, 'unload', function () {
  507.                      try {
  508.                          video.stop();
  509.                      } catch(e) {}
  510.  
  511.                      video.style.display = 'none';
  512.                      video = null;
  513.                  });
  514.  
  515.                 container.appendChild(video);
  516.  
  517.                 existingVideoSrc = videoSrc;
  518.                 existingVideo = video;
  519.  
  520.             } else {
  521.                 // We need to create our fallback in case the browser supports <video>, but not our codec.
  522.                 // So... do that now
  523.                 video = this._createFallback(container, src, options);
  524.             }
  525. //alert(video.outerHTML);
  526.             return video;
  527.         },
  528.         
  529.         eventsToRegister: {
  530.             load: 'load',
  531.             loadedmetadata: 'loadedmetadata',
  532.             timeupdate: 'timeupdate',
  533.             durationchange: 'durationchange',
  534.             progress: 'progress',
  535.             playing: 'playing',
  536.             play: 'play',
  537.             pause: 'pause',
  538.             ended: 'ended'
  539.             // fullscreen removal
  540.             // webkitendfullscreen: 'webkitendfullscreen'
  541.         },
  542.         
  543.         _captions: null,
  544.         // fullscreen removal
  545.         // _fullscreen: false,
  546.         
  547.         interfaceMethods: {
  548.             readystate: function () {
  549.                 return this.readyState;
  550.             },
  551.             autoplay: function() {
  552.                 return this.autoplay;
  553.             },
  554.             duration: function () {
  555.                 return this.duration;
  556.             },
  557.             time: function () {
  558.                 if (!this.webkitClosedCaptionsVisible && this._captionsEnabled === true) {
  559.                     // update the closedcaptions display if we're playing
  560.                     if (typeof Media.Spec.Video._captions !== 'undefined') {
  561.                         var closedcaptions = Media.Spec.Video._captions.getElementsByTagName('p');
  562.  
  563.                         if (closedcaptions.length > 0) {
  564.                             var caption = '';
  565.                             
  566.                             function convertTime(oldTime) { 
  567.                                 var newTime = 0.0; 
  568.                                 if (oldTime) { 
  569.                                     var timeArr = oldTime.split(':'); 
  570.  
  571.                                     switch (timeArr.length) { 
  572.                                         case 3: 
  573.                                             for (var i=0; i < 3; i++) 
  574.                                             newTime = newTime * 60 + parseFloat(timeArr[i].replace(',', '.')); 
  575.                                             break; 
  576.                                         case 4: 
  577.                                             for (var i=0; i < 3; i++) 
  578.                                             newTime = newTime * 60 + parseFloat(timeArr[i].replace(',', '.')); 
  579.                                             // @@ ignore frames 
  580.                                             break;
  581.                                         default:
  582.                                             break;
  583.                                     } 
  584.                                 } 
  585.                                 return newTime; 
  586.                             }
  587.  
  588.                             for (var index = 0, closedcaption; closedcaption = closedcaptions[index]; index++) {
  589.                                 var begin = convertTime(closedcaption.getAttribute('begin')), 
  590.                                     end = convertTime(closedcaption.getAttribute('end')); 
  591.  
  592.                                 if (this.currentTime < begin) {
  593.                                     break;
  594.                                 }
  595.  
  596.                                 if (this.currentTime >= begin && this.currentTime < end) {
  597.                                     caption = closedcaption; 
  598.                                 }
  599.                             }
  600.  
  601.                             if (typeof caption != 'undefined' && caption != this.currentCaption) { 
  602.                                 this.currentCaption = caption; 
  603.  
  604.                                 var children = caption.childNodes, 
  605.                                     length = (typeof children != 'undefined') ? children.length : 0, 
  606.                                     captionString = ''; 
  607.  
  608.                                 for (var i = 0; i < length; i++) { 
  609.                                     var child = children.item(i); 
  610.                                     if (child.nodeType == 3) { 
  611.                                         captionString += '<span>'+child.nodeValue+'</span>';                                                                 
  612.                                     } 
  613.                                 } 
  614.                    
  615.                                 if (captionString === '') { 
  616.                                     this.trackTextSpan.style.display = 'none'; 
  617.                                 } else { 
  618.                                     this.trackTextSpan.style.display = 'inline-block'; 
  619.                                     this.trackTextSpan.innerHTML = captionString; 
  620.                                 }
  621.                             }
  622.                         }
  623.                     }
  624.                 }
  625.                 
  626.                 return this.currentTime;
  627.             },
  628.             setTime: function(value) {
  629.                 this.currentTime = value;
  630.             },
  631.             volume: function () {
  632.                 return this.volume;
  633.             },
  634.             setVolume: function(value) {
  635.                 this.volume = value;
  636.             },
  637.             muted: function () {
  638.                 return this.muted;
  639.             },
  640.             setMuted: function(value) {
  641.                 this.muted = value;
  642.             },
  643.             rate: function () {
  644.                 return this.playbackRate;
  645.             },
  646.             setRate: function (value) {
  647.                 this.playbackRate = value;
  648.             },
  649.             defaultRate: function () {
  650.                 return this.defaultPlaybackRate;
  651.             },
  652.             src: function () {
  653.                 return this.src;
  654.             },
  655.             setSrc: function (src) {
  656.     // console.log('in video spec setting src');
  657.                 this.src = src;
  658.             },
  659.             status: function () {
  660.                 return this.status;
  661.             },
  662.             percentLoaded: function () {
  663.                 var percentLoaded = 0;
  664.                 try {
  665.                     percentLoaded = this.buffered.end(0) / this.duration;
  666.                 } catch(e) {}
  667.                 return percentLoaded;
  668.             },
  669.             pause: function () {
  670.                 this.pause();
  671.             },
  672.             play: function () {
  673.                 this.play();
  674.             },
  675.             paused: function () {
  676.                 return this.paused;
  677.             },
  678.             ended: function () {
  679.                 return this.ended;
  680.             },
  681.             timeScale: function () {
  682.                 return 2997;
  683.             },
  684.             movieType: function () {
  685.                 return 'Video';
  686.             },
  687.             // fullscreen removal
  688.             // supportsFullscreen: function() {
  689.             //     return !!this.webkitSupportsFullscreen;
  690.             // },
  691.             getContainer: function () {
  692.                 return this.parentNode;
  693.             },
  694.             setTrackTextSpan: function(span) {
  695.                 this.trackTextSpan = span;
  696.             },
  697.             setCaptionsAvailable: function(func, url) {
  698.                 if ((typeof Media.Spec.Video._captions != 'undefined' && Media.Spec.Video._captions != null) || typeof this.webkitClosedCaptionsVisible != 'undefined') {
  699.                     func();
  700.                     return;
  701.                 }
  702.  
  703.                 var videoText;
  704.  
  705.                 if (url.match(/\w+:\/\//i)) {
  706.                     url = url.replace(/\w+:\/\/[^\/]+/i,"");
  707.                 }
  708.  
  709.                 // for debugging uncomment the line below
  710.                 //url = '/global/scripts/sbvdp/caption_export.xml';
  711.                 //console.log('captions url: '+url);
  712.  
  713.                 new Ajax.checkURL(url, func);
  714.             
  715.                 videoText = document.createElement('text');
  716.                 videoText.setAttribute('type', 'application/ttaf+xml');
  717.                 videoText.setAttribute('src', url);
  718.             
  719.                 this.appendChild(videoText); 
  720.  
  721.                 new Ajax.Request(url, {
  722.                     method:'get',
  723.                     requestHeaders: {Accept: 'application/ttaf+xml'},
  724.                     onSuccess: function(httpResponse) {
  725.                         var captionsDocument = httpResponse.responseXMLValue().documentElement;
  726.  
  727.                         if (AC.Detector.isIEStrict()) {
  728.                             captionsDocument = captionsDocument.ownerDocument;
  729.                         }
  730.  
  731.                         var language = captionsDocument.getAttribute('xml:lang'); 
  732.                         videoText.setAttribute('lang', language);
  733.                     
  734.                         Media.Spec.Video._captions = captionsDocument.getElementsByTagNameNS(Media.CAPTIONS_NS, 'body').item(0);
  735.                         Media.Spec.Video._captions.currentIndex = 0;
  736.                         //console.log('got captionsxml');
  737.                     }.bind(this),
  738.                     onFailure: function() {},
  739.                     onException: function() {}, 
  740.                     onCreate: function(httpResponse) { 
  741.                         httpResponse.request.overrideMimeType('application/ttaf+xml'); 
  742.                     }
  743.                 });
  744.                 
  745.             },
  746.             enableCaptions: function() {
  747.                 var enableCaptionsTextDisplay = this._videoClosedCaptionsEnabled;
  748.                 try{
  749.                     if (this._videoClosedCaptionsEnabled === true) {
  750.                         this.webkitClosedCaptionsVisible = true;
  751.                     }
  752.                 } catch(e) {}
  753.                 this._captionsEnabled = true;
  754.             },
  755.             disableCaptions: function() {
  756.                 try {
  757.                     if (this._videoClosedCaptionsEnabled === true) {
  758.                         this.webkitClosedCaptionsVisible = false;
  759.                     }
  760.                 } catch (e) {}
  761.                 
  762.                 if ('' != this.currentCaption) {
  763.                     this.currentCaption = this.trackTextSpan.innerHTML = '';
  764.                 }
  765.                 this._captionsEnabled = false;
  766.             },
  767.             _videoClosedCaptionsEnabled: false,
  768.             videoClosedCaptionsEnabled: function() {
  769.                 this._videoClosedCaptionsEnabled = (typeof this.webkitClosedCaptionsVisible != 'undefined') ? true : false;
  770.                 return this._videoClosedCaptionsEnabled;
  771.             } //,
  772.             // enableCaptionsTextDisplay: function() {
  773.             //     return (typeof this.webkitClosedCaptionsVisible != 'undefined') ? true : false;
  774.             // 
  775.             //     // if (typeof this.webkitClosedCaptionsVisible != 'undefined') {
  776.             //     //     return true;
  777.             //     // } else {
  778.             //     //     return false;
  779.             //     // }
  780.             // },
  781.             // fullscreen removal
  782.             // enableFullscreen: function() {
  783.             //     try {
  784.             //         if (this._captionsEnabled === true) {
  785.             //             this.webkitClosedCaptionsVisible = true;
  786.             //         }
  787.             //         this.webkitEnterFullScreen();
  788.             //     } catch(e) {}
  789.             // },
  790.             // disableFullscreen: function() {
  791.             //     try {
  792.             //         if (this._captionsEnabled === true) {
  793.             //             this.webkitClosedCaptionsVisible = false;
  794.             //         }
  795.             //         this.webkitExitFullScreen();
  796.             //     } catch(e) {}
  797.             // }
  798.         },
  799.         
  800.         _configure: function (video, src, options)
  801.         {
  802.             if (!options) {
  803.                 return;
  804.             }
  805.  
  806.             var property,
  807.                 attributeName;
  808.  
  809.             for (property in options) {
  810.  
  811.                 if (options.hasOwnProperty(property)) {
  812.                     if(typeof options[property] == undefined) {
  813.                         continue;
  814.                     }
  815.  
  816.                     attributeName = property.toLowerCase();
  817.  
  818.                     switch(attributeName) {
  819.                         case 'type':
  820.                         case 'src':
  821.                         case 'data':
  822.                         case 'classid':
  823.                         case 'name':
  824.                         case 'id':
  825.                         case 'postdomevents':
  826.                         case 'saveembedtags':
  827.                         case 'factory':
  828.                         case 'aggressiveCleanup':
  829.                         case 'innerId':
  830.                         case 'cache':
  831.                         case 'aggressivecleanup':
  832.                         case 'showlogo':
  833.                             //do nothing as these shouldn't be overridden or set
  834.                         break;
  835.                         case('class'):
  836.                             Element.addClassName(video, options[property]);
  837.                         break;
  838.                         case('controller'):
  839.                             if (options[property] || (Media.Detection.iPad() && video.tagName === "VIDEO") ) {
  840.                                 video.setAttribute("controls", "controls");
  841.                             }
  842.                         break;
  843.                         case('autoplay'):
  844.                         case('autostart'):
  845.                             if (options[property]) {
  846.                                 video.setAttribute("autoplay", "autoplay");
  847.                             }
  848.                         break;
  849.                         case('posterframe'):
  850.                             if (options[property]) {
  851.                                 video.setAttribute("poster", options[property]);
  852.                             }
  853.                         break;
  854.                         default:
  855.                             if(typeof options[property] !== "undefined") {
  856.                                 video.setAttribute(attributeName, options[property]);
  857.                             }
  858.                         break;
  859.                     }
  860.                 }
  861.             }
  862.         },
  863.         
  864.         _createFallback: function (container, src, options)
  865.         {
  866.             if (Media._isQuickTimeAvailable()) {
  867.                 return Media.Spec.QuickTime.create(container, src, options);
  868.             }
  869.             
  870.             if (Media._isSBVDPAvailable()) {
  871.                 return Media.Spec.SBVDP.create(container, src, options);
  872.             }
  873.             
  874.             if (Media._shouldShowDownloadPrompt()) {
  875.                 return Media.createDownloadPrompt(container, src, options);
  876.             }
  877.             
  878.             return false;
  879.         }
  880.     },
  881.     
  882.     QuickTime: {
  883.         create: function(container, src, options) {
  884.             var outerObject = this._createObject(src, options),
  885.                 innerObject = null,
  886.                 id = options.id || (container.id ? container.id+'_video' : '');
  887.                 
  888.             outerObject.setAttribute('id', id);
  889.             
  890.             if (!Media.Detection.IE() && !Media.Detection.Mobile()) {
  891.  
  892.                 // Note:
  893.                 // Creating an inner object in IE results in a "# items remaining" 
  894.                 // status which makes the page appear as if it never finishes loading. 
  895.                 // So, we won't create one for IE.
  896.  
  897.                 if (options.target === 'quicktimeplayer') {
  898.                     innerObject = this._innerObject = this._createInnerObject(src, options);
  899.                 } else {
  900.                     innerObject = this._embed = this._createEmbed(src, options);
  901.                 }
  902.                 outerObject.appendChild(innerObject);
  903.             } else {
  904.                 outerObject.style.behavior = "url(#qt_event_source)";
  905.                 
  906.                 if (options.aggressiveCleanup !== false){
  907.  
  908.                     //knowing it's IE at this point, make sure we clear the movie when the page closes
  909.                     //we also set our reference to null for good measure
  910.                     Event.observe(window, 'unload', function () {
  911.                         try {
  912.                             outerObject.Stop();
  913.                         } catch(e) {}
  914.  
  915.                         outerObject.style.display = 'none';
  916.                         outerObject = null;
  917.                     });
  918.                 }
  919.             }
  920.  
  921.             this._configure(innerObject, outerObject, options);
  922.  
  923.             // Needs to be last so IE sees all the parameters appended to
  924.             // the object prior to loading the activex control
  925.             outerObject.setAttribute('classid', 'clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B');
  926.             
  927.             // We're adding that in order to be able to specialize the CSS for movie-loading for the Quicktime plugin only.
  928.             Element.addClassName(outerObject, (outerObject.playerType = 'quicktime'));
  929.             //console.log(outerObject.innerHTML);
  930.             container.appendChild(outerObject);
  931.  
  932.             return innerObject || outerObject;
  933.         },
  934.  
  935.         pollForChanges: [
  936.             'load',
  937.             'timeupdate',
  938.             'durationchange',
  939.                'progress',
  940.             'playing',
  941.             'play',
  942.             'pause',
  943.                'ended'
  944.         ],
  945.         
  946.         _captions: null,
  947.         
  948.         interfaceMethods: {
  949.             setup: function () {
  950.             },
  951.             duration: function () {
  952.                 var duration = 0;
  953.                 try {
  954.                     duration = this.GetDuration() / this.GetTimeScale();
  955.                 } catch(e) {}
  956.                 return duration || 0;
  957.             },
  958.             time: function () {
  959.                 var time = 0;
  960.                 try {
  961.                     time = this.GetTime() / this.GetTimeScale();
  962.                 } catch(e) {}
  963.                 
  964.                 return time || 0;
  965.             },
  966.             setTime: function(value) {
  967.                 try {
  968.                     this.SetTime(value * this.GetTimeScale());
  969.                 } catch(e) {} 
  970.             },
  971.             volume: function () {
  972.                 return this.GetVolume() / 255;
  973.             },
  974.             setVolume: function(value) {
  975.                 this.SetVolume(value * 255);
  976.             },
  977.             muted: function () {
  978.                 return this.GetMute();
  979.             },
  980.             setMuted: function(value) {
  981.                 this.SetMute(value);
  982.             },
  983.             rate: function () {
  984.                 var rate;
  985.                 try {
  986.                     rate = this.GetRate();
  987.                 } catch(e) {}
  988.                 
  989.                 return rate || 1;
  990.             },
  991.             setRate: function (value) {
  992.                 this.SetRate(value);
  993.             },
  994.             status: function () {
  995.                 this.GetPluginStatus();
  996.             },
  997.             percentLoaded: function () {
  998.                 var percent = 0;
  999.                 try {
  1000.                     percent = this.GetMaxBytesLoaded()/this.GetMovieSize();
  1001.                 } catch(e) {}
  1002.                 return percent;
  1003.             },
  1004.             pause: function () {
  1005.                 try {
  1006.                     this.Stop();
  1007.                 } catch(e) {}
  1008.             },
  1009.             play: function () {
  1010.                 try {
  1011.                     this.Play();
  1012.                 } catch(e) {}
  1013.             },
  1014.             paused: function () {
  1015.                 try {
  1016.                     return this.GetRate()===0;
  1017.                 } catch(e) {}
  1018.             },
  1019.             ended: function () {
  1020.                 return this.ended;
  1021.             },
  1022.             src: function () {
  1023.                 var src;
  1024.                 try {
  1025.                     src = this.GetURL();
  1026.                 } catch(e) {}
  1027.             
  1028.                 return src || '';
  1029.             },
  1030.             setSrc: function (src) {
  1031.                 this.SetURL(src);
  1032.                 this.SetControllerVisible(false);
  1033.                 if (typeof this._embed != 'undefined') {
  1034.                     this._embed.SetControllerVisible(false);
  1035.                 }
  1036.             },
  1037.             timeScale: function () {
  1038.                 return this.GetTimeScale();
  1039.             },
  1040.             movieType: function () {
  1041.                 return 'QuickTime';
  1042.             },
  1043.             // fullscreen removal
  1044.             // supportsFullscreen: function() {
  1045.             //     return false;
  1046.             // },
  1047.             getContainer: function() {
  1048.                 return this._container;
  1049.             },
  1050.             setTrackTextSpan: function(span) {
  1051.  
  1052.             },
  1053.             setCaptionsAvailable: function(func, url) {
  1054.                 try {
  1055.                     // Try to find the closed caption trackCount
  1056.                     // (tragically the index starts at 1, not 0)
  1057.                     var trackCount = this.GetTrackCount(),
  1058.                         i;
  1059.             
  1060.                     for (i = 1; i <= trackCount; i++) {
  1061.                         if ('Closed Caption' === this.GetTrackType(i)) {
  1062.                             Media.Spec.QuickTime._captions = i;
  1063.                             if (typeof func != 'undefined') {
  1064.                                 func();
  1065.                             }
  1066.                         }
  1067.                     }
  1068.                 } catch(e) {}
  1069.             },
  1070.             enableCaptions: function() {
  1071.                 try {
  1072.                     if (Media.Spec.QuickTime._captions === 'undefined') {
  1073.                         this.setCaptionsAvailable();
  1074.                     }
  1075.  
  1076.                     this.SetTrackEnabled(Media.Spec.QuickTime._captions, true);
  1077.                     this._captionsEnabled = true;
  1078.                 } catch(e) {}
  1079.             },
  1080.             disableCaptions: function() {
  1081.                 try {
  1082.                     this.SetTrackEnabled(Media.Spec.QuickTime._captions, false);
  1083.                     this._captionsEnabled = false;
  1084.                 } catch(e) {}
  1085.             },
  1086.             videoClosedCaptionsEnabled: function() {
  1087.                 return false;
  1088.             }
  1089.         },
  1090.         
  1091.         _configure: function(innerObject, outerObject, options)
  1092.         {
  1093.             if (!options) {
  1094.                 return;
  1095.             }
  1096.  
  1097.             var property = null,
  1098.                 attributeName = null;
  1099.  
  1100.             for (property in options) {
  1101.                 if (options.hasOwnProperty(property)) {
  1102.  
  1103.                     if(typeof options[property] == undefined) {
  1104.                         continue;
  1105.                     }
  1106.                     
  1107.                     attributeName = property.toLowerCase();
  1108.  
  1109.                     switch(attributeName) {
  1110.                         case('type'):
  1111.                         case('src'):
  1112.                         case('data'):
  1113.                         case('classid'):
  1114.                         case('name'):
  1115.                         case('id'):
  1116.                         case('postdomevents'):
  1117.                         case('saveembedtags'):
  1118.                         case('factory'):
  1119.                         case('aggressiveCleanup'):
  1120.                             //do nothing as these shouldn't be overridden or set
  1121.                         break;
  1122.                         case('class'):
  1123.                             Element.addClassName(outerObject, options[property]);
  1124.                         break;
  1125.                         case('innerId'):
  1126.                             if (innerObject) {
  1127.                                 innerObject.setAttribute('id', options[property]);
  1128.                             }
  1129.                         break;
  1130.                         case('autoplay'):
  1131.                             this._addParameter(outerObject, 'autostart', options[property]);
  1132.                             this._addParameter(innerObject, 'autostart', options[property]);
  1133.                         break;
  1134.                         case('width'):
  1135.                         case('height'):
  1136.                             outerObject.setAttribute(attributeName, options[property]);
  1137.                             if (innerObject) {
  1138.                                 innerObject.setAttribute(attributeName, options[property]);
  1139.                             }
  1140.                         break;
  1141.                         default:
  1142.                             this._addParameter(outerObject, attributeName, options[property]);
  1143.                             this._addParameter(innerObject, attributeName, options[property]);
  1144.                         break;
  1145.                     }
  1146.                 }
  1147.             }
  1148.         },
  1149.         
  1150.         /**
  1151.         * Adds an object param tag to the specified parent
  1152.         * Note that the attributes are added in this seemingly odd order
  1153.         * so they show up in the logical order in the dom
  1154.         */
  1155.         _addParameter: function(parent, name, value)
  1156.         {
  1157.             if (!parent) {
  1158.                 return;
  1159.             }
  1160.  
  1161.             var param = document.createElement('param');
  1162.             param.setAttribute('value', value);
  1163.             param.setAttribute('name', name);
  1164.             parent.appendChild(param);
  1165.  
  1166.             param = null;
  1167.         },
  1168.  
  1169.         /**
  1170.         * Adds an object embed tag to the specified parent
  1171.         * only used for displaying controller over the movie
  1172.         */
  1173.         _createEmbed: function(url, options) {
  1174.             var embed = document.createElement('embed');
  1175.             embed.setAttribute('src', url);
  1176.             embed.setAttribute('type', 'video/quicktime');
  1177.             if (!Media.Detection.Firefox() && !Media.Detection.Opera())
  1178.                 embed.setAttribute('wmode', 'transparent');
  1179.             embed.setAttribute('postdomevents', true);
  1180.             embed.setAttribute('controller', false);
  1181.             embed.setAttribute('showlogo', false);
  1182.             embed.setAttribute('scale', 'tofit');
  1183.             
  1184.             if (options) {
  1185.                 if (!isNaN(parseInt(options.width, 10))) {
  1186.                     embed.setAttribute('width', options.width);
  1187.                 }
  1188.                 if (!isNaN(parseInt(options.height, 10))) {
  1189.                     embed.setAttribute('height', options.height);
  1190.                 }
  1191.                 if (typeof options.target != 'undefined') {
  1192.                     embed.setAttribute('target', options.target);
  1193.                 }
  1194.             }
  1195.             
  1196.             return embed;
  1197.         },
  1198.  
  1199.         /**
  1200.         * Adds an inner object tag to the specified parent
  1201.         * only used for targeting QuickTime player
  1202.         */
  1203.         _createInnerObject: function(url, options) {
  1204.             var object = document.createElement('object');
  1205.             
  1206.             object.setAttribute('type', 'video/quicktime');
  1207.             object.setAttribute('id', options.id+'Inner');
  1208.             object.setAttribute('name', options.id);
  1209.             object.setAttribute('width', '1');
  1210.             object.setAttribute('height', '1');
  1211.             object.setAttribute('data', url);
  1212.             
  1213.             this._addParameter(object, 'target', options.target);
  1214.             this._addParameter(object, 'postdomevents', 'true');
  1215.             
  1216.             return object;
  1217.         },
  1218.         
  1219.         /**
  1220.         * Creates the IE friendly outer object
  1221.         * NOTE Safari and Opera both seem to be able to use this one as well
  1222.         */
  1223.         _createObject: function(url, options)
  1224.         {
  1225.             var object = document.createElement('object'),
  1226.                 activexVersion = '7,3,0,0';
  1227.  
  1228.             if (Media.Detection.Mobile() && options.posterFrame) {
  1229.                 this._addParameter(object, 'src', options.posterFrame);
  1230.                 this._addParameter(object, 'href', url);
  1231.                 this._addParameter(object, 'target', 'myself');
  1232.             } else {
  1233.                 this._addParameter(object, 'src', url);
  1234.                 if (!Media.Detection.Firefox() && !Media.Detection.Opera()) {
  1235.                     this._addParameter(object, 'wmode', 'transparent');
  1236.                 }
  1237.             }
  1238.  
  1239.             object.setAttribute('id', name);
  1240.             
  1241.             if (!Media.Detection.Mobile()) {
  1242.                 this._addParameter(object, 'showlogo', false);
  1243.                 this._addParameter(object, 'scale', 'tofit');
  1244.                 this._addParameter(object, 'saveembedtags', true);
  1245.                 this._addParameter(object, 'postdomevents', true);
  1246.             }
  1247.  
  1248.             if (null !== options && (typeof options.codebase !== 'undefined') && '' !== options.codebase) {
  1249.                 activexVersion = options.codeBase;
  1250.             }
  1251.  
  1252.             object.setAttribute('codebase', 'http://www.apple.com/qtactivex/qtplugin.cab#version=' + activexVersion);
  1253.  
  1254.             return object;
  1255.         }
  1256.  
  1257.     }
  1258. };    
  1259. /*
  1260. if(AC.Detector.isiPad()) {
  1261.     HTMLMediaElement.prototype.forcePlay = function() {
  1262.         //alert("ipad = forcePlay");
  1263.         var self = this,
  1264.             link = document.createElement("a"),
  1265.             forcePlay = function(event) {
  1266.                 event.preventDefault();
  1267.                 self.play();
  1268.             },
  1269.             triggerEvent;
  1270.             link.addEventListener("click",forcePlay,false);
  1271.             document.body.appendChild(link);
  1272.             triggerEvent = document.createEvent("MouseEvents");
  1273.             if (triggerEvent.initMouseEvent) {
  1274.                 triggerEvent.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
  1275.                 link.dispatchEvent(triggerEvent);
  1276.             }
  1277.             document.body.removeChild(link);
  1278.     };
  1279.     HTMLMediaElement.prototype.forcePause = function() {
  1280.         var self = this,
  1281.             link = document.createElement("a"),
  1282.             forcePause = function(event) {
  1283.                 event.preventDefault();
  1284.                 self.pause();
  1285.             },
  1286.             triggerEvent;
  1287.             link.addEventListener("click",forcePause,false);
  1288.             document.body.appendChild(link);
  1289.             triggerEvent = document.createEvent("MouseEvents");
  1290.             if (triggerEvent.initMouseEvent) {
  1291.                 triggerEvent.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
  1292.                 link.dispatchEvent(triggerEvent);
  1293.             }
  1294.             document.body.removeChild(link);
  1295.     };
  1296.     
  1297. }
  1298. */
  1299.     
  1300.             
  1301. // == Media.VideoInterface ==
  1302. //
  1303. // Media.VideoInterface does the work of talking with the media element.
  1304. // It takes cues from Media.Spec to operate on the video element itself.
  1305. Media.VideoInterface = function(videoElement, delegateObject) {
  1306.  
  1307.     var video = videoElement,
  1308.         delegate = delegateObject,
  1309.         pollTimeout,
  1310.         videoTitle,
  1311.         videoUrl,
  1312.         videoDescription,
  1313.         videoPosterFrame;
  1314.  
  1315.     return {
  1316.         videoTitle: function() {
  1317.             return videoTitle;
  1318.         },
  1319.         
  1320.         setVideoTitle: function(newTitle) {
  1321.             videoTitle = newTitle;
  1322.         },
  1323.         
  1324.         videoUrl: function() {
  1325.             return videoUrl;
  1326.         },
  1327.         
  1328.         setVideoUrl: function(newUrl) {
  1329.             videoUrl = newUrl;
  1330.         },
  1331.         
  1332.         videoDescription: function() {
  1333.             return videoDescription;
  1334.         },
  1335.         
  1336.         setVideoDescription: function(newDescription) {
  1337.             videoDescription = newDescription;
  1338.         },
  1339.         
  1340.         videoPosterFrame: function() {
  1341.             return videoPosterFrame;
  1342.         },
  1343.         
  1344.         setVideoPosterFrame: function(newPosterFrame) {
  1345.             videoPosterFrame = newPosterFrame;
  1346.         },
  1347.     
  1348.         object: function () {
  1349.             return video;
  1350.         },
  1351.  
  1352.         setObject: function (newVideo) {
  1353.             video = newVideo;
  1354.         },
  1355.         
  1356.         setDelegate: function (newDelegate) {
  1357.             delegate = newDelegate;
  1358.         },
  1359.  
  1360.         setup: function() {},
  1361.         
  1362.         /**
  1363.          * Override default values (and optionally add new ones), subscribing the 
  1364.          * standard media interface to a customized one.
  1365.          */
  1366.         override: function (functions) {
  1367.             var member;
  1368.             
  1369.             function wrap(name, fn) {
  1370.                 return function() {
  1371.                     return fn.apply(video, arguments);
  1372.                 };
  1373.             }
  1374.             
  1375.             for (member in functions) {
  1376.                 this[member] = wrap(member, functions[member]);
  1377.             }
  1378.             return this;
  1379.         },
  1380.         
  1381.         registerEvent: function (functionName, eventName, auxFunction) {
  1382.             if (!auxFunction && typeof(eventName)=='function') {
  1383.                 auxFunction = eventName;
  1384.                 eventName = null;
  1385.             }
  1386.         
  1387.             var e = eventName || functionName;
  1388.             
  1389.             Event.observe(video, e, function (event) {
  1390.                 if (auxFunction) {
  1391.                     auxFunction.apply(this);
  1392.                 }
  1393.                 this.messageDelegate(functionName);
  1394.             }.bind(this));
  1395.         },
  1396.     
  1397.         pollForChanges: function (functions) {
  1398.             if (pollTimeout) {
  1399.                 window.clearInterval(pollTimeout);
  1400.             }
  1401.  
  1402.             if (functions) {
  1403.                 pollTimeout = window.setInterval(function(){
  1404.                     for(var i = 0, func; func = functions[i]; i++) {
  1405.                         this.messageDelegate(func);
  1406.                     }
  1407.                 }.bind(this), 480);
  1408.             }
  1409.         },
  1410.     
  1411.         messageDelegate: function(eventName) {
  1412.             if (!delegate) {
  1413.                 return;
  1414.             }
  1415.                 
  1416.             eventName = eventName.charAt(0).toUpperCase()+eventName.substring(1);
  1417.             var callback = 'videoReceived'+eventName+'Event';
  1418.         
  1419.             if (callback in delegate) {
  1420.                 delegate[callback](this);
  1421.             }
  1422.         }
  1423.     };
  1424. };
  1425.  
  1426. Media.Controller = function (containerElement) {
  1427.     var container = containerElement,
  1428.         delegate,
  1429.         video,
  1430.         videoSrc,
  1431.         controlPanel,
  1432.         timeout,
  1433.         sizeTimeout,
  1434.         duration,
  1435.         seeking = false,
  1436.         wasPlayingBeforeSeek,
  1437.         hasBegunPlaying = false,
  1438.         hasEndedPlaying = false,
  1439.         playing = false,
  1440.         playAcknowledged = true,
  1441.         pauseAcknowledged = true,
  1442.         isPlayAdvanced = false,
  1443.         currentlyChangingSize = false,
  1444.         sizeAnimation = false,
  1445.         controlPanelConfigurationsSet = false;
  1446.  
  1447.     function containerMouseMove(e) {
  1448.         if (!controlPanel || currentlyChangingSize || !hasBegunPlaying) {
  1449.             return;
  1450.         }
  1451.             
  1452.         controlPanel.show();
  1453.         window.clearTimeout(timeout);
  1454.         
  1455.         var controls = controlPanel.element;
  1456.             mouseElement = e.target || e.srcElement;        
  1457.         
  1458.         if (mouseElement == controls) {
  1459.             timeout = window.setTimeout(function(){
  1460.                 if (controlPanel && typeof controlPanel != 'undefined') {
  1461.                     controlPanel.hide();
  1462.                 }
  1463.             }, 2500);
  1464.         }
  1465.     }
  1466.     function containerMouseOut(e) {
  1467.         if (!controlPanel || !hasBegunPlaying) {
  1468.             return;
  1469.         }
  1470.         
  1471.         window.clearTimeout(timeout);
  1472.         timeout = window.setTimeout(function(){
  1473.             if (controlPanel) {
  1474.                 controlPanel.hide();
  1475.             }
  1476.         },50);
  1477.     }
  1478.     function containerMouseOver(e) {
  1479.         if (!controlPanel || !hasBegunPlaying) {
  1480.             return;
  1481.         }
  1482.             
  1483.         window.clearTimeout(timeout);
  1484.         timeout = window.setTimeout(function(){
  1485.             if (controlPanel) {
  1486.                 controlPanel.hide();
  1487.             }
  1488.         },50);
  1489.     }
  1490.     function containerMouseOver(e) {
  1491.         if (!controlPanel || currentlyChangingSize || !hasBegunPlaying) {
  1492.             return;
  1493.         }
  1494.             
  1495.         window.clearTimeout(timeout);
  1496.         controlPanel.show();
  1497.     }
  1498.     function menuMouseOver(e) {
  1499.         if (!controlPanel) {
  1500.             return;
  1501.         }
  1502.             
  1503.         window.clearTimeout(timeout);
  1504.         controlPanel.show();
  1505.     }
  1506.     
  1507.     return {
  1508.         _send: function (msg, params) {
  1509.             if (delegate && msg in delegate) {
  1510.                 params = [this].concat(params);
  1511.                 return delegate[msg].apply(delegate, params);
  1512.             }
  1513.         },
  1514.         
  1515.         _fireEvent: function (event, data) {
  1516.             Media.Controller.fireEvent(event, data);
  1517.         },
  1518.         
  1519.         reset: function () {
  1520.             seeking = false;
  1521.             hasBegunPlaying = false;
  1522.             hasEndedPlaying = false;
  1523.             playing = false;
  1524.         },
  1525.         
  1526.         setDelegate: function (newDelegate) {
  1527.             delegate = newDelegate;
  1528.         },
  1529.         
  1530.         setVideo: function (vid) {
  1531.             hasBegunPlaying = false;
  1532.             hasEndedPlaying = false;
  1533.             
  1534.             video = vid;
  1535.             duration = video.duration() || 0;
  1536.  
  1537.             if (controlPanel && controlPanel.videoObjectHasChanged) {
  1538.                 controlPanel.videoObjectHasChanged(video);
  1539.             }
  1540.  
  1541.             return this;
  1542.         },
  1543.  
  1544.         setVideoSrc: function(src) {
  1545.             videoSrc = src;
  1546.         },
  1547.  
  1548.         video: function() {
  1549.             return video;
  1550.         },
  1551.         
  1552.         setControlPanel: function (cp) {
  1553.             // Give the language file a moment to load first
  1554.             setTimeout(function() {
  1555.                 controlPanel = (video.tagName === "VIDEO" && Media.Detection.iPad()) ? false : cp;
  1556.                 
  1557.                 if (controlPanel) {
  1558.                     if (existingVideo != false && playExistingVideo === true) {
  1559.                         video.play();
  1560.                     }
  1561.                     
  1562.                     controlPanel.delegate = this;
  1563.                     Event.observe(containerElement, 'mousemove', containerMouseMove);
  1564.                     Event.observe(containerElement, 'mouseout', containerMouseOut);
  1565.                     Event.observe(containerElement, 'mouseover', containerMouseOver);
  1566.                     if(controlPanel.settingsMenu) {
  1567.                         Event.observe(controlPanel.settingsMenu, 'mouseover', menuMouseOver);
  1568.                     }
  1569.                     video.setTrackTextSpan(controlPanel.trackText);
  1570.                     if (!controlPanel.settingsControlsAreSet && (video.tagName === "VIDEO")) {
  1571.                         this.configureSettingsControls(videoSrc);
  1572.                         controlPanel.settingsControlsAreSet = true;
  1573.                     }
  1574.                     if(controlPanel.element) {
  1575.                         controlPanel.element.parentNode.parentNode.style.width = this.currentWidth + 'px';
  1576.                         controlPanel.element.parentNode.parentNode.style.height = this.currentHeight + 'px';
  1577.                     }
  1578.                     if(video.object().tagName.toLowerCase() === "video") {
  1579.                         this.setSizeAnimation(true);
  1580.                     }
  1581.                     this.setVideoSizeForWidthAndHeight(this.currentWidth, this.currentHeight);
  1582.                     controlPanel.setFocus();
  1583.                 } else {
  1584.                     Event.stopObserving(containerElement, 'mousemove', containerMouseMove);
  1585.                     Event.stopObserving(containerElement, 'mouseout', containerMouseOut);   
  1586.                     Event.stopObserving(containerElement, 'mouseover', containerMouseOver);
  1587.                 }
  1588.             
  1589.                 return this;
  1590.             }.bind(this), 1);
  1591.         },
  1592.  
  1593.         beginSeeking: function () {
  1594.             if (seeking) {
  1595.                 return;
  1596.             }
  1597.  
  1598.             seeking = true;
  1599.             wasPlayingBeforeSeek = !video.paused() && this.rate()==1;
  1600.             
  1601.             this.pause();
  1602.             
  1603.             var time = video.time();
  1604.             this._send('didStartJogging', time);
  1605.             this._fireEvent("QuickTime:didStartJogging", {controller: this, time: time});
  1606.         },
  1607.         
  1608.         endSeeking: function () {
  1609.             var time = video.time(),
  1610.                 duration = video.duration();
  1611.             
  1612.             seeking = false;
  1613.  
  1614.             this._send('didStopJogging', time);
  1615.             this._fireEvent("QuickTime:didStopJogging", {controller: this, time: time});
  1616.     
  1617.             if (wasPlayingBeforeSeek) {
  1618.                 if (time != duration) {
  1619.                     this.play();
  1620.                 } else {
  1621.                     // ending the movie if user scrubs past the end of the movie
  1622.                     // also, have to set hasEndedPlaying to false, since it hasn't ended yet
  1623.                     hasEndedPlaying = false;
  1624.                        this.videoReceivedEndedEvent(this);
  1625.                 }
  1626.             }
  1627.         },
  1628.         // fullscreen removal
  1629.         // supportsFullscreen: function() {
  1630.         //     //console.log('going to see if fullscreen is supported');
  1631.         //     return video.supportsFullscreen();
  1632.         // },    
  1633.  
  1634.         time: function () {
  1635.             return video.time() || this._lastTime || 0;
  1636.         },
  1637.         
  1638.         setTime: function(newTime) {
  1639.             video.setTime(newTime);
  1640.             this.videoReceivedTimeupdateEvent();
  1641.         },
  1642.  
  1643.         duration: function () {
  1644.             if ( !duration ) {
  1645.                 duration = video.duration();
  1646.             }
  1647.                return duration;
  1648.         },
  1649.  
  1650.         volume: function() {
  1651.             return video.volume();
  1652.         },
  1653.  
  1654.         setVolume: function(level) {
  1655.             video.setMuted(false);
  1656.             video.setVolume(level);
  1657.             if (typeof controlPanel != 'undefined' && controlPanel != null) {
  1658.                 controlPanel.volumeControlSetting = level;
  1659.             }
  1660.         },
  1661.  
  1662.         setMuted: function(mute) {
  1663.             video.setMuted(mute);
  1664.             if (typeof controlPanel != 'undefined' && controlPanel != null) {
  1665.                 controlPanel.volumeControlSetting = 0;
  1666.             }
  1667.         },
  1668.         
  1669.         toggleMute: function () {
  1670.             var isMuted = video.muted();
  1671.  
  1672.             if ( isMuted ) {
  1673.                 this.setMuted(false);
  1674.             } else {
  1675.                 this.setMuted(true);
  1676.             }
  1677.             
  1678.             return !isMuted;
  1679.         },
  1680.     
  1681.         playPause: function () {
  1682.             var isPaused = video.paused(),
  1683.                 rate = this.rate();
  1684.             
  1685.             if (isPaused && rate === 1) {
  1686.                 this.play();
  1687.             } else if (rate !== 1) {
  1688.                 this.setRate(1);
  1689.             } else {
  1690.                 this.pause();
  1691.             }
  1692.             
  1693.             return video.paused();
  1694.         },
  1695.         
  1696.         playing: function() {
  1697.             return playing;
  1698.         },
  1699.  
  1700.         play: function () {
  1701.                 video.play();
  1702.             playing = true;
  1703.             playAcknowledged = false;
  1704.         },
  1705.     
  1706.         playing: function () {    
  1707.             return playing;
  1708.         },
  1709.         pause: function () {
  1710.             video.pause();
  1711.             playing = false;
  1712.             pauseAcknowledged = false;
  1713.         },
  1714.     
  1715.         stop: function () {
  1716.                video.pause();
  1717.             playing = false;
  1718.             pauseAcknowledged = false;
  1719.             hasEndedPlaying = true;
  1720.         },
  1721.         
  1722.         setRate: function (newRate) {
  1723.             video.setRate(newRate);
  1724.             if (newRate !== 1 || newRate !== 0) {
  1725.                 isPlayAdvanced = true;
  1726.             } else {
  1727.                 isPlayAdvanced = false;
  1728.             }
  1729.         },
  1730.  
  1731.         rate: function () {
  1732.             return video.rate();
  1733.         },
  1734.  
  1735.         src: function () {
  1736.             return video.src();
  1737.         },
  1738.         
  1739.         setSrc: function (src) {
  1740.             // console.log('before setting src: '+src);
  1741.             video.setSrc(src);
  1742.             this._currentSrc = src;
  1743.         },
  1744.         
  1745.         setSizeAnimation: function(bool) {
  1746.             sizeAnimation = bool;
  1747.         },
  1748.         
  1749.         _currentSrc: false,
  1750.         setVideoSizeForSrc: function(src) {
  1751.             var path = this.moviePath(),
  1752.                 filename = src.substring(src.lastIndexOf('/')+1, src.length);
  1753.                 srcToSet = path + filename,
  1754.                 newWidth = filename.substring(filename.lastIndexOf('_')+1, filename.lastIndexOf('x')),
  1755.                 newHeight = filename.substring(filename.lastIndexOf('x')+1, filename.lastIndexOf('.'));
  1756.                 
  1757.             if (sizeAnimation === false || (video.percentLoaded() < 1 || (video.percentLoaded() >= 1 && (this._currentSrc != false && videoSrc != this._currentSrc)))) {
  1758.                 if (sizeAnimation === true) {
  1759.                     this.setSizeAnimation(false);
  1760.                 }
  1761.                 // console.log('set new src');
  1762.                 
  1763.                 this.setSrc(srcToSet);
  1764.             }
  1765.             
  1766.             this.setVideoSizeForWidthAndHeight(newWidth, newHeight);
  1767.         },
  1768.         
  1769.         setVideoSizeForWidthAndHeight: function(width, height) {
  1770.             var videoObject = video.object() || video.object().parentNode;
  1771.             if (typeof controlPanel != 'undefined' && typeof videoObject != 'undefined') {
  1772.                 //var videoObject = video.object();
  1773.                 
  1774.                 function setControlPanelType() {
  1775.                     if (typeof controlPanel != 'undefined') {
  1776.                         controlPanel.setControllerType();
  1777.                     // if (typeof controlPanel != 'undefined' && (controlPanel.controllerType === 'slim' || controlPanel.controllerType === 'short-slim')) {
  1778.                     //     if (controlPanel.controllerType === 'short-slim' && width > 450) {
  1779.                     //         Element.removeClassName(controlPanel.container, 'short-slim');
  1780.                     //         controlPanel.controllerType = 'slim';
  1781.                     //     }
  1782.                     //     if (controlPanel.controllerType === 'slim' && width <= 450) {
  1783.                     //         Element.addClassName(controlPanel.container, 'short-slim');
  1784.                     //         controlPanel.controllerType = 'short-slim';
  1785.                     //     }
  1786.                         controlPanel.setTrackContainerWidth();
  1787.                     }
  1788.                 }
  1789.                 
  1790.                 if (AC.Detector.isIEStrict()) {
  1791.                     var top = parseInt(height / 2);
  1792.                     videoObject.style.marginTop = '-' + top + 'px';
  1793.                     controlPanel.element.style.marginTop = '-' + top + 'px';
  1794.                     // if (AC.Detector.getAgent().match(/msie 8/i)) {
  1795.                     //     var left = parseInt(width/2);
  1796.                     //     videoObject.style.marginLeft = '-' + left + 'px';
  1797.                     //     controlPanel.element.style.marginLeft = '-' + left + 'px';
  1798.                     // }
  1799.                 }
  1800.                 
  1801.                 if (video.percentLoaded() < 1 || sizeAnimation === false || Media.Detection.Chrome()) {
  1802.                     // console.log('changing height/width');
  1803.                     videoObject.width = width;
  1804.                     videoObject.height = height;
  1805.                     if (video.movieType() != 'Video' && typeof videoObject.parentNode != null) {
  1806.                         videoObject.parentNode.width = width;
  1807.                         videoObject.parentNode.height = height;
  1808.                     }
  1809.                     controlPanel.container.style.width = width + 'px';
  1810.                     controlPanel.container.style.height = height + 'px';
  1811.                     if(controlPanel.element) {
  1812.                         controlPanel.element.style.width = width + 'px';
  1813.                         controlPanel.element.style.height = height + 'px';
  1814.                     }
  1815.                     
  1816.                     if (AC.Detector.isIEStrict()) {
  1817.                         var top = parseInt(height / 2);
  1818.                         videoObject.style.marginTop = '-' + top + 'px';
  1819.                         controlPanel.element.style.marginTop = '-' + top + 'px';
  1820.                         if (AC.Detector.getAgent().match(/msie 8/i)) {
  1821.                             var left = parseInt(width/2, 10);
  1822.                             //videoObject.style.left = '50%';
  1823.                             videoObject.parentNode.style.left = '50%';
  1824.                             controlPanel.element.style.left = '0';
  1825.                             videoObject.style.marginLeft = '-' + left + 'px';
  1826.                             controlPanel.element.style.marginLeft = '-' + left + 'px';
  1827.                             //     videoObject.parentNode.style.left = '50%';
  1828.                             //     videoObject.style.left = '0';
  1829.                             //     controlPanel.element.style.left = '0';
  1830.                             //     videoObject.style.marginLeft = '-' + left + 'px';
  1831.                             //     controlPanel.element.style.marginLeft = '-' + left + 'px';
  1832.  
  1833.                         }
  1834.                     }
  1835.                 } else {
  1836.                     // add transition
  1837.                     if (Media.Detection.CSSTransitions() === true && video.movieType() !== 'QuickTime') {
  1838.                         videoObject.style.width = width + 'px';
  1839.                         videoObject.style.height = height + 'px';
  1840.                         controlPanel.container.style.width = width + 'px';
  1841.                         controlPanel.container.style.height = height + 'px';
  1842.                         controlPanel.element.style.width = width + 'px';
  1843.                         controlPanel.element.style.height = height + 'px';
  1844.                     } else {
  1845.                         var morphEffects = [];
  1846.  
  1847.                         if (controlPanel.controllerType === 'slim' || controlPanel.controllerType === 'short-slim') {
  1848.                             controlPanel._hiding = true;
  1849.                             controlPanel._showing = false;
  1850.                     
  1851.                             controlPanel.fadeElement.style.opacity = '0';
  1852.                             controlPanel.fadeElement.style.visibility = 'hidden';
  1853.                             if(controlPanel.settingsMenu) {
  1854.                                 Element.removeClassName(controlPanel.settingsMenu, controlPanel.settingsMenu.baseClassName+'-hovered');    
  1855.                             }
  1856.                             
  1857.                             currentlyChangingSize = true;
  1858.                         }
  1859.                         controlPanel.resetSettingsMenus();
  1860.  
  1861.                         morphEffects.push(new Effect.Morph(videoObject, {sync:true, style:{width:width+'px', height:height+'px'}}));
  1862.                         if (video.movieType != 'Video' && typeof videoObject.parentNode != null) {
  1863.                             morphEffects.push(new Effect.Morph(videoObject.parentNode, {sync:true, style:{width:width+'px', height:height+'px'}}));
  1864.                         }
  1865.                         morphEffects.push(new Effect.Morph(controlPanel.container, {sync:true, style:{width:width+'px', height:height+'px'}}));
  1866.                         morphEffects.push(new Effect.Morph(controlPanel.element, {sync:true, style:{width:width+'px', height:height+'px'}}));
  1867.                         
  1868.                         var redraw = document.createElement('div');
  1869.                         Element.addClassName(redraw, 'ACMediaRedraw');
  1870.                         
  1871.                         var agent = AC.Detector.getAgent();
  1872.                         
  1873.                         var forceIERedraw = function() {
  1874.                             //if (!agent.match(/msie 8/i)) {
  1875.                                 // having to do a redraw on these elements to force IE6 not to show a black screen
  1876.                                 videoObject.style.outline = "1px solid transparent"; // adding an outline on the movie so the movie isn't black
  1877.                                 document.body.appendChild(redraw); // adding an element above the movie to remove black on and around movie
  1878.                                 controlPanel.mouseoverSettingsControl(controlPanel.sizesControl); // adding settings menu to remove black on edges of screen
  1879.  
  1880.                                 // removing all added CSS and elements
  1881.                                 videoObject.style.outline = 'none';
  1882.                                 document.body.removeChild(redraw);
  1883.                                 controlPanel.hide();
  1884.                                 controlPanel.resetSettingsMenus();
  1885.                             //}
  1886.                         }
  1887.  
  1888.                         new Effect.Parallel(morphEffects, {
  1889.                             duration:0.4,
  1890.                             beforeStart: function() {
  1891.                                 if (AC.Detector.isIEStrict()) {
  1892.                                     var top = parseInt(videoObject.offsetHeight/2);
  1893.                                     videoObject.parentNode.style.top = '50%';
  1894.                                     videoObject.style.top = '0';
  1895.                                     controlPanel.element.style.top = '0';
  1896.                                     videoObject.style.marginTop = '-' + top + 'px';
  1897.                                     controlPanel.element.style.marginTop = '-' + top + 'px';
  1898.                                     // if (agent.match(/msie 8/i)) {
  1899.                                     //     var left = parseInt(videoObject.offsetWidth/2);
  1900.                                     //     videoObject.parentNode.style.left = '50%';
  1901.                                     //     videoObject.style.left = '0';
  1902.                                     //     controlPanel.element.style.left = '0';
  1903.                                     //     videoObject.style.marginLeft = '-' + left + 'px';
  1904.                                     //     controlPanel.element.style.marginLeft = '-' + left + 'px';
  1905.                                     // }
  1906.                                     
  1907.                                     // force a redraw
  1908.                                     forceIERedraw();
  1909.                                 }                                
  1910.                             },
  1911.                             afterUpdate: function() {
  1912.                                 currentlyChangingSize = true;
  1913.                                 if (AC.Detector.isIEStrict()) {
  1914.                                     var top = parseInt(videoObject.offsetHeight/2);
  1915.                                     videoObject.parentNode.style.top = '50%';
  1916.                                     videoObject.style.top = '0';
  1917.                                     controlPanel.element.style.top = '0';
  1918.                                     videoObject.style.marginTop = '-' + top + 'px';
  1919.                                     controlPanel.element.style.marginTop = '-' + top + 'px';
  1920.                                     // if (agent.match(/msie 8/i)) {
  1921.                                     //     var left = parseInt(videoObject.offsetWidth/2);
  1922.                                     //     videoObject.parentNode.style.left = '50%';
  1923.                                     //     videoObject.style.left = '0';
  1924.                                     //     controlPanel.element.style.left = '0';
  1925.                                     //     videoObject.style.marginLeft = '-' + left + 'px';
  1926.                                     //     controlPanel.element.style.marginLeft = '-' + left + 'px';
  1927.                                     // }
  1928.                                 
  1929.                                     forceIERedraw();
  1930.                                 }
  1931.                             },
  1932.                             afterFinish: function() {
  1933.                                 if (AC.Detector.isIEStrict()) {
  1934.                                     var top = parseInt(height/2);
  1935.                                     //video.object().parentNode.parentNode.style.marginTop = '-' + top + 'px';
  1936.                                     videoObject.parentNode.style.top = '50%';
  1937.                                     videoObject.style.top = '0';
  1938.                                     controlPanel.element.style.top = '0';
  1939.                                     videoObject.style.marginTop = '-' + top + 'px';
  1940.                                     controlPanel.element.style.marginTop = '-' + top + 'px';
  1941.                                     // if (agent.match(/msie 8/i)) {
  1942.                                     //     var left = parseInt(width/2);
  1943.                                     //     videoObject.parentNode.style.left = '50%';
  1944.                                     //     videoObject.style.left = '0';
  1945.                                     //     controlPanel.element.style.left = '0';
  1946.                                     //     videoObject.style.marginLeft = '-' + left + 'px';
  1947.                                     //     controlPanel.element.style.marginLeft = '-' + left + 'px';
  1948.                                     // }
  1949.                                     
  1950.                                     // force a redraw
  1951.                                     controlPanel.mouseoutSettingsControl(controlPanel.sizesControl);
  1952.                                     controlPanel.hide();
  1953.                                 }
  1954.                                 
  1955.                                 setControlPanelType();
  1956.                                 
  1957.                                 window.clearTimeout(sizeTimeout);
  1958.                                 sizeTimeout = window.setTimeout(function(){
  1959.                                     if (controlPanel.controllerType === 'slim' || controlPanel.controllerType === 'short-slim') {
  1960.                                     
  1961.                                         controlPanel.fadeElement.style.visibility = 'visible';
  1962.                                         controlPanel.fadeElement.style.opacity = '1';
  1963.                                     
  1964.                                         controlPanel._hiding = false;
  1965.                                         controlPanel._showing = false;
  1966.                                     }
  1967.                             
  1968.                                     currentlyChangingSize = false;
  1969.                                 },50);
  1970.                             }
  1971.                         });
  1972.  
  1973.                     }
  1974.  
  1975.                 }
  1976.             
  1977.                 setControlPanelType();
  1978.             }
  1979.             this.currentWidth = width;
  1980.             this.currentHeight = height;
  1981.         },
  1982.         
  1983.         timeScale: function () {
  1984.             return video.timeScale();
  1985.         },
  1986.         
  1987.         movieType: function() {
  1988.             return video.movieType();
  1989.         },
  1990.  
  1991.         moviePath: function() {
  1992.             var url,
  1993.                 path = '';
  1994.  
  1995.             if (typeof videoSrc != 'undefined' && videoSrc.length > 0) {
  1996.                 url = videoSrc.substring(0, videoSrc.lastIndexOf('_')) + '.html';
  1997.             } else {
  1998.                 return;
  1999.             }
  2000.         
  2001.             if (url.match(/\w+:\/\//i)) {
  2002.                 // comment out the if section if not debugging
  2003.                 if ((window.location.href.match(/\w+:\/\/ic/i) || window.location.href.match(/\w+:\/\/www-dev/i)) && url.indexOf('/105') < 0) {
  2004.                     url = url.replace(/\w+:\/\/[^\/]+/i,"/105");
  2005.                 } else {
  2006.                     url = url.replace(/\w+:\/\/[^\/]+/i,"");
  2007.                 }
  2008.             }
  2009.         
  2010.             path = url.substring(0, (url.lastIndexOf('/')+1));
  2011.             
  2012.             return path;
  2013.         },
  2014.         
  2015.         setCaptionsAvailable: function(url) {
  2016.             var func = this.enableCaptionsControl.bind(this);
  2017.             video.setCaptionsAvailable(func, url);
  2018.         },
  2019.         
  2020.         enableCaptionsControl: function() {
  2021.             if (controlPanel && typeof controlPanel.enableCaptionsControl !== 'undefined') {
  2022.                 controlPanel.enableCaptionsControl();
  2023.                 return true;
  2024.             }
  2025.             return false;
  2026.         },
  2027.         
  2028.         enableCaptions: function() {
  2029.             video.enableCaptions();
  2030.             this._fireEvent("QuickTime:didSetClosedCaptions", {controller: this, enabled: true});
  2031.         },
  2032.         
  2033.         disableCaptions: function() {
  2034.             video.disableCaptions();
  2035.             this._fireEvent("QuickTime:didSetClosedCaptions", {controller: this, enabled: false});
  2036.         },
  2037.         
  2038.         enableCaptionsTextDisplay: function() {
  2039.             return video.videoClosedCaptionsEnabled();
  2040.         },
  2041.         
  2042.         resetCaptions: function() {
  2043.             video.disableCaptions();
  2044.         },
  2045.         
  2046.         setSizesAvailable: function(list) {
  2047.             this.sizesMenuOptions = list;
  2048.             
  2049.             for (var i=0, option; option=this.sizesMenuOptions[i]; i++) {
  2050.                 this.sizesMenuOptions['size_'+option.type] = option;
  2051.             }
  2052.             
  2053.             this.enableSizesControl();
  2054.         },
  2055.         
  2056.         enableSizesControl: function() {
  2057.             if (controlPanel && typeof controlPanel.enableSizesControl !== 'undefined') {
  2058.                 if (this.sizesMenuOptions.length > 1) {
  2059.                     controlPanel.buildSizesMenu(this.sizesMenuOptions);
  2060.                     controlPanel.setSizesAvailable();
  2061.                     controlPanel.enableSizesControl();
  2062.                     return true;
  2063.                 }
  2064.             }
  2065.             return false;
  2066.         },
  2067.         
  2068.         setDownloadAvailable: function(list) {
  2069.             this.downloadMenuOptions = list;
  2070.             
  2071.             for (var i=0, option; option=this.downloadMenuOptions[i]; i++) {
  2072.                 this.downloadMenuOptions['download_'+option.type] = option;
  2073.             }
  2074.             
  2075.             this.enableDownloadControl();
  2076.         },
  2077.  
  2078.         enableDownloadControl: function() {
  2079.             if (controlPanel && typeof controlPanel.enableDownloadControl !== 'undefined') {
  2080.                 if (this.downloadMenuOptions.length > 0) {
  2081.                     controlPanel.buildDownloadMenu(this.downloadMenuOptions);
  2082.                     controlPanel.setDownloadAvailable();
  2083.                     controlPanel.enableDownloadControl();
  2084.                     return true;
  2085.                 }
  2086.             }
  2087.             return false;
  2088.         },
  2089.         
  2090.         setShareAvailable: function(movie) {
  2091.             if (controlPanel && typeof controlPanel.enableShareControl !== 'undefined' && ac_media_language.sharemenu) {
  2092.                 var head = document.getElementsByTagName('head').item(0),
  2093.                     sharemenu = ac_media_language.sharemenu, self = this;
  2094.  
  2095.                 for (var i=0, sharemenuitem; sharemenuitem=sharemenu[i]; i++) {
  2096.                     var localScript = document.createElement('script'), shareMenuSetup;
  2097.                     localScript.setAttribute('type', 'text/javascript');
  2098.                     localScript.pluginName = sharemenuitem.id;
  2099.                     
  2100.                     shareMenuSetup = function() {
  2101.                     
  2102.                         //1) Get the class of the plugin that just loaded
  2103.                         //2) Create an instance
  2104.                         //3) Register it to controlPanel.registerPluginForMenu(newPlugin);
  2105.  
  2106.                         if (typeof window.event != 'undefined') {
  2107.                             var target = window.event.srcElement;
  2108.  
  2109.                             if (!window.event || ((target = window.event.srcElement) && (target.isLoaded || ( (typeof target.isLoaded === "undefined") && ((target.readyState == 'complete') || (target.readyState == 'loaded'))) ) )) {
  2110.                                 if (target && !target.isLoaded) {
  2111.                                     target.onreadystatechange = null;
  2112.                                     target.isLoaded = true;
  2113.                                 }
  2114.  
  2115.                                 Event._domReady();
  2116.                             }
  2117.                         }
  2118.                                     
  2119.                     }
  2120.                     
  2121.                     if (localScript.addEventListener) {
  2122.                         localScript.addEventListener("load",shareMenuSetup,false);
  2123.                     } else {
  2124.                     
  2125.                         if (typeof localScript.onreadystatechange === "function") {
  2126.                             localScript.onreadystatechange = function () {
  2127.                                 if (this.readyState == 'complete') {
  2128.                                     shareMenuSetup();
  2129.                                 }
  2130.                             }
  2131.                         } else {
  2132.                             localScript.onreadystatechange = shareMenuSetup;
  2133.                         }
  2134.                     }
  2135.  
  2136.                     localScript.setAttribute('src', sharemenuitem.plugin);
  2137.                     head.appendChild(localScript);
  2138.                     
  2139.                     sharemenu[i].localScript = localScript;
  2140.                 }
  2141.             }
  2142.         },
  2143.         // fullscreen removal
  2144.         // setFullscreenAvailable: function() {
  2145.         //     //console.log('setting fullscreen available');    
  2146.         //     this.enableFullscreenControl();
  2147.         // },
  2148.         // fullscreen removal
  2149.         // enableFullscreenControl: function() {
  2150.         //     if (controlPanel && typeof controlPanel.enableFullscreenControl !== 'undefined') {
  2151.         //         controlPanel.enableFullscreenControl();
  2152.         //         return true;
  2153.         //     }
  2154.         //     return false;
  2155.         // },
  2156.         // fullscreen removal
  2157.         // enableFullscreen: function() {
  2158.         //     video.enableFullscreen();
  2159.         //     this._fireEvent("QuickTime:didSetClosedFullscreen", {controller: this, enabled: true});
  2160.         // },
  2161.         // fullscreen removal
  2162.         // disableFullscreen: function() {
  2163.         //     video.disableFullscreen();
  2164.         //     this._fireEvent("QuickTime:didSetClosedFullscreen", {controller: this, enabled: false});
  2165.         // },
  2166.         
  2167.         configureSettingsControls: function(videoSrc) {
  2168.             if (existingVideo != false && controlPanelConfigurationsSet === true) return;
  2169.             
  2170.             var url,
  2171.                 langAttr = document.body.parentNode.getAttribute('lang'),
  2172.                 language = MediaLanguage.getLangFromAttr(langAttr),
  2173.                 //language = document.getElementsByTagName('html').item(0).getAttribute('lang'),
  2174.                 path = this.moviePath();
  2175.  
  2176.             if (typeof videoSrc != 'undefined' && videoSrc.length > 0) {
  2177.                     url = videoSrc.substring(0, videoSrc.lastIndexOf('_')) + '.json';
  2178.                 // url = videoSrc.substring(0, videoSrc.lastIndexOf('_')) + '.html';
  2179.             } else {
  2180.                 return;
  2181.             }
  2182.         
  2183.             
  2184.             if (url.match(/\w+:\/\//i)) {
  2185.                 // comment out the if section if not debugging
  2186.                 if ((window.location.href.match(/\w+:\/\/ic/i) || window.location.href.match(/\w+:\/\/www-dev/i)) && url.indexOf('/105') < 0) {
  2187.                     url = url.replace(/\w+:\/\/[^\/]+/i,"/105");
  2188.                 } else {
  2189.                     url = url.replace(/\w+:\/\/[^\/]+/i,"");
  2190.                 }
  2191.             }
  2192.         
  2193.             //path = url.substring(0, (url.lastIndexOf('/')+1));
  2194.             
  2195.             // for debugging uncomment the lines below
  2196.             // if (location.href.match('test-without-share')){
  2197.             //     url = '/tests/quicktime/snow_leopard_controls/configure-test-without-share.html';
  2198.             // } else {
  2199.             //     url = '/tests/quicktime/snow_leopard_controls/configure-test.html';
  2200.             // }
  2201.         
  2202.             // new Ajax.checkURL(url, function() {
  2203.             //     this.checkedForConfigXML = true;
  2204.             // }.bind(this));
  2205.             //  url = '/105'+url;
  2206.             // if (url.match(/\/105\/105/i)) {
  2207.             //     url = url.replace(/\/105\/105/, "/105");
  2208.             // }
  2209.             
  2210.             // JSON request for configuration file
  2211.             new Ajax.Request(url, {
  2212.                 method:'get',
  2213.                 requestHeaders: {Accept: 'application/json'},
  2214.                 onSuccess: function(transport) {
  2215.                     this.configSettings = new Function("return "+transport.responseText)();
  2216.                     
  2217.                     this.setSettingsControlsAvailableForLanguageAndPath(language, path);
  2218.                 }.bind(this),
  2219.                 onFailure: function() {
  2220.                     if (typeof controlPanel != 'undefined') {
  2221.                         controlPanel.setTrackContainerWidth();
  2222.                     }
  2223.                 }.bind(this),
  2224.                 onException: function() {},
  2225.                 evalJS: false
  2226.             });
  2227.             
  2228.         },
  2229.         
  2230.         setSettingsControlsAvailableForLanguageAndPath: function(language, path) {
  2231.             var captionsWithPath = this.configSettings.metadata.captions,
  2232.                 sizesList = this.configSettings.metadata.sizes,
  2233.                 downloadList = this.configSettings.metadata.downloads,
  2234.                 shareToggle = this.configSettings.metadata.share || true,
  2235.                 movieLanguage = this.configSettings.metadata.lang,
  2236.                 movieTitle = this.configSettings.metadata.title,
  2237.                 movieDescription = this.configSettings.metadata.description,
  2238.                 movieUrl = this.configSettings.src,
  2239.                 moviePosterframe = this.configSettings.posterframe || 'http://images.apple.com/global/elements/overlay/overlay_movie_endstate_640x400_20081014.jpg';
  2240.  
  2241.                 if (typeof movieTitle != 'undefined') {
  2242.                     video.setVideoTitle(movieTitle);
  2243.                 }
  2244.                 if (typeof movieUrl != 'undefined') {
  2245.                     video.setVideoUrl(movieUrl);
  2246.                 }
  2247.                 if (typeof movieDescription != 'undefined') {
  2248.                     video.setVideoDescription(movieDescription);
  2249.                 }
  2250.                 if (typeof moviePosterframe != 'undefined') {
  2251.                     video.setVideoPosterFrame(moviePosterframe);
  2252.                 }
  2253.  
  2254.                 if (typeof captionsWithPath != 'undefined') {
  2255.                     var captionsFile = captionsWithPath.substring(captionsWithPath.lastIndexOf('/'), captionsWithPath.length),
  2256.                         captionsUrl = path + ((captionsFile[0] === '/') ? captionsFile.substring(1, captionsFile.length) : captionsFile);
  2257.  
  2258.                     controlPanel.captionsUrl = captionsUrl;
  2259.                     this.setCaptionsAvailable(controlPanel.captionsUrl);
  2260.                 }
  2261.  
  2262.                 if (typeof sizesList != 'undefined') {
  2263.                     this.setSizesAvailable(sizesList);
  2264.                 }
  2265.                 if (typeof downloadsList != 'undefined') {
  2266.                     this.setDownloadAvailable(downloadList);
  2267.                 }
  2268.                 if (shareToggle) {
  2269.                     this.setShareAvailable();
  2270.                 }
  2271.                 
  2272.                 // if (this.supportsFullscreen() === true) {
  2273.                 //     //console.log('in setting... before setfullscreenavailable');
  2274.                 //     this.setFullscreenAvailable();
  2275.                 // }
  2276.                 
  2277.                 if (typeof captionsUrl == 'undefined' && typeof sizesList == 'undefined' && typeof downloadsList == 'undefined' && !shareToggle && this.supprtsFullscreen() === false && typeof controlPanel != 'undefined') {
  2278.                     controlPanel.setTrackContainerWidth();
  2279.                 }
  2280.                 
  2281.                 controlPanelConfigurationsSet = true;
  2282.         },
  2283.         
  2284.         videoReceivedPlayingEvent: function (evt) {
  2285.             if (!hasBegunPlaying && (this.movieType() == 'Video' || (this.time() > 0 && this.duration != 0))) {
  2286.                 if (controlPanel && typeof controlPanel.mediaDidBecomePlayable !== 'undefined') {
  2287.                     controlPanel.mediaDidBecomePlayable();
  2288.                 }
  2289.                 
  2290.                 if (controlPanel && typeof controlPanel.enableBasicControls !== 'undefined') {
  2291.                     // give the settings config file a moment to load
  2292.                     controlPanel.enableBasicControls();
  2293.                     controlPanel.setSettingsControls();
  2294.                     if (typeof controlPanel.captionsUrl != 'undefined' && !controlPanel.captionsControl.isEnabled) {
  2295.                         this.setCaptionsAvailable(controlPanel.captionsUrl);
  2296.                     }
  2297.                     
  2298.                     switch(true) {
  2299.                         case (typeof controlPanel.captionsControlSetting != 'undefined' && controlPanel.captionsControlSetting === true):
  2300.                             video.enableCaptions();
  2301.                             break;
  2302.                         default:
  2303.                             break;
  2304.                     }
  2305.                 }
  2306.  
  2307.                 // if (Media.Detection.SnowLeopard1062() && this.movieType() == 'Video') {
  2308.                 //     var state = video.readystate(),
  2309.                 //         autoplay = video.autoplay();
  2310.                 //     console.log('videoReceivedPlayingEvent - state: '+state);
  2311.                 //     console.log('videoReceivedPlayingEvent - autoplay: '+autoplay);
  2312.                 // }
  2313.  
  2314.                 playing = true;
  2315.  
  2316.                 Element.removeClassName(this.container, this.movieLoadingPanelClass);
  2317.  
  2318.                 hasBegunPlaying = true;
  2319.                 this._send('didBecomePlayable');
  2320.                 this._fireEvent("QuickTime:canplaythrough", {controller: this});
  2321.                 this._send('didBegin');
  2322.                this._fireEvent("QuickTime:begin", {controller: this});
  2323.                 
  2324.                 timeout = window.setTimeout(function(){
  2325.                     if (controlPanel && typeof controlPanel != 'undefined') {
  2326.                         controlPanel.hide();
  2327.                     }
  2328.                 }, 500);
  2329.                 
  2330.             }
  2331.         },
  2332.         
  2333.         videoReceivedLoadEvent: function (evt) {
  2334.             if (controlPanel) {
  2335.                 var percentLoaded = video.percentLoaded();
  2336.                 controlPanel.updatePercentLoaded(percentLoaded);
  2337.  
  2338.                 // if (Media.Detection.SnowLeopard1062() && this.movieType() == 'Video') {
  2339.                 //     var state = video.readystate(),
  2340.                 //         autoplay = video.autoplay();
  2341.                 //     // console.log('videoReceivedLoadEvent - state: '+state);
  2342.                 //     // console.log('videoReceivedLoadEvent - autoplay: '+autoplay);
  2343.                 // }
  2344.                 
  2345.                 if (percentLoaded <= 1 && typeof controlPanel.captionsUrl != 'undefined' && !controlPanel.captionsControl.isEnabled) {
  2346.                     this.setCaptionsAvailable(controlPanel.captionsUrl);
  2347.                 }
  2348.                 
  2349.                 // if (percentLoaded >= 1 && Media.Detection.SnowLeopard1062()) {
  2350.                 //     controlPanel.removeClickToPlay();
  2351.                 // }
  2352.             }
  2353.             
  2354.         },
  2355.         // fullscreen removal
  2356.         // videoReceivedLoadedmetadataEvent: function (evt) {
  2357.         //     if (controlPanel) {
  2358.         //         if (this.supportsFullscreen() === true) {
  2359.         //             //console.log('in onfailure before setfullscreenavailable');
  2360.         //             this.setFullscreenAvailable();
  2361.         //         }
  2362.         //     }
  2363.         // },
  2364.         
  2365.         videoReceivedEndedEvent: function (evt) {
  2366.             var time = video.time();
  2367.                 duration = video.duration();
  2368.             
  2369.             if (hasEndedPlaying) {
  2370.                 return;
  2371.             }
  2372.  
  2373.             if (hasBegunPlaying && ((time >= duration && duration != 0) || (video.movieType() == "SBVDP" && duration != 0 && time >= (duration - 0.5)))) {
  2374.                 hasEndedPlaying = true;
  2375.                 this.videoReceivedTimeupdateEvent(this);
  2376.  
  2377.                 if (controlPanel) {
  2378.                     controlPanel.resetSettingsMenus();
  2379.                     
  2380.                     if (AC.Detector.isIEStrict()) {
  2381.                         // clean up video sizing for IE
  2382.                         var videoObject = video.object();
  2383.                         
  2384.                         videoObject.parentNode.style.width = '';
  2385.                         videoObject.parentNode.style.height = '';
  2386.                         videoObject.parentNode.style.top = '';
  2387.                         videoObject.style.top = '';
  2388.                         controlPanel.element.style.top = '';
  2389.                         videoObject.style.marginTop = '';
  2390.                         controlPanel.element.style.marginTop = '';
  2391.                         
  2392.                         if (AC.Detector.getAgent().match(/msie 8/i)) {
  2393.                             videoObject.parentNode.style.left = '';
  2394.                             videoObject.style.left = '';
  2395.                             controlPanel.element.style.left = '';
  2396.                             videoObject.style.marginLeft = '';
  2397.                             controlPanel.element.style.marginLeft = '';
  2398.                         }
  2399.                     }
  2400.                 }
  2401.                 
  2402.                 if (!seeking) {
  2403.                     this._send('onMovieFinished');
  2404.                     this._send('didEnd');
  2405.                     this._fireEvent("QuickTime:end", {controller: this});
  2406.                 }
  2407.             }
  2408.         },
  2409.         
  2410.         videoReceivedPlayEvent: function (evt) {
  2411.             this._currentPlayState = 'playing';
  2412.             if (playAcknowledged) {
  2413.                 return;
  2414.             }
  2415.                 
  2416.             playAcknowledged = true;
  2417.             
  2418.             this._send('didStart');
  2419.             this._fireEvent("QuickTime:start", {controller: this});
  2420.         },
  2421.  
  2422.         videoReceivedPauseEvent: function (evt) {
  2423.             this._currentPlayState = 'paused';
  2424.             if (pauseAcknowledged) {
  2425.                 return;
  2426.             }
  2427.                 
  2428.             pauseAcknowledged = true;
  2429.             
  2430.             this._send('didStop');
  2431.             this._fireEvent("QuickTime:stop", {controller: this});
  2432.         },
  2433.  
  2434.         videoReceivedTimeupdateEvent: function (evt) {
  2435.             
  2436.             var time = video.time() || 0;
  2437.             //console.log("time = "+time);
  2438.             if (controlPanel) {
  2439.                 controlPanel.updateTime(time);
  2440.             }
  2441.             if (this._lastTime != time) {
  2442.                 this._fireEvent("QuickTime:didPlayProgress", {
  2443.                     controller: this, 
  2444.                     currentTime: time, 
  2445.                     duration: this.duration()
  2446.                 });
  2447.             }
  2448.             
  2449.             this._lastTime = time;
  2450.         },
  2451.     
  2452.         videoReceivedProgressEvent: function (evt) {
  2453.             if (controlPanel) {
  2454.                 controlPanel.updatePercentLoaded(video.percentLoaded());
  2455.             }
  2456.             
  2457.             // console.log('videoReceivedProgressEvent - state: '+video.readystate()+' - '+video.percentLoaded());
  2458.             switch(true) {
  2459.                 case (!hasBegunPlaying && Media.Detection.SnowLeopard() && this.movieType() == 'Video' && video.autoplay() === true && video.readystate() >= 3 && video.percentLoaded() > 0.4):
  2460.                     // console.log('should start playing');
  2461.                     this.play();
  2462.                     //this.videoReceivedPlayingEvent();
  2463.                     break;
  2464.                 default:
  2465.                     break;
  2466.             }
  2467.  
  2468.         },
  2469.  
  2470.         videoReceivedDurationchangeEvent: function (evt) {
  2471.             if (controlPanel) {
  2472.                 controlPanel.updateRemainingTime(this.duration() - this.time());
  2473.             }
  2474.         }
  2475.         // fullscreen removal
  2476.         // videoReceivedWebkitendfullscreenEvent: function (evt) {
  2477.         //     if (controlPanel) {
  2478.         //         if (typeof this._currentPlayState != 'undefined' && this._currentPlayState === 'playing') {
  2479.         //             controlPanel.play();
  2480.         //         } else if (typeof this._currentPlayState != 'undefined' && this._currentPlayState === 'paused') {
  2481.         //             controlPanel.pause();
  2482.         //         }
  2483.         //         
  2484.         //         var currentVolume = this.volume();
  2485.         //         controlPanel.volumeScrubber.setValue(currentVolume);
  2486.         //         this.setVolume(currentVolume);
  2487.         // 
  2488.         //     }
  2489.         // 
  2490.         // }
  2491.     };
  2492. };
  2493. Media.Controller.fireEvent = function (event, data) {
  2494.     var body = $(document.body);
  2495.     if ('fire' in body) {
  2496.         body.fire(event, data);
  2497.     }
  2498. };
  2499.  
  2500. Media.ControlsWidget = function (containerElement, delegateObject, options) {
  2501.     this.settingsControlsAreSet = false;
  2502.     this.container = containerElement;
  2503.     this.delegate = delegateObject;
  2504.     this.options = options;
  2505.  
  2506.     //Adds itself as an observer of the plugin loaded notification.
  2507.     //process any plugin that are already loaded.
  2508.     // and call this.registerPluginClass() //The instance level method.
  2509.     Event.observe(document.body, 'PluginClass:Added', this.registerPluginClass.bind(this));
  2510.  
  2511.     for (var i=0, pluginType; pluginType=Media.ControlsWidget.pluginTypes[i]; i++) {
  2512.         for (var j=0, pluginClass; pluginClass=pluginType[j]; j++) {
  2513.             this.registerPluginClass(pluginClass);
  2514.         }
  2515.     }
  2516.     
  2517.     if (!Media.Detection.iPad()) {
  2518.         this._createTemplate();
  2519.         this._setupControls();
  2520.     }
  2521. };
  2522.  
  2523. Media.ControlsWidget.registerPluginClass = function(aPluginClass) {
  2524.     //Structure plugins by pluginType: pluginType -> [plugin1, plugin2, plugin3]
  2525.     //Send an event to tell that a new plugin class is available
  2526.     //Instances need to register for that event, and when they get it, they add the menu for themselves.
  2527.  
  2528.     var pluginName = aPluginClass.prototype.name(),
  2529.         pluginType = aPluginClass.prototype.pluginType(),
  2530.         pluginTypeArray;
  2531.     
  2532.     this.pluginTypes(pluginType);
  2533.     this.pluginClassesForType
  2534.     
  2535.     if (!(pluginTypeArray = Media.ControlsWidget._pluginTypes[pluginType]) || !Media.ControlsWidget._pluginTypes.hasOwnProperty(pluginType)) {
  2536.         pluginTypeArray = [];
  2537.         Media.ControlsWidget._pluginTypes[pluginType] = pluginTypeArray;
  2538.         Media.ControlsWidget._pluginTypes.push(pluginType);
  2539.     }
  2540.     
  2541.     if (!pluginTypeArray.hasOwnProperty(pluginName)) {
  2542.         pluginTypeArray[pluginName] = pluginName;
  2543.         pluginTypeArray.push(pluginName);
  2544.     }
  2545.     
  2546.     Media.Controller.fireEvent('PluginClass:Added', {
  2547.         'plugin': aPluginClass,
  2548.         'name': pluginName,
  2549.         'type': pluginType
  2550.     });
  2551. };
  2552. Media.ControlsWidget._pluginTypes = [];
  2553. Media.ControlsWidget.pluginTypes = function(aPluginType) {
  2554.     return this._pluginTypes;
  2555. };
  2556. Media.ControlsWidget.pluginClassesForType = function(aPluginType) {
  2557.     return this.pluginTypes[aPluginType];
  2558. };
  2559.  
  2560. Media.ControlsWidget.TEMPLATE = '\
  2561. <div id="ACMedia-controls" class="ACMediaControls" tabindex="0">\
  2562.     <a href="#video"></a>\
  2563.     <div id="ACMedia-alert-display-container" class="ACMediaAlertDisplay"></div>\
  2564.     <div id="ACMedia-track-text" class="ACMediaTrackText"><span id="ACMedia-track-text-span"></span></div>\
  2565.     <div id="ACMedia-controls-panel" class="mediaControllerPanel">\
  2566.         <div class="slim-left-cap"></div>\
  2567.         <div id="ACMedia-media-controller" class="ACMediaController">\
  2568.             <div id="ACMedia-volume-mute" class="volumeMute"></div>\
  2569.             <div class="volumePanel">\
  2570.                 <div id="ACMedia-volume-track" class="volumeTrack">\
  2571.                     <div id="ACMedia-control-volume-progress" class="volumeTrackProgress"></div>\
  2572.                     <div id="ACMedia-volume-handle" class="volumePlayHead"></div>\
  2573.                 </div>\
  2574.             </div>\
  2575.             <div id="ACMedia-volume-full" class="volumeFull"></div>\
  2576.             <div id="ACMedia-control-fastbackward" class="fastBackward"></div>\
  2577.             <div id="ACMedia-control-play-pause"></div>\
  2578.             <div id="ACMedia-control-fastforward" class="fastForward"></div>\
  2579.             <div id="ACMedia-track-container" class="track-container">\
  2580.                 <div id="ACMedia-control-time-display" class="timeDisplay"><span id="ACMedia-min-played">00</span>:<span id="ACMedia-sec-played">00</span></div>\
  2581.                 <div class="trackPanel">\
  2582.                     <div id="ACMedia-control-track" class="track">\
  2583.                         <div id="ACMedia-control-loaded-progress" class="loadedProgress"></div>\
  2584.                         <div id="ACMedia-control-track-progress" class="trackProgress"></div>\
  2585.                         <div id="ACMedia-control-playhead" class="playHead"></div>\
  2586.                     </div>\
  2587.                     <div id="ACMedia-track-end-cap" class="track-right-cap"></div>\
  2588.                 </div>\
  2589.                 <div id="ACMedia-control-duration-display" class="durationDisplay">-<span id="ACMedia-min-remain">00</span>:<span id="ACMedia-sec-remain">00</span></div>\
  2590.             </div>\
  2591.             <div id="ACMedia-settings-controls" class="settingsControls">\
  2592.                 <div id="ACMedia-captions-control" class="captionsControl"></div>\
  2593.                 <div id="ACMedia-sizes-control" class="sizesControl"></div>\
  2594.                 <div id="ACMedia-download-control" class="downloadControl"></div>\
  2595.                 <div id="ACMedia-share-control" class="shareControl"></div>\
  2596.             </div>\
  2597.         </div>\
  2598.         <div class="slim-right-cap"></div>\
  2599.     </div>\
  2600. </div>';
  2601.  
  2602. // fullscreen removal
  2603. //                 <div id="ACMedia-fullscreen-control" class="fullscreenControl"></div>\
  2604.  
  2605.  
  2606. Media.ControlsWidget.show = function(controls) {
  2607.     if (controls.fadeElement && !controls._showing) {
  2608.         if (controls._effect) {
  2609.             try {
  2610.                 controls._effect.cancel();
  2611.             } catch(e) {}
  2612.             delete controls._effect;
  2613.         }
  2614.  
  2615.         controls._showing = true;
  2616.         controls._hiding = false;
  2617.  
  2618.         if (controls.fadeElement) {
  2619.             if (Media.Detection.CSSTransitions() === true) {
  2620.                 controls._effect = function() {
  2621.                     Element.removeClassName(controls.fadeElement, 'fade');
  2622.                 };
  2623.                 controls._effect();
  2624.             } else {
  2625.                 controls._effect = new Effect.Opacity(controls.fadeElement, {
  2626.                     to: 1, 
  2627.                     duration: 0.5,
  2628.                     afterFinish: function(){controls._showing=false;}
  2629.                 });
  2630.             }
  2631.         }
  2632.     }
  2633. };
  2634. Media.ControlsWidget.hide = function(controls) {
  2635.     if (controls.fadeElement && !controls._hiding) {
  2636.         if (controls._effect) {
  2637.             try {
  2638.                 controls._effect.cancel();
  2639.             } catch(e) {}
  2640.             delete controls._effect;
  2641.         }
  2642.         
  2643.         controls._hiding = true;
  2644.         controls._showing = false;
  2645.         if (controls.fadeElement) {
  2646.             if (Media.Detection.CSSTransitions() === true) {
  2647.                 controls._effect = function() {
  2648.                     controls.resetSettingsMenus();
  2649.                     //controls._unselectControl(controls._currentSettingsControl);
  2650.                     Element.addClassName(controls.fadeElement, 'fade');
  2651.                 };
  2652.                 controls._effect();
  2653.             } else {
  2654.                 controls._effect = new Effect.Opacity(controls.fadeElement, {
  2655.                     to: 0,
  2656.                     duration: 0.5,
  2657.                     beforeStart: function(){
  2658.                         controls.resetSettingsMenus();
  2659.                         //controls._unselectControl(controls._currentSettingsControl);
  2660.                     },
  2661.                     afterFinish: function(){
  2662.                         controls._hiding=false;
  2663.                     }
  2664.                 });
  2665.             }
  2666.         }
  2667.     }
  2668. };
  2669.  
  2670. Media.ControlsWidget.prototype = {
  2671.     delegate: null,
  2672.     element: null,
  2673.     _plugins: [],
  2674.  
  2675.     _buildControlWithTitleOptions: function(title, menuOptions) {
  2676.         var control = document.createElement('li'),
  2677.             anchor = document.createElement('a');
  2678.  
  2679.         Element.addClassName(control, title);
  2680.         // console.log('menuOptions.url: '+menuOptions.url+' menuOptions.name: '+menuOptions.name);
  2681.         if (typeof menuOptions != 'undefined' && typeof menuOptions.url != 'undefined' && typeof menuOptions.name != 'undefined') {
  2682.             anchor.setAttribute('href', menuOptions.url);
  2683.             anchor.innerHTML = menuOptions.name;
  2684.             control.appendChild(anchor);
  2685.         } else {
  2686.             return;
  2687.         }
  2688.  
  2689.         control.baseClassName = control.baseClassName || control.className;
  2690.         
  2691.         Event.observe(control, 'mousedown', function(evt) {
  2692.             Element.addClassName(this, this.baseClassName+'-active');
  2693.         });
  2694.         Event.observe(control, 'mouseup', function(evt) {
  2695.             Element.removeClassName(this, this.baseClassName+'-active');
  2696.         });
  2697.         Event.observe(document.documentElement, 'mouseup', function(evt) {
  2698.             Element.removeClassName(this, this.baseClassName+'-active');
  2699.         });
  2700.         Event.observe(control, 'mouseover', function(evt) {
  2701.             Element.addClassName(this, this.baseClassName+'-hover');
  2702.         });
  2703.         Event.observe(control, 'mouseout', function(evt) {
  2704.             Element.removeClassName(this, this.baseClassName+'-hover');
  2705.         });
  2706.  
  2707.         return control;
  2708.     },
  2709.     
  2710.     _sizesMenuControls: [],
  2711.     selectSizeFromMenu: function(control) {
  2712.         if (typeof control != 'undefined') {
  2713.             this._unselectMenu();
  2714.             this._unselectControl(this.sizesControl);
  2715.             for (var i=0, sizeControl; sizeControl=this._sizesMenuControls[i]; i++) {
  2716.                 (sizeControl === control) ? this._selectControl(sizeControl) : this._unselectControl(sizeControl);
  2717.             }
  2718.             this._send('setVideoSizeForSrc', control.optionsUrl);
  2719.             this.sizesControlSetting = control;
  2720.         }
  2721.     },
  2722.     _getSizesMenuControl: function(size, title, options) {
  2723.         var control = this._buildControlWithTitleOptions('size'+title, {
  2724.             'url': options.src,
  2725.             'name': (ac_media_language[size] || title) + ' ' + options.width + 'x' + options.height
  2726.         });
  2727.         control.appendChild(document.createElement('span'));
  2728.         control.optionsUrl = options.src;
  2729.         Event.observe(control, 'click', function(evt) {
  2730.             Event.stop(evt);
  2731.             this.selectSizeFromMenu(control);
  2732.         }.bindAsEventListener(this));
  2733.  
  2734.         if (this.element.offsetWidth == options.width && this.element.offsetHeight == options.height) {
  2735.             this._selectControl(control);
  2736.         }
  2737.  
  2738.         return control;
  2739.     },
  2740.     buildSizesMenu: function(options) {
  2741.         this.originalElementWidth = this.element.offsetWidth;
  2742.         this.originalElementHeight = this.element.offsetHeight;
  2743.         
  2744.         if (Media.Detection.CSSTransitions() === true) {
  2745.             this.element.style.width = this.originalElementWidth + 'px';
  2746.             this.element.style.height = this.originalElementHeight + 'px';
  2747.         }
  2748.         
  2749.         if (typeof options.size_hd != 'undefined' && this.originalElementWidth >= options.size_hd.width && this.originalElementHeight >= options.size_hd.height) {
  2750.             this.sizesHDControl = this._getSizesMenuControl('hd', 'HD', options.size_hd);
  2751.             this._sizesMenuControls.push(this.sizesHDControl);
  2752.             this.sizesMenu.appendChild(this.sizesHDControl);
  2753.         }
  2754.  
  2755.         if (typeof options.size_large != 'undefined' && this.originalElementWidth >= options.size_large.width && this.originalElementHeight >= options.size_large.height) {
  2756.             this.sizesLargeControl = this._getSizesMenuControl('large', 'Large', options.size_large);
  2757.             this._sizesMenuControls.push(this.sizesLargeControl);
  2758.             this.sizesMenu.appendChild(this.sizesLargeControl);
  2759.         }
  2760.         
  2761.         if (typeof options.size_medium != 'undefined' && this.originalElementWidth >= options.size_medium.width && this.originalElementHeight >= options.size_medium.height) {
  2762.             this.sizesMediumControl = this._getSizesMenuControl('medium', 'Medium', options.size_medium);
  2763.             this._sizesMenuControls.push(this.sizesMediumControl);
  2764.             this.sizesMenu.appendChild(this.sizesMediumControl);
  2765.         }
  2766.         
  2767.         if (typeof options.size_small != 'undefined' && this.originalElementWidth >= options.size_small.width && this.originalElementHeight >= options.size_small.height) {
  2768.             this.sizesSmallControl = this._getSizesMenuControl('small', 'Small', options.size_small);
  2769.             this._sizesMenuControls.push(this.sizesSmallControl);
  2770.             this.sizesMenu.appendChild(this.sizesSmallControl);
  2771.         }
  2772.         
  2773.         return this._sizesMenuControls;
  2774.     },
  2775.     
  2776.     _downloadMenuControls: [],
  2777.     _getDownloadMenuControl: function(size, title, options) {
  2778.         var controlTitle = (title.match(/\//)) ? title.substring(0, title.indexOf('/')) : title,
  2779.             unit = 'mb';
  2780.         var control = this._buildControlWithTitleOptions('download'+controlTitle, {
  2781.             'url': options.src,
  2782.             'name': (ac_media_language[size] || title) + ' ' + options.size + (ac_media_language[unit] || 'MB')
  2783.         });
  2784.         Event.observe(control, 'click', function(evt) {
  2785.             Event.stop(evt);
  2786.             this._unselectMenu();
  2787.             this._unselectControl(this.downloadControl);
  2788.             document.location.href = options.src;
  2789.         }.bindAsEventListener(this));
  2790.         
  2791.         return control;
  2792.     },
  2793.     buildDownloadMenu: function(options) {
  2794.         if (typeof options.download_hd != 'undefined') {
  2795.             this.downloadHDControl = this._getDownloadMenuControl('hd', 'HD', options.download_hd);
  2796.             this._downloadMenuControls.push(this.downloadHDControl);
  2797.             this.downloadMenu.appendChild(this.downloadHDControl);
  2798.         }
  2799.         if (typeof options.download_large != 'undefined') {
  2800.             this.downloadLargeControl = this._getDownloadMenuControl('large', 'Large', options.download_large);
  2801.             this._downloadMenuControls.push(this.downloadLargeControl);
  2802.             this.downloadMenu.appendChild(this.downloadLargeControl);
  2803.         }
  2804.         if (typeof options.download_ipod != 'undefined') {
  2805.             this.downloadiPodControl = this._getDownloadMenuControl('ipod', 'iPod/iPhone', options.download_ipod);
  2806.             this._downloadMenuControls.push(this.downloadiPodControl);
  2807.             this.downloadMenu.appendChild(this.downloadiPodControl);
  2808.         }
  2809.  
  2810.         return this._downloadMenuControls;
  2811.     },
  2812.     
  2813.     _shareMenuControls: [],
  2814.     buildShareMenu: function(pluginClass) {
  2815.             var pluginName = pluginClass.name(),
  2816.                 pluginUrl = pluginClass.url();
  2817.             //    pluginShare = pluginClass.share();
  2818.             
  2819.             var control = this[pluginName.toLowerCase()+'Control'] = this._buildControlWithTitleOptions(pluginName, {
  2820.                 'url': pluginUrl,
  2821.                 'name': pluginName
  2822.             });
  2823.             
  2824.             var video = this._send('video');
  2825.             
  2826.             Event.observe(control, 'click', function(evt) {
  2827.                 Event.stop(evt);
  2828.                 pluginClass.share(video);
  2829.             });
  2830.             //Event.observe(control, 'click', pluginShare);
  2831.             this._shareMenuControls.push(control);
  2832.             this.shareMenu.appendChild(control);
  2833.             
  2834.             Element.addClassName(control, control.baseClassName + '-enabled');
  2835.         //}
  2836.  
  2837.         //this.shareMenuControls = this.menuControls;
  2838.  
  2839.         return this._shareMenuControls;
  2840.     },
  2841.     
  2842.     _registeredPlugins: [],
  2843.     registerPluginClass: function(evt) {
  2844.         var plugin = new evt.memo.plugin(),
  2845.             pluginName = plugin.name(),
  2846.             pluginActionName = plugin.actionName(),
  2847.             pluginType = plugin.pluginType();
  2848.                     
  2849.         
  2850.         this._registeredPlugins.push(plugin);
  2851.         
  2852.         this.buildShareMenu(plugin);
  2853.  
  2854.         //Add an item in menu menuName and set plugin as the recipient for the action. Share plugins need to receive as an argument:
  2855.         //    - the title of the video
  2856.         //    - a description
  2857.         //    - The URL of the video.
  2858.  
  2859.         if (!this.shareEnabled) {
  2860.             this.setShareAvailable();
  2861.             this.enableShareControl();
  2862.         }
  2863.  
  2864.     },
  2865.     
  2866.     _createTemplate: function () {
  2867.         function templateToNode(str) {
  2868.             var temporary = document.createElement('div'),
  2869.                 node;
  2870.             temporary.innerHTML = str;
  2871.             node = temporary.firstChild;
  2872.             return node;
  2873.         }
  2874.             
  2875.         this.setControllerType();
  2876.         
  2877.         var datetime = new Date();
  2878.         this.timestamp = datetime.getTime();
  2879.         
  2880.            this.container.appendChild(templateToNode(Media.ControlsWidget.TEMPLATE));
  2881.         
  2882.            this.element = document.getElementById('ACMedia-controls');
  2883.         this.element.id = 'ACMedia-controls_'+this.timestamp;
  2884.         this.element.style.outline = 'none';
  2885.         
  2886.         Event.observe(this.element, 'keydown', this.keyDownHandler.bindAsEventListener(this));
  2887.         // Click to Play for Snow Leopard < 10.6.3
  2888.         // if (Media.Detection.SnowLeopard1062()) {        
  2889.         //     this.fadeElement = document.getElementById('ACMedia-controls-panel');
  2890.         //     this.fadeElement.style.visibility = 'hidden';
  2891.         // 
  2892.         //     this.clickToPlayElement = document.createElement('ul');
  2893.         //     var clickToPlayItem = document.createElement('li'),
  2894.         //         clickToPlaySpanButton = document.createElement('span'),
  2895.         //         clickToPlaySpan = document.createElement('span'),
  2896.         //         clickToPlayBold = document.createElement('b');
  2897.         //     
  2898.         //     Element.addClassName(clickToPlaySpanButton, 'pillbutton');
  2899.         //     clickToPlaySpan.innerHTML = ac_media_language.play || 'Play';
  2900.         //     clickToPlayBold.innerHTML = '>';
  2901.         //     Event.observe(this.clickToPlayElement, 'click', this.clickToPlay.bindAsEventListener(this));
  2902.         // 
  2903.         //     clickToPlaySpanButton.appendChild(clickToPlaySpan);
  2904.         //     clickToPlaySpanButton.appendChild(clickToPlayBold);
  2905.         //     clickToPlayItem.appendChild(clickToPlaySpanButton);
  2906.         //     this.clickToPlayElement.appendChild(clickToPlayItem);
  2907.         // 
  2908.         //     this.element.appendChild(this.clickToPlayElement);
  2909.         // }
  2910.     },
  2911.  
  2912.     _setRegularControllerType: function() {
  2913.         Element.removeClassName(this.container, 'slim');
  2914.         Element.removeClassName(this.container, 'short-slim');
  2915.         this.controllerType = 'regular';
  2916.     },
  2917.     _setSlimControllerType: function() {
  2918.         Element.addClassName(this.container, 'slim');
  2919.         Element.removeClassName(this.container, 'short-slim');
  2920.         this.controllerType = 'slim';
  2921.     },
  2922.     _setShortSlimControllerType: function() {
  2923.         Element.addClassName(this.container, 'slim');
  2924.         Element.addClassName(this.container, 'short-slim');
  2925.         this.controllerType = 'short-slim';
  2926.     },
  2927.     setControllerType: function() {
  2928.         switch (true) {
  2929.             case Media.Detection.Firefox():
  2930.             case Media.Detection.Opera():
  2931.             case (typeof this.options != 'undefined' && this.options.slimController === true):
  2932.             case (typeof this.options != 'undefined' && this.options.controllerType === 'slim'):
  2933.                 if (this.container.offsetWidth < 450) {
  2934.                     this._setShortSlimControllerType();
  2935.                 } else {
  2936.                     this._setSlimControllerType();
  2937.                 }
  2938.                 break;
  2939.             case (this.container.offsetWidth < 450 && !AC.Detector.isIEStrict()):
  2940.                 this._setShortSlimControllerType();
  2941.                 break;
  2942.             default:
  2943.                 this._setRegularControllerType();
  2944.         }
  2945.         
  2946.         if (!this.volumeScrubber) {
  2947.             this.createVolumeScrubber();
  2948.         }
  2949.     },
  2950.     
  2951.     setFocus: function() {
  2952.         if(this.element) {
  2953.             window.setTimeout(function() {
  2954.                 try{
  2955.                     this.element.focus();
  2956.                 } catch(e) {
  2957.                     this.setFocus();
  2958.                 }
  2959.             }.bind(this), 50);
  2960.         }
  2961.     },
  2962.  
  2963.     // clickToPlay: function() {
  2964.     //     this.removeClickToPlay();
  2965.     //     this.play();
  2966.     // },
  2967.     // removeClickToPlay: function() {
  2968.     //     this.fadeElement.style.visibility = 'visible';
  2969.     //     this.clickToPlayElement.style.display = 'none';
  2970.     // },
  2971.     
  2972.     _setupControls: function () {
  2973.         var timestamp = this.timestamp;
  2974.         this.fadeElement = get('ACMedia-controls-panel');
  2975.         this.trackEndCap = get('ACMedia-track-end-cap');
  2976.  
  2977.         function addTimeStamp(element) {
  2978.             var currentId = element.id;
  2979.             element.id = currentId+'_'+timestamp;
  2980.             return element.id;
  2981.         }
  2982.         
  2983.         function addBaseClassName(element) {
  2984.             element.baseClassName = element.baseClassName || element.className;
  2985.         }
  2986.         
  2987.         function addActiveStateSwitching(element) {
  2988.             addBaseClassName(element);
  2989.  
  2990.             function onmousedown(event) {
  2991.     //console.log('adding active to: '+this.baseClassName);
  2992.                 Element.addClassName(this, this.baseClassName+'-active');
  2993.             }
  2994.             function onmouseup(event) {
  2995.                 Element.removeClassName(this, this.baseClassName+'-active');            
  2996.             }
  2997.             
  2998.             Event.observe(element, 'mousedown', onmousedown.bind(element));
  2999.             Event.observe(element, 'mouseup', onmouseup.bind(element));
  3000.             Event.observe(document.documentElement, 'mouseup', onmouseup.bind(element));
  3001.         }
  3002.         
  3003.         function addHoverStateSwitching(element) {
  3004.             if (!element.baseClassName) {
  3005.                 addBaseClassName(element);
  3006.             }
  3007.             
  3008.             function onmouseover(event) {
  3009.                 Element.addClassName(this, element.baseClassName+'-hover');
  3010.             }
  3011.             function onmouseout(event) {
  3012.                 Element.removeClassName(this, element.baseClassName+'-hover');
  3013.             }
  3014.             
  3015.             Event.observe(element, 'mouseover', onmouseover.bind(element));
  3016.             Event.observe(element, 'mouseout', onmouseout.bind(element));
  3017.         }
  3018.         
  3019.         function get(id) {
  3020.             var element = document.getElementById(id),
  3021.                 newId = addTimeStamp(element);
  3022.             
  3023.             return element;
  3024.         }
  3025.         
  3026.         // Play/pause button
  3027.         this.toggleControl = get('ACMedia-control-play-pause');
  3028.         
  3029.         this.playControl = document.createElement('div');
  3030.         Element.addClassName(this.playControl, 'play');
  3031.         addActiveStateSwitching(this.playControl);
  3032.         this.playControl.id = 'ACMedia-play-control_'+this.timestamp;
  3033.         Event.observe(this.playControl, 'click', this.play.bind(this));
  3034.         this.playControl.innerHTML = ac_media_language.play || 'Play';
  3035.         this.playControl.style.display = 'none';
  3036.  
  3037.         this.pauseControl = document.createElement('div');
  3038.         Element.addClassName(this.pauseControl, 'pause');
  3039.         addActiveStateSwitching(this.pauseControl);
  3040.         this.pauseControl.id = 'ACMedia-pause-control_'+this.timestamp;
  3041.         Event.observe(this.pauseControl, 'click', this.pause.bind(this));
  3042.         this.pauseControl.innerHTML = ac_media_language.pause || 'Pause';
  3043.         this.pauseControl.style.display = 'none';
  3044.         
  3045.         Element.show(this._send('playing') ? this.pauseControl : this.playControl);        
  3046.         //var playpause = get('ACMedia-control-play-pause');
  3047.         var playpause = this.toggleControl;
  3048.         playpause.appendChild(this.playControl);
  3049.         playpause.appendChild(this.pauseControl);
  3050.         
  3051.         // Fast Backward
  3052.         this.fastBackwardControl = get('ACMedia-control-fastbackward');
  3053.         this.fastBackwardControl.innerHTML = ac_media_language.fastreverse || 'Fast Reverse';
  3054.         Event.observe(this.fastBackwardControl, 'click', this.fastBackward.bind(this));
  3055.         addActiveStateSwitching(this.fastBackwardControl);
  3056.         
  3057.         // Fast Forward
  3058.         this.fastForwardControl = get('ACMedia-control-fastforward');
  3059.         this.fastForwardControl.innerHTML = ac_media_language.fastforward || 'Fast Forward';
  3060.         Event.observe(this.fastForwardControl, 'click', this.fastForward.bind(this));
  3061.         addActiveStateSwitching(this.fastForwardControl);
  3062.         
  3063.         // Volume Mute
  3064.         this.volumeMuteControl = get('ACMedia-volume-mute');
  3065.         this.volumeMuteControl.innerHTML = ac_media_language.mutevolume || 'Mute Volume';
  3066.         Event.observe(this.volumeMuteControl, 'click', this.muteVolume.bind(this));
  3067.         addActiveStateSwitching(this.volumeMuteControl);
  3068.         
  3069.         // Volume Full
  3070.         this.volumeFullControl = get('ACMedia-volume-full');
  3071.         this.volumeFullControl.innerHTML = ac_media_language.fullvolume || 'Full Volume';
  3072.         Event.observe(this.volumeFullControl, 'click', this.fullVolume.bind(this));
  3073.         addActiveStateSwitching(this.volumeFullControl);
  3074.         
  3075.         // Settings Controls
  3076.         this.settingsControls = get('ACMedia-settings-controls');
  3077.         addBaseClassName(this.settingsControls);
  3078.         
  3079.         this.captionsControl = get('ACMedia-captions-control');
  3080.         if (!AC.Detector.isIEStrict()) {
  3081.             this.captionsControl.innerHTML = ac_media_language.captionscontrol || 'Closed Captions';
  3082.         }
  3083.         Event.observe(this.captionsControl, 'click', this.toggleCaptions.bind(this));
  3084.         addActiveStateSwitching(this.captionsControl);
  3085.         
  3086.         this.sizesControl = get('ACMedia-sizes-control');
  3087.         if (!AC.Detector.isIEStrict()) {
  3088.             this.sizesControl.innerHTML = ac_media_language.sizescontrol || 'Video Size';
  3089.         }
  3090.         this.sizesControl.controlName = 'sizes';
  3091.         Event.observe(this.sizesControl, 'click', this.toggleSizesMenu.bind(this));
  3092.         addActiveStateSwitching(this.sizesControl);
  3093.         Event.observe(this.sizesControl, 'mouseover', this.mouseoverSettingsControl.bind(this, this.sizesControl));
  3094.         Event.observe(this.sizesControl, 'mouseout', this.mouseoutSettingsControl.bindAsEventListener(this, this.sizesControl));
  3095.         
  3096.         this.downloadControl = get('ACMedia-download-control');
  3097.         if (!AC.Detector.isIEStrict()) {
  3098.             this.downloadControl.innerHTML = ac_media_language.downloadcontrol || 'Download Video';
  3099.         }
  3100.         this.downloadControl.controlName = 'download';
  3101.         Event.observe(this.downloadControl, 'click', this.toggleDownloadMenu.bind(this));
  3102.         addActiveStateSwitching(this.downloadControl);
  3103.         Event.observe(this.downloadControl, 'mouseover', this.mouseoverSettingsControl.bind(this, this.downloadControl));
  3104.         Event.observe(this.downloadControl, 'mouseout', this.mouseoutSettingsControl.bindAsEventListener(this, this.downloadControl));
  3105.         
  3106.         this.shareControl = get('ACMedia-share-control');
  3107.         if (!AC.Detector.isIEStrict()) {
  3108.             this.shareControl.innerHTML = ac_media_language.sharecontrol || 'Share Video';
  3109.         }
  3110.         this.shareControl.controlName = 'share';
  3111.         Event.observe(this.shareControl, 'click', this.toggleShareMenu.bind(this));
  3112.         addActiveStateSwitching(this.shareControl);
  3113.         Event.observe(this.shareControl, 'mouseover', this.mouseoverSettingsControl.bind(this, this.shareControl));
  3114.         Event.observe(this.shareControl, 'mouseout', this.mouseoutSettingsControl.bindAsEventListener(this, this.shareControl));
  3115.         
  3116.         // fullscreen removal
  3117.         // this.fullscreenControl = get('ACMedia-fullscreen-control');
  3118.         // if (!AC.Detector.isIEStrict()) {
  3119.         //     this.fullscreenControl.innerHTML = ac_media_language.fullscreencontrol || 'Full Screen';
  3120.         // }
  3121.         // Event.observe(this.fullscreenControl, 'click', this.toggleFullscreen.bind(this));
  3122.         // addActiveStateSwitching(this.fullscreenControl);
  3123.         
  3124.         this.settingsMenu = document.createElement('div');
  3125.         if (Media.Detection.CSSBorderRadius() === false) {
  3126.             this.settingsMenuRoundRect = this.getRoundRectForArcAndOpacity(0.05, 0.9);
  3127.             this.settingsMenu.appendChild(this.settingsMenuRoundRect);
  3128.         }
  3129.  
  3130.         this.settingsMenu.id = 'ACMedia-settings-menu_'+this.timestamp;
  3131.         Element.addClassName(this.settingsMenu, 'ACMediaSettingsMenu');
  3132.         document.body.appendChild(this.settingsMenu);
  3133.         this.settingsMenu.baseClassName = 'ACMediaSettingsMenu';
  3134.         
  3135.         this.settingsMenuCarrot = document.createElement('div');
  3136.         Element.addClassName(this.settingsMenuCarrot, 'ACMediaSettingsMenuCarrot');
  3137.         this.settingsMenu.appendChild(this.settingsMenuCarrot);
  3138.         
  3139.         this.settingsMenuTitle = document.createElement('div');
  3140.         Element.addClassName(this.settingsMenuTitle, 'ACMediaSettingsMenuTitle');
  3141.         this.settingsMenu.appendChild(this.settingsMenuTitle);
  3142.         
  3143.         this.mediaController = get('ACMedia-media-controller');    
  3144.         
  3145.         this.speedDisplayAlert = document.createElement('div');
  3146.         this.captionsDisplayAlert = document.createElement('div');
  3147.         Element.addClassName(this.captionsDisplayAlert, 'ACMediaCaptionsDisplay');
  3148.         
  3149.         this.alertDisplayContainer = get('ACMedia-alert-display-container');
  3150.         this.trackText = get('ACMedia-track-text');
  3151.         this.trackTextSpan = get('ACMedia-track-text-span');
  3152.         this.volumeThumb = get('ACMedia-volume-handle');
  3153.         this.volumeTrack = get('ACMedia-volume-track');
  3154.         this.volumeProgress = get('ACMedia-control-volume-progress');
  3155.         this.trackContainer = get('ACMedia-track-container');
  3156.         this.playhead = get('ACMedia-control-playhead');
  3157.         this.track = get('ACMedia-control-track');
  3158.         this.trackProgress = get('ACMedia-control-track-progress');
  3159.         this.controlLoadedProgress = get('ACMedia-control-loaded-progress');
  3160.         this.mediaTimeDisplay = get('ACMedia-control-time-display');
  3161.         this.minutesPlayed = get('ACMedia-min-played');
  3162.         this.secondsPlayed = get('ACMedia-sec-played');
  3163.         this.mediaDurationDisplay = get('ACMedia-control-duration-display');
  3164.         this.minutesRemaining = get('ACMedia-min-remain');
  3165.         this.secondsRemaining = get('ACMedia-sec-remain');
  3166.     
  3167.         this.settingsMenuList = document.createElement('div');
  3168.         this.settingsMenu.appendChild(this.settingsMenuList);
  3169.  
  3170.         this.sizesMenu = document.createElement('ul');
  3171.         this.sizesMenu.menuName = 'sizes';
  3172.         this.sizesMenu.menuTitle = this.sizesControl.menuTitle = ac_media_language.sizescontrol || 'Video Size';
  3173.         
  3174.         this.downloadMenu = document.createElement('ul');
  3175.         this.downloadMenu.menuName = 'download';
  3176.         this.downloadMenu.menuTitle = this.downloadControl.menuTitle = ac_media_language.downloadcontrol || 'Download Video';
  3177.         
  3178.         this.shareMenu = document.createElement('ul');
  3179.         this.shareMenu.menuName = 'share';
  3180.         this.shareMenu.menuTitle = this.shareControl.menuTitle = ac_media_language.sharecontrol || 'Share Video';
  3181.         
  3182.         addBaseClassName(this.alertDisplayContainer);
  3183.         addBaseClassName(this.trackText);
  3184.         addBaseClassName(this.mediaTimeDisplay);
  3185.         addBaseClassName(this.mediaDurationDisplay);
  3186.         
  3187.         switch (this.controllerType) {
  3188.             case 'slim':
  3189.             case 'short-slim':
  3190.                 var trackContainerWidth = +(this.container.offsetWidth - 235);
  3191.                 if (AC.Detector.isWin()) {
  3192.                     trackContainerWidth = trackContainerWidth - 10;
  3193.                 }
  3194.                 this.trackContainer.style.width = trackContainerWidth + 'px';
  3195.                 break;
  3196.             default:
  3197.                 break;
  3198.         }
  3199.         // if (this.controllerType === 'slim' || this.controllerType === 'short-slim') {
  3200.         //     var trackContainerWidth = parseInt(this.container.offsetWidth - 235);
  3201.         //     if (AC.Detector.isWin()) {
  3202.         //         trackContainerWidth = trackContainerWidth - 10;
  3203.         //     }
  3204.         //     this.trackContainer.style.width = trackContainerWidth + 'px';
  3205.         // }
  3206.         
  3207.         addActiveStateSwitching(this.volumeThumb);
  3208.         //this.createVolumeScrubber();
  3209.         
  3210.         
  3211.         if (!this.scrubber && this.element !== null) {
  3212.             addActiveStateSwitching(this.playhead);
  3213.         }
  3214.         
  3215.     },
  3216.  
  3217.     SPECIAL_KEYS: [ "ESC", "COMMAND", "CONTROL", "OPTION", "ALT", "SHIFT" ],
  3218.     KEYS: {
  3219.             KEY_TAB: 9,
  3220.             KEY_ESCAPE: 27,
  3221.             KEY_SPACE: 32,
  3222.             KEY_PAGE_UP: 33,
  3223.             KEY_PAGE_DOWN: 34,
  3224.             KEY_END: 35,
  3225.             KEY_HOME: 36,
  3226.             KEY_LEFT_ARROW: 37,
  3227.             KEY_UP_ARROW: 38,
  3228.             KEY_RIGHT_ARROW: 39,
  3229.             KEY_DOWN_ARROW: 40,
  3230.             KEY_0: 48,
  3231.             KEY_1: 49,
  3232.             KEY_2: 50,
  3233.             KEY_C: 67,
  3234.             KEY_F: 70,
  3235.             KEY_R: 82,
  3236.             KEY_T: 84
  3237.         },
  3238.     _keyHandlerTimeout: null,
  3239.     keyDownHandler: function (evt) {
  3240.         var oEvent = window.event ? window.event : evt;
  3241.         var keyCode = (oEvent.keyCode) ? oEvent.keyCode : ( (oEvent.which) ? oEvent.which : 0);
  3242.  
  3243.         // for (var i =0;i<this.SPECIAL_KEYS.length;i++) {  // Quick reset
  3244.         //     showOrHide( this.SPECIAL_KEYS[i], false );
  3245.         // }
  3246.  
  3247.         // if (oEvent.shiftKey) { showOrHide( "SHIFT", true ); }
  3248.         // if (oEvent.ctrlKey) { showOrHide( "CONTROL", true ); }
  3249.         // if (oEvent.altKey) { showOrHide( "ALT", true ); }
  3250.         // if (oEvent.metaKey) { showOrHide( "COMMAND", true ); }
  3251.         // if (keyCode==this.KEYS.KEY_ESCAPE) { showOrHide( "ESC", true ); }
  3252.  
  3253.         window.clearTimeout(this._keyHandlerTimeout);
  3254.         
  3255.         var theAction = "";
  3256.         switch (true) {
  3257.             // Display size
  3258.             case ((keyCode == this.KEYS.KEY_0) && oEvent.ctrlKey):
  3259.                 Event.stop(evt);
  3260.                 this.selectSizeFromMenu(this.sizesSmallControl);
  3261.                 break;
  3262.             case ((keyCode == this.KEYS.KEY_1) && oEvent.ctrlKey):
  3263.                 Event.stop(evt);
  3264.                 this.selectSizeFromMenu(this.sizesMediumControl);
  3265.                 break;
  3266.             case ((keyCode == this.KEYS.KEY_2) && oEvent.ctrlKey):
  3267.                 Event.stop(evt);
  3268.                 this.selectSizeFromMenu(this.sizesLargeControl);
  3269.                 break;
  3270.             case ((keyCode == this.KEYS.KEY_3) && oEvent.ctrlKey):
  3271.                 Event.stop(evt);
  3272.                 this.selectSizeFromMenu(this.sizesHDControl);
  3273.                 break;
  3274.             // fullscreen removal
  3275.             // case ((keyCode == this.KEYS.KEY_F) && (oEvent.ctrlKey || oEvent.metaKey)):
  3276.             //     Event.stop(evt);
  3277.             //     this.toggleFullscreen();
  3278.             //     break;
  3279.             
  3280.             // Playback
  3281.             case (!Media.Detection.Firefox() && ((keyCode == this.KEYS.KEY_T) && oEvent.metaKey && oEvent.altKey)):
  3282.             case ((keyCode == this.KEYS.KEY_C) && oEvent.ctrlKey && oEvent.shiftKey):
  3283.                 Event.stop(evt);
  3284.                 this.toggleCaptions();
  3285.                 this._keyHandlerTimeout = window.setTimeout(this.hide.bind(this), 2500);
  3286.                 //timeout = window.setTimeout(this.removeAlertDisplay.bind(this), 2500);
  3287.                 break;
  3288.             case ((keyCode == this.KEYS.KEY_RIGHT_ARROW) && oEvent.metaKey):
  3289.                 Event.stop(evt);
  3290.                 this.show();
  3291.                 this.fastForward();
  3292.                 this._keyHandlerTimeout = window.setTimeout(this.hide.bind(this), 2500);
  3293.                 break;
  3294.             case ((keyCode == this.KEYS.KEY_LEFT_ARROW) && oEvent.metaKey):
  3295.                 Event.stop(evt);
  3296.                 this.show();
  3297.                 this.fastBackward();
  3298.                 this._keyHandlerTimeout = window.setTimeout(this.hide.bind(this), 2500);
  3299.                 break;
  3300.             case ((keyCode == this.KEYS.KEY_RIGHT_ARROW) && oEvent.altKey):  // Note: Windows should technically be (oEvent.ctrlKey && oEvent.altKey) here
  3301.                 Event.stop(evt);
  3302.                 this.show();
  3303.                 this.pause();
  3304.                 var value = +(1);
  3305.                 this.scrubber.setValue(value);
  3306.                 
  3307.                 if (!this._seeking) {
  3308.                     this._seeking = true;
  3309.                     this._send('beginSeeking');
  3310.                     this.resetRate();
  3311.                 }
  3312.                 this._send('setTime',+(value*this._send('duration')-0.1));
  3313.                 
  3314.                 window.setTimeout(function() {
  3315.                     this.trackProgress.style.width = +((this.scrubber.maximum*value)-4) + 'px';
  3316.                     this.playhead.style.left = +((this.scrubber.maximum*value)-4) + 'px';
  3317.                 }.bind(this), 50);
  3318.                 
  3319.                 this._keyHandlerTimeout = window.setTimeout(this.hide.bind(this), 2500);
  3320.                 break;
  3321.             case ((keyCode == this.KEYS.KEY_LEFT_ARROW) && oEvent.altKey):  // Note: Windows should technically be (oEvent.ctrlKey && oEvent.altKey) here
  3322.                 Event.stop(evt);
  3323.                 this.show();
  3324.                 this.pause();
  3325.                 var value = +(0);
  3326.                 this.scrubber.setValue(value);
  3327.                 
  3328.                 if (!this._seeking) {
  3329.                     this._seeking = true;
  3330.                     this._send('beginSeeking');
  3331.                     this.resetRate();
  3332.                 }
  3333.  
  3334.                 this._send('setTime',+(value*this._send('duration')+0.1));
  3335.                 window.setTimeout(function() {
  3336.                     this.trackProgress.style.width = value + 'px';
  3337.                     this.playhead.style.left = value + 'px';
  3338.                 }.bind(this), 50);
  3339.                 
  3340.                 this._keyHandlerTimeout = window.setTimeout(this.hide.bind(this), 2500);
  3341.                 break;
  3342.             case ((keyCode == this.KEYS.KEY_RIGHT_ARROW)):
  3343.                 break;
  3344.             case ((keyCode == this.KEYS.KEY_LEFT_ARROW)):
  3345.                 break;
  3346.             case (keyCode == this.KEYS.KEY_SPACE):
  3347.                 Event.stop(evt);
  3348.                 this.show();
  3349.                 this.togglePlaying();
  3350.                 this._keyHandlerTimeout = window.setTimeout(this.hide.bind(this), 2500);
  3351.                 break;
  3352.                 
  3353.             // Volume
  3354.             case ((keyCode == this.KEYS.KEY_UP_ARROW) && oEvent.altKey):    // Note: Windows should technically be (oEvent.ctrlKey && oEvent.altKey) here
  3355.                 Event.stop(evt);
  3356.                 this.show();
  3357.                 this.fullVolume();
  3358.                 this.volumeControlSetting = 1;
  3359.                 this._keyHandlerTimeout = window.setTimeout(this.hide.bind(this), 2500);
  3360.                 break;
  3361.             case ((keyCode == this.KEYS.KEY_DOWN_ARROW) && oEvent.altKey):    // Note: Windows should technically be (oEvent.ctrlKey && oEvent.altKey) here
  3362.                 Event.stop(evt);
  3363.                 this.show();
  3364.                 this.muteVolume();
  3365.                 this.volumeControlSetting = 0;
  3366.                 this._keyHandlerTimeout = window.setTimeout(this.hide.bind(this), 2500);
  3367.                 break;
  3368.             case (keyCode == this.KEYS.KEY_UP_ARROW):
  3369.                 Event.stop(evt);
  3370.                 this.show();
  3371.                 var volume = this._send('volume'),
  3372.                     volNumber = +(volume + .1),
  3373.                     newVolume = (volNumber < 1) ? volNumber : 1;
  3374.                 this._send('setVolume', newVolume);
  3375.                 this.volumeScrubber.setValue(newVolume);
  3376.                 this.volumeControlSetting = newVolume;
  3377.                 this._keyHandlerTimeout = window.setTimeout(this.hide.bind(this), 2500);
  3378.                 break;
  3379.             case (keyCode == this.KEYS.KEY_DOWN_ARROW):
  3380.                 Event.stop(evt);
  3381.                 this.show();
  3382.                 var volume = this._send('volume'),
  3383.                     volNumber = +(volume - .1),
  3384.                     newVolume = (volNumber > 0) ? volNumber : 0;
  3385.                 this._send('setVolume', newVolume);
  3386.                 this.volumeScrubber.setValue(newVolume);
  3387.                 this.volumeControlSetting = newVolume;
  3388.                 this._keyHandlerTimeout = window.setTimeout(this.hide.bind(this), 2500);
  3389.                 break;
  3390.                 
  3391.             // reload
  3392.             case ((keyCode == this.KEYS.KEY_R) && oEvent.metaKey):
  3393.                 Event.stop(evt);
  3394.                 window.location.reload(false);
  3395.                 break;
  3396.             default:
  3397.                 return true;
  3398.                 break;
  3399.  
  3400.         }
  3401.         
  3402.  
  3403.     },
  3404.  
  3405.     createTrackScrubber: function() {
  3406.         // Playback Slider
  3407.         if(this.track) {
  3408.             var max = this.track.offsetWidth;
  3409.             if (!this.scrubber && this.element !== null) {
  3410.                 this.scrubber = new Control.Slider(this.playhead, this.track, {
  3411.                     alignX: -5,
  3412.                     increment: 1,
  3413.                     sliderValue: 0,
  3414.                     minimum: 0,
  3415.                     maximum: max,
  3416.                     onSlide: function (value) {
  3417.                         if (!this._seeking) {
  3418.                             this._seeking = true;
  3419.                             this._send('beginSeeking');
  3420.                             this.resetRate();
  3421.                         }
  3422.                         this._send('setTime',value*this._send('duration'));
  3423.                         this.trackProgress.style.width = this.playhead.style.left;
  3424.                     }.bind(this),
  3425.                     onChange: function (value) {
  3426.                         if (this._seeking) {
  3427.                             this._seeking = false;
  3428.                             this._send('endSeeking');
  3429.                         }
  3430.                         this.trackProgress.style.width = this.playhead.style.left;
  3431.                     }.bind(this)
  3432.                 });
  3433.             }
  3434.         }
  3435.     },
  3436.     createVolumeScrubber: function() {
  3437.         // Volume Slider
  3438.         if (!this.volumeScrubber && this.element !== null) {
  3439.             var max = this.volumeTrack.offsetWidth;
  3440.             this.volumeScrubber = new Control.Slider(this.volumeThumb, this.volumeTrack, {
  3441.                 alignX: -3,
  3442.                 increment: 1,
  3443.                 sliderValue: 0,
  3444.                 minimum: 0,
  3445.                 maximum: max,
  3446.                 onSlide: function (value) {
  3447.                     this._volSeeking = true;
  3448.                     this._send('setVolume', value);
  3449.                     this.volumeProgress.style.width = this.volumeThumb.style.left;
  3450.                 }.bind(this),
  3451.                 onChange: function (value) {
  3452.                     this._volSeeking = false;
  3453.                     this.volumeProgress.style.width = this.volumeThumb.style.left;
  3454.                 }.bind(this)
  3455.             });
  3456.  
  3457.             if (typeof this.volumeControlSetting == 'undefined') {
  3458.                 this.volumeControlSetting = 1;
  3459.             }
  3460.             
  3461.             this.volumeScrubber.setValue(this.volumeControlSetting);
  3462.         }
  3463.     },
  3464.     
  3465.     getRoundRectForArcAndOpacity: function(arc, opacity) {
  3466.         if (Media.Detection.CSSBorderRadius() !== false) {
  3467.             return false;
  3468.         }
  3469.         
  3470.         if (typeof this.hasVMLNameSpaceDefined == 'undefined' || this.hasVMLNameSpaceDefined == false) {
  3471.             this.setVML();
  3472.         }
  3473.  
  3474.         var roundRect = document.createElement('v:roundrect'),
  3475.             fill = document.createElement('v:fill');
  3476.         
  3477.         roundRect.setAttribute('arcsize', arc);
  3478.         roundRect.setAttribute('fill', 'true');
  3479.         roundRect.setAttribute('fillcolor', '#000000');
  3480.         roundRect.setAttribute('stroked', 'false');
  3481.         roundRect.className = 'border-radius-box';
  3482.         
  3483.         fill.setAttribute('type', 'background');
  3484.         fill.setAttribute('opacity', opacity);
  3485.         fill.className = 'border-radius-fill';
  3486.  
  3487.         if (typeof roundRect == 'object') {
  3488.             roundRect.appendChild(fill);
  3489.             return roundRect;
  3490.         } else {
  3491.             return false;
  3492.         }
  3493.         
  3494.         //return (typeof roundRect == 'object') ? roundRect : false;
  3495.     },
  3496.     
  3497.     setVML: function() {
  3498.         if (!document.namespaces) {
  3499.             return;
  3500.         }
  3501.         
  3502.         var i, countI, style, 
  3503.             head = document.getElementsByTagName('head')[0];
  3504.             
  3505.         this.hasVMLNameSpaceDefined = false;
  3506.  
  3507.         for (i=0, countI=document.namespaces.length; i<countI; i++) { 
  3508.             if (document.namespaces(i).name == 'v') {
  3509.                 this.hasVMLNameSpaceDefined = true;
  3510.                 break;
  3511.             }
  3512.         }
  3513.         //<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v" />
  3514.  
  3515.         if (!this.hasVMLNameSpaceDefined) {
  3516.             document.namespaces.add('v', 'urn:schemas-microsoft-com:vml');
  3517.         }
  3518.         
  3519.  
  3520.     },
  3521.     
  3522.     setCaptionsAvailable: function() {
  3523.         this._send('setCaptionsAvailable', this.captionsUrl);
  3524.     },
  3525.     _setControlsAvailableForMenu: function(mainControl, controls) {
  3526.         mainControl.menuListHeight = 0;
  3527.         
  3528.         for (var i=0, control; control=controls[i]; i++) {
  3529.             this._enableControl(control);
  3530.             mainControl.menuListHeight += 25;
  3531.         }
  3532.         
  3533.         switch(mainControl) {
  3534.             case this.sizesControl:
  3535.                 this.enableSizesControl();
  3536.                 break;
  3537.             case this.downloadControl:
  3538.                 this.enableDownloadControl();
  3539.                 break;
  3540.             case this.shareControl:
  3541.                 this.enableShareControl();
  3542.                 break;
  3543.             default:
  3544.                 break;
  3545.         }
  3546.     },
  3547.     setSizesAvailable: function() {
  3548.         this._setControlsAvailableForMenu(this.sizesControl, this._sizesMenuControls);
  3549.     },
  3550.     setDownloadAvailable: function() {
  3551.         this._setControlsAvailableForMenu(this.downloadControl, this._downloadMenuControls);
  3552.     },
  3553.     setShareAvailable: function() {
  3554.         this._setControlsAvailableForMenu(this.shareControl, this._shareMenuControls);
  3555.     },
  3556.     // fullscreen removal
  3557.     // setFullscreenAvailable: function() {
  3558.     //     this._send('setFullscreenAvailable', this.fullscreenUrl);
  3559.     // },
  3560.     
  3561.     enableBasicControls: function() {
  3562.         if(this.playControl) {
  3563.             Element.hide(this.playControl);
  3564.         }
  3565.         if(this.pauseControl) {
  3566.             Element.show(this.pauseControl);
  3567.         }
  3568.         
  3569.         this._enableControl(this.volumeMuteControl);
  3570.         this._enableControl(this.volumeFullControl);
  3571.         this._enableControl(this.volumeThumb);
  3572.         this._enableControl(this.playControl);
  3573.         this._enableControl(this.pauseControl);
  3574.         this._enableControl(this.playhead);
  3575.         this._enableControl(this.fastBackwardControl);
  3576.         this._enableControl(this.fastForwardControl);
  3577.  
  3578.         this.createTrackScrubber();
  3579.         
  3580.         this._enableControl(this.mediaTimeDisplay);
  3581.         this._enableControl(this.mediaDurationDisplay);
  3582.     },
  3583.     enableCaptionsControl: function() {
  3584.         if (!this.captionsControl.isEnabled && this.controllerType !== 'short-slim' && !this.captionsControl.isEnabled && !(typeof this.options != 'undefined' && this.options.captionsControlOff === true)) {
  3585.  
  3586.             Element.addClassName(this.captionsControl, this.captionsControl.baseClassName + '-enabled');
  3587.             this.captionsControl.isEnabled = true;
  3588.             
  3589.             this.setSettingsControlsClass();
  3590.         }
  3591.     },
  3592.     _enableSettingsControlWithMenu: function(control, menu) {
  3593.         if (!control.isEnabled && this.controllerType !== 'short-slim' && !(typeof this.options != 'undefined' && this.options[control.name+'Off'] === true)) {
  3594.             this.settingsMenuList.appendChild(menu);
  3595.             control.menuListWidth = (AC.Detector.isIEStrict()) ? 165 : this.settingsMenuList.offsetWidth;
  3596.             this.settingsMenuList.removeChild(menu);
  3597.  
  3598.             Element.addClassName(control, control.baseClassName + '-enabled');
  3599.             control.isEnabled = true;
  3600.             
  3601.             this.setSettingsControlsClass();
  3602.         }
  3603.     },
  3604.     enableSizesControl: function() {
  3605.         this.sizesControl.name = 'sizesControl';
  3606.         this._enableSettingsControlWithMenu(this.sizesControl, this.sizesMenu);
  3607.     },
  3608.     enableDownloadControl: function() {
  3609.         this.downloadControl.name = 'downloadControl';
  3610.         this._enableSettingsControlWithMenu(this.downloadControl, this.downloadMenu);
  3611.     },
  3612.     enableShareControl: function() {
  3613.         this.shareControl.name = 'shareControl';
  3614.         this._enableSettingsControlWithMenu(this.shareControl, this.shareMenu);
  3615.     },
  3616.     // fullscreen removal
  3617.     // enableFullscreenControl: function() {
  3618.     //     //console.log('before if in enablefullscreencontrol');
  3619.     //     if (!this.fullscreenControl.isEnabled && this.controllerType !== 'short-slim' && !(typeof this.options != 'undefined' && this.options.fullscreenControlOff === true)) {
  3620.     //         //console.log('enabling fullscreen');
  3621.     //         Element.addClassName(this.fullscreenControl, this.fullscreenControl.baseClassName + '-enabled');
  3622.     //         this.fullscreenControl.isEnabled = true;
  3623.     //         
  3624.     //         this.setSettingsControlsClass();
  3625.     //     }
  3626.     // },
  3627.     
  3628.     togglePlaying: function () {
  3629.         var isPlaying = this._send('playing');
  3630.  
  3631.         if (isPlaying) {
  3632.             this.pause();
  3633.         } else {
  3634.             this.resetRate();
  3635.             this.play();
  3636.         }
  3637.     },
  3638.     toggleCaptions: function() {
  3639.         if (!Element.hasClassName(this.captionsControl, this.captionsControl.baseClassName + '-selected') && !this.resettingController && this.captionsControl.isEnabled === true) {
  3640.             this._selectControl(this.captionsControl);
  3641.             if (this._send('movieType') === 'Video' && this._send('enableCaptionsTextDisplay') === false) {
  3642.                 this._enableControl(this.trackText);
  3643.             }
  3644.             this._send('enableCaptions');
  3645.             var captionsText = ac_media_language.captionsturnedon || 'Closed Captions On';
  3646.  
  3647.             // using while loops to remove children of elements so they aren't completely erased in IE6
  3648.             while (typeof this.alertDisplayContainer.firstChild != 'undefined' && this.alertDisplayContainer.firstChild != null) {
  3649.                 this.alertDisplayContainer.removeChild(this.alertDisplayContainer.firstChild);
  3650.             }
  3651.             
  3652.             if (Media.Detection.CSSBorderRadius() === false) {
  3653.                 var roundRect = this.getRoundRectForArcAndOpacity(0.19, 0.5);
  3654.             }
  3655.             
  3656.             if (typeof roundRect != 'undefined' && roundRect !== false) {
  3657.                 var textSpan = document.createElement('span');
  3658.                 
  3659.                 this.captionsDisplayAlert.innerHTML = '';
  3660.                 textSpan.appendChild(document.createTextNode(captionsText));
  3661.                 roundRect.appendChild(textSpan);
  3662.                 this.captionsDisplayAlert.appendChild(roundRect);
  3663.             } else {
  3664.                 this.captionsDisplayAlert.innerHTML = captionsText;
  3665.             }
  3666.  
  3667.             this.alertDisplayContainer.appendChild(this.captionsDisplayAlert);
  3668.             Element.addClassName(this.alertDisplayContainer, this.alertDisplayContainer.baseClassName + '-active');
  3669.             this.captionsControlSetting = true;
  3670.         } else if (this.captionsControl.isEnabled === true) {
  3671.             this._unselectControl(this.captionsControl);
  3672.             this._disableControl(this.trackText);
  3673.             this.captionsControlSetting = false;
  3674.             if (this.resettingController === true) {
  3675.                 this._send('resetCaptions');
  3676.             } else { 
  3677.                 this._send('disableCaptions');
  3678.                 var captionsText = ac_media_language.captionsturnedoff || 'Closed Captions Off';
  3679.  
  3680.                 while (typeof this.alertDisplayContainer.firstChild != 'undefined' && this.alertDisplayContainer.firstChild != null) {
  3681.                     this.alertDisplayContainer.removeChild(this.alertDisplayContainer.firstChild);
  3682.                 }
  3683.  
  3684.                 var roundRect = this.getRoundRectForArcAndOpacity(0.19, 0.5);
  3685.                 
  3686.                 if (roundRect !== false) {
  3687.                     var textSpan = document.createElement('span');
  3688.                     
  3689.                     this.captionsDisplayAlert.innerHTML = '';
  3690.                     textSpan.appendChild(document.createTextNode(captionsText));
  3691.                     roundRect.appendChild(textSpan);
  3692.                     this.captionsDisplayAlert.appendChild(roundRect);
  3693.                 } else {
  3694.                     this.captionsDisplayAlert.innerHTML = captionsText;
  3695.                 }
  3696.  
  3697.                 this.alertDisplayContainer.appendChild(this.captionsDisplayAlert);
  3698.                 Element.addClassName(this.alertDisplayContainer, this.alertDisplayContainer.baseClassName + '-active');
  3699.             }
  3700.         }
  3701.     },
  3702.     _toggleMenuForControlAndMenuControls: function(menu, control, menuControls) {
  3703.         if (!Element.hasClassName(control, control.baseClassName + '-selected') && !this.resettingMenus && !this.resettingController) {
  3704.             this._selectControl(control);
  3705.             this._selectSettingsMenuForMenu(menu);
  3706.             this.positionSettingsMenuForControl(control);
  3707.         } else {
  3708.             this._unselectControl(control);
  3709.             this._unselectMenu();
  3710.             if (this.resettingController === true) {
  3711.                 for (var i=0, menuControl; menuControl = menuControls[i]; i++) {
  3712.                     this._unselectControl(menuControl);
  3713.                 }
  3714.             }
  3715.         }
  3716.     },
  3717.     toggleSizesMenu: function() {
  3718.         if (this.sizesControl && this.sizesControl.isEnabled === true && this.sizesMenu) {
  3719.             this._toggleMenuForControlAndMenuControls(this.sizesMenu, this.sizesControl, this._sizesMenuControls);
  3720.         }
  3721.     },
  3722.     toggleDownloadMenu: function() {
  3723.         if (this.downloadControl && this.downloadControl.isEnabled === true && this.downloadMenu) {
  3724.             this._toggleMenuForControlAndMenuControls(this.downloadMenu, this.downloadControl, this._downloadMenuControls);
  3725.         }
  3726.     },
  3727.     toggleShareMenu: function() {
  3728.         if (this.shareControl && this.shareControl.isEnabled === true && this.shareMenu) {
  3729.             this._toggleMenuForControlAndMenuControls(this.shareMenu, this.shareControl, this._shareMenuControls);
  3730.         }
  3731.     },
  3732.     // fullscreen removal
  3733.     // toggleFullscreen: function() {
  3734.     //     if (!this.resettingController && this.fullscreenControl.isEnabled === true) {
  3735.     //         this._send('enableFullscreen');
  3736.     //     }
  3737.     // },
  3738.     
  3739.     volumeControlSetting: 1,
  3740.     // fullscreen removal
  3741.     // fullscreenControlSetting: false,
  3742.     sizesControlSetting: false,
  3743.     setSettingsControls: function() {
  3744.         // fullscreen removal
  3745.         // if (typeof this.fullscreenControlSetting != 'undefined' && this.fullscreenControlSetting != false) {
  3746.         //     this._send('enableFullscreen');
  3747.         // }
  3748.         if (typeof this.sizesControlSetting != 'undefined' && this.sizesControlSetting != false) {
  3749.             this.selectSizeFromMenu(this.sizesControlSetting);
  3750.         }
  3751.         if (typeof this.volumeControlSetting != 'undefined' && this.volumeControlSetting != 1) {
  3752.             this.volumeScrubber.setValue(this.volumeControlSetting);
  3753.             this._send('setVolume', this.volumeControlSetting);
  3754.         }
  3755.     },
  3756.     
  3757.     mouseoverSettingsControl: function(control) {
  3758.         this.settingsMenuTitle.innerHTML = control.menuTitle;
  3759.         if (typeof this.currentMenu != 'undefined' && this.currentMenu != false) {
  3760.             if (this.settingsMenuList.childNodes.length > 0) {
  3761.                 this.settingsMenuList.removeChild(this.currentMenu);
  3762.             }
  3763.             this.currentMenu = false;
  3764.         }
  3765.  
  3766.         this.positionSettingsMenuForControl(control);
  3767.         Element.addClassName(this.settingsMenu, this.settingsMenu.baseClassName+'-hovered');
  3768.         Element.removeClassName(this.settingsMenu, this.settingsMenu.baseClassName);
  3769.         this._unselectControl(this.sizesControl);
  3770.         this._unselectControl(this.downloadControl);
  3771.         this._unselectControl(this.shareControl);
  3772.     },
  3773.     mouseoutSettingsControl: function(evt, control) {
  3774.         return;
  3775.         var evt = evt || window.event,
  3776.             menuTop = Element.cumulativeOffset(this.settingsMenu).top,
  3777.             menuLeft = Element.cumulativeOffset(this.settingsMenu).left,
  3778.             menuWidth = this.settingsMenu.offsetWidth,
  3779.             menuHeight = this.settingsMenu.offsetHeight,
  3780.             mouseX, mouseY;
  3781.  
  3782.         if (evt) {
  3783.             mouseX = evt.pageX || (evt.clientX + (document.documentElement.scrollLeft) ? document.documentElement.scrollLeft : document.body.scrollLeft);
  3784.             mouseY = evt.pageY || (evt.clientY + (document.documentElement.scrollTop) ? document.documentElement.scrollTop : document.body.scrollTop);
  3785.             
  3786.             if (!(mouseX > menuLeft && mouseX < (menuLeft + menuWidth) && mouseY > menuTop && mouseY < (menuTop + menuHeight + 14))) {
  3787.                 Element.addClassName(this.settingsMenu, this.settingsMenu.baseClassName);
  3788.                 Element.removeClassName(this.settingsMenu, this.settingsMenu.baseClassName+'-hovered');            
  3789.             }
  3790.         }
  3791.     },
  3792.     
  3793.     positionSettingsMenuForControl: function(control) {
  3794.         this.positionCarrotForControl(control);
  3795.         if (typeof this.settingsMenuRoundRect != 'undefined' && this.settingsMenuRoundRect !== false) {
  3796.             var items = this.settingsMenuList.getElementsByTagName('li'),
  3797.                 width = control.menuListWidth,
  3798.                 height = parseInt(((items.length > 0) ? 22 : 0) + this.settingsMenuTitle.offsetHeight + (items.length * 25)),
  3799.                 arc = Math.min((7 / Math.min(height, width)), 1).toFixed(2),
  3800.                 settingsMenuChildren = this.settingsMenu.childNodes,
  3801.                 node = this.settingsMenu.node;
  3802.  
  3803.             try{
  3804.                 while(typeof this.settingsMenuRoundRect != 'undefined' && this.settingsMenuRoundRect.firstChild) {
  3805.                     this.settingsMenuRoundRect.removeChild(this.settingsMenuRoundRect.firstChild);
  3806.                 }
  3807.             } catch(e) {}
  3808.             
  3809.             this.settingsMenu.removeChild(this.settingsMenuRoundRect);
  3810.  
  3811.             //alert('in positionSettingsMenuForControl')
  3812.             this.settingsMenuRoundRect = this.getRoundRectForArcAndOpacity(arc, 0.9);
  3813.             
  3814.             this.settingsMenu.insertBefore(this.settingsMenuRoundRect, this.settingsMenu.firstChild);
  3815.             
  3816.             if (width && height) {
  3817.                 this.settingsMenuList.style.display = 'block';
  3818.                 this.settingsMenu.style.width = width + 'px';
  3819.                 this.settingsMenu.style.height = height + 'px';
  3820.             } else {
  3821.                 this.settingsMenu.style.display = 'none';
  3822.             }
  3823.         
  3824.         } else if (typeof control.menuListWidth != 'undefined') {
  3825.             this.settingsMenuList.style.width = control.menuListWidth + 'px';
  3826.         }
  3827.         
  3828.         var carrotTop = parseInt(this.settingsMenuCarrot.style.top),
  3829.             carrotLeft = parseInt(this.settingsMenuCarrot.style.left),
  3830.             menuHeight = this.settingsMenu.offsetHeight,
  3831.             menuWidth = this.settingsMenu.offsetWidth,
  3832.             mediaControllerLeft = Element.cumulativeOffset(this.mediaController).left,
  3833.             mediaControllerWidth = this.mediaController.offsetWidth,
  3834.             carrotHeight = this.settingsMenuCarrot.offsetHeight,
  3835.             carrotWidth = this.settingsMenuCarrot.offsetWidth,
  3836.             menuTop = carrotTop - menuHeight + carrotHeight,
  3837.             menuLeft = (mediaControllerLeft + mediaControllerWidth) - menuWidth,
  3838.             controlLeft = Element.cumulativeOffset(control).left,
  3839.             controlCenter = controlLeft + (control.offsetWidth / 2),
  3840.             newMenuLeft, newMenuBottom, newCarrotTop, newCarrotLeft, menuListWidth;
  3841.             
  3842.         switch (this.controllerType) {
  3843.             case 'slim':
  3844.             case 'short-slim':
  3845.                 var slimMenuLeft = (mediaControllerLeft + mediaControllerWidth + 20) - menuWidth;
  3846.                 this.settingsMenu.style.top = (carrotTop + carrotHeight) + 'px';
  3847.                 this.settingsMenu.style.left = ((slimMenuLeft < carrotLeft) ? slimMenuLeft : carrotLeft) + 'px';
  3848.                 break;
  3849.             default:
  3850.                 this.settingsMenu.style.top = menuTop + 'px';
  3851.                 this.settingsMenu.style.left = ((menuLeft - 7 < carrotLeft) ? (menuLeft - 7) : carrotLeft) + 'px';
  3852.                 break;
  3853.         }        
  3854.         // if (this.controllerType === 'slim' || this.controllerType === 'short-slim') {
  3855.         //     var slimMenuLeft = (mediaControllerLeft + mediaControllerWidth + 20) - menuWidth;
  3856.         //     this.settingsMenu.style.top = (carrotTop + carrotHeight) + 'px';
  3857.         //     this.settingsMenu.style.left = ((slimMenuLeft < carrotLeft) ? slimMenuLeft : carrotLeft) + 'px';
  3858.         // } else {
  3859.         //     this.settingsMenu.style.top = menuTop + 'px';
  3860.         //     this.settingsMenu.style.left = ((menuLeft - 7 < carrotLeft) ? (menuLeft - 7) : carrotLeft) + 'px';
  3861.         //     //this.settingsMenu.style.left = parseInt(controlCenter - (menuWidth / 2)) + 'px';
  3862.         // }
  3863.                 
  3864.         newMenuLeft = parseInt(this.settingsMenu.style.left);
  3865.         
  3866.         newCarrotTop = menuHeight;
  3867.         newCarrotLeft = parseInt(this.settingsMenuCarrot.style.left) - newMenuLeft;
  3868.         
  3869.         switch (this.controllerType) {
  3870.             case 'slim':
  3871.             case 'short-slim':
  3872.                 this.settingsMenuCarrot.style.top = (0 - (carrotHeight + 6)) + 'px';
  3873.                 break;
  3874.             default:
  3875.                 this.settingsMenuCarrot.style.top = ((AC.Detector.isIEStrict()) ? ((menuHeight - carrotHeight) + 8) : (menuHeight - carrotHeight)) + 'px';
  3876.                 break;
  3877.         }
  3878.         // if (this.controllerType === 'slim' || this.controllerType === 'short-slim') {
  3879.         //     this.settingsMenuCarrot.style.top = (0 - (carrotHeight + 6)) + 'px';
  3880.         // } else {
  3881.         //     this.settingsMenuCarrot.style.top = (AC.Detector.isIEStrict()) ? ((menuHeight - carrotHeight) + 8) + 'px' : (menuHeight - carrotHeight) + 'px';
  3882.         // }
  3883.         this.settingsMenuCarrot.style.left = (newCarrotLeft - (carrotWidth / 2)) + 'px';
  3884.         
  3885.         this.settingsMenu.style.overflow = 'visible';
  3886.  
  3887.     },
  3888.     positionCarrotForControl: function(control) {
  3889.         
  3890.         var mediaControllerTop = Element.cumulativeOffset(this.mediaController).top,
  3891.             mediaControllerWidth = this.mediaController.offsetWidth,
  3892.             mediaControllerHeight = this.mediaController.offsetHeight,
  3893.             controlLeft = Element.cumulativeOffset(control).left,
  3894.             controlWidth = control.offsetWidth,
  3895.             carrotWidth = this.settingsMenuCarrot.offsetWidth,
  3896.             carrotHeight = this.settingsMenuCarrot.offsetHeight,
  3897.             carrotTop = mediaControllerTop - carrotHeight,
  3898.             carrotLeft = controlLeft + ((controlWidth - carrotWidth) / 2);
  3899.             
  3900.         this.settingsMenu.style.overflow = 'hidden';
  3901.         switch (this.controllerType) {
  3902.             case 'slim':
  3903.             case 'short-slim':
  3904.                 Element.addClassName(this.settingsMenuCarrot, 'slim-menu-carrot');
  3905.                 this.settingsMenuCarrot.style.top = (mediaControllerTop + mediaControllerHeight) + 'px';
  3906.                 break;
  3907.             default:
  3908.                 this.settingsMenuCarrot.style.top = carrotTop + 'px';
  3909.                 break;
  3910.         }
  3911.         // if (this.controllerType === 'slim' || this.controllerType === 'short-slim') {
  3912.         //     Element.addClassName(this.settingsMenuCarrot, 'slim-menu-carrot');
  3913.         //     this.settingsMenuCarrot.style.top = (mediaControllerTop + mediaControllerHeight) + 'px';
  3914.         // } else {
  3915.         //     this.settingsMenuCarrot.style.top = carrotTop + 'px';
  3916.         // }
  3917.         this.settingsMenuCarrot.style.left = carrotLeft + 'px';
  3918.     },
  3919.     
  3920.     _selectSettingsMenuForMenu: function(menu) {
  3921.         var menuTitle = menu.menuTitle,
  3922.             menuName = menu.menuName;
  3923.  
  3924.         this.settingsMenuTitle.innerHTML = menuTitle;
  3925.  
  3926.         if (typeof this.currentMenu != 'undefined' && this.currentMenu != false) {
  3927.             if (this.settingsMenuList.childNodes > 0) {
  3928.                 this.settingsMenuList.removeChild(this.currentMenu);
  3929.             }
  3930.         }
  3931.  
  3932.         this.settingsMenuList.appendChild(menu);
  3933.         this.currentMenu = menu;
  3934.     },
  3935.     _unselectMenu: function() {
  3936.         Element.addClassName(this.settingsMenu, this.settingsMenu.baseClassName);
  3937.         Element.removeClassName(this.settingsMenu, this.settingsMenu.baseClassName+'-selected');
  3938.         Element.removeClassName(this.settingsMenu, this.settingsMenu.baseClassName+'-hovered');
  3939.     },
  3940.     _selectControl: function(control) {
  3941.         Element.addClassName(control, control.baseClassName+'-selected');
  3942.         if (control === this.sizesControl || control === this.downloadControl || control === this.shareControl) {
  3943.             Element.addClassName(this.settingsMenu, this.settingsMenu.baseClassName+'-selected');
  3944.             Element.removeClassName(this.settingsMenu, this.settingsMenu.baseClassName);
  3945.             Element.removeClassName(this.settingsMenu, this.settingsMenu.baseClassName+'-hovered');
  3946.             this._currentSettingsControl = control;
  3947.         }
  3948.     },
  3949.     _unselectControl: function(control) {
  3950.         if(control) {
  3951.             Element.removeClassName(control, control.baseClassName+'-selected');
  3952.         }
  3953.     },
  3954.     _enableControl: function(control) {
  3955.         if(control) {
  3956.             Element.addClassName(control, control.baseClassName+'-enabled');
  3957.         }
  3958.     },
  3959.     _disableControl: function(control) {
  3960.         if(control) {
  3961.             Element.removeClassName(control, control.baseClassName+'-enabled');
  3962.          }
  3963.     },
  3964.     
  3965.     reset: function () {
  3966.         if (typeof this.scrubber != 'undefined') {
  3967.             this.playhead.style.left = '0px';
  3968.             this.trackProgress.style.width = this.playhead.style.left;
  3969.         
  3970.             this.show();
  3971.         
  3972.             if(this.playControl) {
  3973.                 Element.show(this.playControl);
  3974.             }
  3975.             if(this.pauseControl) {
  3976.                 Element.hide(this.pauseControl);
  3977.             }
  3978.         
  3979.             this._disableControl(this.volumeMuteControl);
  3980.             this._disableControl(this.volumeFullControl);
  3981.             this._disableControl(this.volumeThumb);
  3982.             this._disableControl(this.playControl);
  3983.             this._disableControl(this.pauseControl);
  3984.             this._disableControl(this.playhead);
  3985.             this._disableControl(this.fastBackwardControl);
  3986.             this._disableControl(this.fastForwardControl);
  3987.         
  3988.             this.removeAdvancedPlayDisplay();
  3989.         }
  3990.     },
  3991.     resetSettingsControls: function() {
  3992.         this.resetSettingsMenus();
  3993.     },
  3994.     resetSettingsMenus: function() {
  3995.         this.resettingMenus = true;
  3996.         if(this.alertDisplayContainer) {
  3997.             Element.removeClassName(this.alertDisplayContainer, this.alertDisplayContainer.baseClassName + '-active');
  3998.         }
  3999.         if(this.settingsMenu) {
  4000.             Element.removeClassName(this.settingsMenu, this.settingsMenu.baseClassName+'-hovered');
  4001.             Element.removeClassName(this.settingsMenu, this.settingsMenu.baseClassName+'-selected');
  4002.         }
  4003.         this.toggleSizesMenu();
  4004.         this.toggleDownloadMenu();
  4005.         this.toggleShareMenu();
  4006.         this.resettingMenus = false;
  4007.     },
  4008.     resetRate: function() {
  4009.         if (this._send('rate') !== 1) {
  4010.             this.removeAdvancedPlayDisplay();        
  4011.             this._send('setRate', 1);
  4012.         }        
  4013.     },
  4014.     
  4015.     removeAdvancedPlayDisplay: function() {
  4016.         this.removeAlertDisplay();
  4017.         Element.removeClassName(this.fastBackwardControl, 'fastBackward-active');
  4018.         Element.removeClassName(this.fastForwardControl, 'fastForward-active');
  4019.     },
  4020.     removeAlertDisplay: function () {
  4021.         if(this.fastBackwardControl) {
  4022.             this.setRateDisplay(this.fastBackwardControl, null);
  4023.         }
  4024.         if(this.fastForwardControl) {
  4025.             this.setRateDisplay(this.fastForwardControl, null);
  4026.         }
  4027.         if(this.alertDisplayContainer) {
  4028.             //alert(this.alertDisplayContainer.baseClassName + '-active')
  4029.             Element.removeClassName(this.alertDisplayContainer, this.alertDisplayContainer.baseClassName + '-active');    
  4030.         }
  4031.     },
  4032.     
  4033.     setSettingsControlsClass: function() {
  4034.         var settingsControlsClass = this.settingsControls.baseClassName,
  4035.             buttonCount = 0;
  4036.         if (typeof this.captionsControl.isEnabled != 'undefined' && this.captionsControl.isEnabled === true) {
  4037.             settingsControlsClass += '-captions';
  4038.             buttonCount++;
  4039.         }
  4040.         if (typeof this.sizesControl.isEnabled != 'undefined' && this.sizesControl.isEnabled === true) {
  4041.             settingsControlsClass += '-sizes';
  4042.             buttonCount++;
  4043.         }        
  4044.         if (typeof this.downloadControl.isEnabled != 'undefined' && this.downloadControl.isEnabled === true) {
  4045.             settingsControlsClass += '-download';
  4046.             buttonCount++;
  4047.         }
  4048.         if (typeof this.shareControl.isEnabled != 'undefined' && this.shareControl.isEnabled === true) {
  4049.             settingsControlsClass += '-share';
  4050.             buttonCount++;
  4051.         }
  4052.         // fullscreen removal
  4053.         // if (typeof this.fullscreenControl.isEnabled != 'undefined' && this.fullscreenControl.isEnabled === true) {
  4054.         //     settingsControlsClass += '-fullscreen';
  4055.         //     buttonCount++;
  4056.         // }
  4057.         
  4058.         this.settingsControls.className = '';
  4059.         Element.addClassName(this.settingsControls, this.settingsControls.baseClassName);
  4060.         Element.addClassName(this.settingsControls, settingsControlsClass);
  4061.         
  4062.         this.setTrackContainerWidth();
  4063.     },
  4064.     
  4065.     setTrackContainerWidth: function() {
  4066.         if (this.controllerType === 'regular' || !this.settingsControls || !this.trackContainer ) {
  4067.             return;
  4068.         }
  4069.         // if (this.controllerType === 'slim' || this.controllerType === 'short-slim') {
  4070.  
  4071.             var buttonWidth = (this.settingsControls.offsetWidth > 0) ? parseInt(this.settingsControls.offsetWidth + 10) : 0,
  4072.                 controllerLeft = this.mediaController.offsetLeft,
  4073.                 controllerWidth = this.mediaController.offsetWidth,
  4074.                 controllerRight = parseInt(controllerLeft + controllerWidth);
  4075.                 newTrackWidth = parseInt(((controllerRight - this.trackContainer.offsetLeft) <= 600) ? (controllerRight - this.trackContainer.offsetLeft) : 600),
  4076.                 newTrackContainerWidth = parseInt(newTrackWidth - (buttonWidth + 10));
  4077.             
  4078.             // this is to make sure that the track doesn't go past the right edge for the slim controller
  4079.             if (this.controllerType === 'slim') {
  4080.                 var trackRight = parseInt(this.trackContainer.offsetLeft + newTrackContainerWidth + 20);
  4081.                 if (controllerRight < trackRight) {
  4082.                     newTrackContainerWidth = parseInt(newTrackContainerWidth - (trackRight - controllerRight));
  4083.                 }
  4084.             }
  4085.             
  4086.             this.trackContainer.style.width =  newTrackContainerWidth + 'px';
  4087.             this.track.parentNode.style.width = (this.controllerType === 'short-slim') ? newTrackContainerWidth + 'px' : parseInt(newTrackContainerWidth - 80) + 'px';
  4088.             this.scrubberMax = (this.controllerType === 'short-slim') ? newTrackContainerWidth : parseInt(newTrackContainerWidth - 80);
  4089.             this.volumeScrubber = null;
  4090.             this.createVolumeScrubber();
  4091.             this.scrubber = null;
  4092.             this.createTrackScrubber();
  4093.         // }
  4094.     },
  4095.     
  4096.     _send: function (msg, params) {
  4097.         if (this.delegate && msg in this.delegate) {
  4098.             params = [].concat(params);
  4099.             return this.delegate[msg].apply(this.delegate, params);
  4100.         }
  4101.     },
  4102.     
  4103.     show: function () {
  4104.         Media.ControlsWidget.show(this);
  4105.     },
  4106.     
  4107.     hide: function () {
  4108.         if (this._seeking || this._volSeeking) {
  4109.             return;
  4110.         }
  4111.         
  4112.         Media.ControlsWidget.hide(this);
  4113.  
  4114.         this.removeAlertDisplay();
  4115.     },
  4116.  
  4117.     play: function() {
  4118.         this.resetRate();
  4119.  
  4120.         if (this._send('playing') === false) {
  4121.             if(AC.Detector.isiPad()) {
  4122.                 this._send('forcePlay');
  4123.             }
  4124.             else {
  4125.                 this._send('play');
  4126.             }
  4127.         }
  4128.         
  4129.         if(this.playControl) {
  4130.             Element.hide(this.playControl);
  4131.         }
  4132.         if(this.pauseControl) {
  4133.             Element.show(this.pauseControl);
  4134.         }
  4135.     },
  4136.     
  4137.     pause: function() {
  4138.         this.resetRate();
  4139.         
  4140.         if (this._send('playing') === true) {
  4141.             if(AC.Detector.isiPad()) {
  4142.                 this._send('forcePause');
  4143.             }
  4144.             else {
  4145.                 this._send('pause');
  4146.             }
  4147.         }
  4148.         
  4149.         if(this.pauseControl) {
  4150.             Element.hide(this.pauseControl);
  4151.         }
  4152.         if(this.playControl) {
  4153.             Element.show(this.playControl);
  4154.         }
  4155.     },
  4156.  
  4157.     fastBackward: function () {
  4158.         var currentRate = this._send('rate'),
  4159.             speedText = '';
  4160.  
  4161.         if (this._send('playing') === false) {
  4162.             this._send('play');
  4163.         } else {
  4164.             if(this.pauseControl) {
  4165.                 Element.hide(this.pauseControl);
  4166.             }
  4167.             if(this.playControl) {
  4168.                 Element.show(this.playControl);
  4169.             }
  4170.         }
  4171.                 
  4172.         switch(currentRate) {
  4173.             case -2:
  4174.                 this._send('setRate', -4);
  4175.                 speedText = '4x';
  4176.                 this.setRateDisplay(this.speedDisplayAlert, 'four-times-speed-display');
  4177.                 this.setRateDisplay(this.fastBackwardControl, 'four-times-fast-backward');
  4178.                 break;
  4179.             case -4:
  4180.                 this._send('setRate', -8);
  4181.                 speedText = '8x';
  4182.                 this.setRateDisplay(this.speedDisplayAlert, 'eight-times-speed-display');
  4183.                 this.setRateDisplay(this.fastBackwardControl, 'eight-times-fast-backward');
  4184.                 break;
  4185.             default:
  4186.                 this._send('setRate', -2);
  4187.                 speedText = '2x';
  4188.                 this.setRateDisplay(this.speedDisplayAlert, 'two-times-speed-display');
  4189.                 this.setRateDisplay(this.fastBackwardControl, 'two-times-fast-backward');            
  4190.                 break;
  4191.         }
  4192.         
  4193.         this.setRateDisplay(this.fastForwardControl, null);
  4194.  
  4195.         while (typeof this.alertDisplayContainer.firstChild != 'undefined' && this.alertDisplayContainer.firstChild != null) {
  4196.             this.alertDisplayContainer.removeChild(this.alertDisplayContainer.firstChild);
  4197.         }
  4198.         
  4199.         this.speedDisplayAlert.innerHTML = '';
  4200.         //alert('in fastBackward');
  4201.         var roundRect = this.getRoundRectForArcAndOpacity(0.19, 0.5);
  4202.         
  4203.         if (roundRect !== false) {
  4204.             var textSpan = document.createElement('span');
  4205.             
  4206.             textSpan.appendChild(document.createTextNode(speedText));
  4207.             roundRect.appendChild(textSpan);
  4208.             this.speedDisplayAlert.appendChild(roundRect);
  4209.         } else {
  4210.             this.speedDisplayAlert.appendChild(document.createTextNode(speedText));
  4211.         }
  4212.         
  4213.         this.alertDisplayContainer.appendChild(this.speedDisplayAlert);
  4214.         Element.addClassName(this.alertDisplayContainer, this.alertDisplayContainer.baseClassName + '-active');
  4215.         Element.removeClassName(this.fastForwardControl, 'fastForward-active');
  4216.         Element.addClassName(this.fastBackwardControl, 'fastBackward-active');
  4217.     },
  4218.  
  4219.     fastForward: function () {
  4220.         var currentRate = this._send('rate'),
  4221.             speedText = '';
  4222.  
  4223.         if (this._send('playing') === false) {
  4224.             this._send('play');
  4225.         } else {
  4226.             if(this.pauseControl) {
  4227.                 Element.hide(this.pauseControl);
  4228.             }
  4229.             if(this.playControl) {
  4230.                 Element.show(this.playControl);
  4231.             }
  4232.         }
  4233.         
  4234.         switch(currentRate) {
  4235.             case 2:
  4236.                 this._send('setRate', 4);
  4237.                 speedText = '4x';
  4238.                 this.setRateDisplay(this.speedDisplayAlert, 'four-times-speed-display');
  4239.                 this.setRateDisplay(this.fastForwardControl, 'four-times-fast-forward');
  4240.                 break;
  4241.             case 4:
  4242.                 this._send('setRate', 8);
  4243.                 speedText = '8x';
  4244.                 this.setRateDisplay(this.speedDisplayAlert, 'eight-times-speed-display');
  4245.                 this.setRateDisplay(this.fastForwardControl, 'eight-times-fast-forward');
  4246.                 break;
  4247.             default:
  4248.                 this._send('setRate', 2);
  4249.                 speedText = '2x';
  4250.                 this.setRateDisplay(this.speedDisplayAlert, 'two-times-speed-display');
  4251.                 this.setRateDisplay(this.fastForwardControl, 'two-times-fast-forward');
  4252.                 break;
  4253.         }
  4254.         
  4255.         this.setRateDisplay(this.fastBackwardControl, null);
  4256.  
  4257.         while (typeof this.alertDisplayContainer.firstChild != 'undefined' && this.alertDisplayContainer.firstChild != null) {
  4258.             this.alertDisplayContainer.removeChild(this.alertDisplayContainer.firstChild);
  4259.         }
  4260.         
  4261.         this.speedDisplayAlert.innerHTML = '';
  4262.         //alert('in fastForward');
  4263.         var roundRect = this.getRoundRectForArcAndOpacity(0.19, 0.5);
  4264.         
  4265.         if (roundRect !== false) {
  4266.             var textSpan = document.createElement('span');
  4267.             
  4268.             textSpan.appendChild(document.createTextNode(speedText));
  4269.             roundRect.appendChild(textSpan);
  4270.             this.speedDisplayAlert.appendChild(roundRect);
  4271.         } else {
  4272.             this.speedDisplayAlert.appendChild(document.createTextNode(speedText));
  4273.         }
  4274.         
  4275.         this.alertDisplayContainer.appendChild(this.speedDisplayAlert);
  4276.         Element.addClassName(this.alertDisplayContainer, this.alertDisplayContainer.baseClassName + '-active');
  4277.         Element.removeClassName(this.fastBackwardControl, 'fastBackward-active');
  4278.         Element.addClassName(this.fastForwardControl, 'fastForward-active');
  4279.     },
  4280.     
  4281.     setRateDisplay: function(control, rate) {
  4282.         if(!control) return;
  4283.         switch(true) {
  4284.             case (typeof control.currentRateDisplay != 'undefined' && control.currentRateDisplay !== rate):
  4285.                 Element.removeClassName(control, control.currentRateDisplay);
  4286.                 break;
  4287.             default:
  4288.                 break;
  4289.         }
  4290.         
  4291.         switch(rate) {
  4292.             case null:
  4293.                 break;
  4294.             default:
  4295.                 Element.addClassName(control, rate);
  4296.                 break;
  4297.         }
  4298.         
  4299.         control.currentRateDisplay = rate;
  4300.     },
  4301.     
  4302.     muteVolume: function() {
  4303.         this._send('setMuted', true);
  4304.         this.volumeScrubber.setValue(0);
  4305.     },
  4306.     
  4307.     fullVolume: function() {
  4308.         this._send('setMuted', false);
  4309.         this._send('setVolume', 1);
  4310.         this.volumeScrubber.setValue(1);
  4311.     },
  4312.     
  4313.     updatePercentLoaded: function (newPercent) {
  4314.         if (typeof this.controlLoadedProgress !== 'undefined' && newPercent) {
  4315.             this.controlLoadedProgress.style.width = newPercent*100 + '%';
  4316.         }
  4317.         if (newPercent === 1) {
  4318.             Element.addClassName(this.trackEndCap, 'track-right-cap-loaded');
  4319.             Element.removeClassName(this.trackEndCap, 'track-right-cap');
  4320.         }
  4321.     },
  4322.     
  4323.     updateTime: function (newTime) {
  4324.         var duration = this._send('duration'),
  4325.             remainingTime = (duration - newTime);
  4326.  
  4327.         if ((newTime < 1 || remainingTime < 1) && this._send('rate') !== 1) {
  4328.             this.resetRate();
  4329.             this._send('pause');
  4330.             Element.removeClassName(this.fastBackwardControl, 'fastBackward-active');
  4331.             Element.removeClassName(this.fastForwardControl, 'fastForward-active');
  4332.         }
  4333.  
  4334.         try {
  4335.             this.scrubber.setValue((newTime / duration) || 0);
  4336.         } catch(e) {}
  4337.         this.updateElapsedTime(newTime);
  4338.         this.updateRemainingTime(remainingTime);
  4339.     },
  4340.     
  4341.     _setTimeForReadout: function(time, minutes, seconds) {
  4342.         if(minutes && seconds) {
  4343.             var min = parseInt(time / 60, 10),
  4344.                 sec = parseInt(time % 60, 10);
  4345.             if (min < 10) {
  4346.                 min = '0'+min;
  4347.             }
  4348.             if (sec < 10) {
  4349.                 sec = '0'+sec;
  4350.             }
  4351.  
  4352.             minutes.innerHTML = min;
  4353.             seconds.innerHTML = sec;
  4354.         }
  4355.     },
  4356.     
  4357.     updateElapsedTime: function (newTime) {
  4358.         var minutes = this.minutesPlayed,
  4359.             seconds = this.secondsPlayed;
  4360.             
  4361.         this._setTimeForReadout(newTime, minutes, seconds);
  4362.     },
  4363.     
  4364.     updateRemainingTime: function (newTime) {
  4365.         var minutes = this.minutesRemaining,
  4366.             seconds = this.secondsRemaining;
  4367.             
  4368.         this._setTimeForReadout(newTime, minutes, seconds);
  4369.     }
  4370. };
  4371.  
  4372. /* adding a method to check that the URL exists using http HEAD so that the file doesn't load */
  4373. Ajax.checkURL = function(url, callback) {
  4374.     var transport = Ajax.getTransport();
  4375.     transport.onreadystatechange = function() {
  4376.         if (this.readyState === 4 && this.status === 200) {
  4377.             callback();
  4378.         }
  4379.     };
  4380.     
  4381.     transport.open('HEAD', url, true);
  4382.     transport.send(null);
  4383. };
  4384.  
  4385. Ajax.Request.prototype._overrideMimeType = null; 
  4386. Ajax.Request.prototype.overrideMimeType = function(overrideMimeTypeValue) { 
  4387.     this._overrideMimeType = overrideMimeTypeValue; 
  4388.     if (this.transport.overrideMimeType) { 
  4389.         this.transport.overrideMimeType(overrideMimeTypeValue); 
  4390.     } 
  4391. }; 
  4392.  
  4393. Ajax.Response.prototype.responseXMLValue = function() { 
  4394.     if (AC.Detector.isIEStrict()) { 
  4395.         var xmlDocument = this.transport.responseXML.documentElement; 
  4396.         if (!xmlDocument && this.request._doesOverrideXMLMimeType()) { 
  4397.             this.transport.responseXML.loadXML(this.transport.responseText); 
  4398.         } 
  4399.     } 
  4400.     return this.transport.responseXML; 
  4401. };
  4402.  
  4403. Media.ControlsWidget.SharePlugin = function(){}
  4404. Media.ControlsWidget.SharePlugin.prototype.name = function() {
  4405.     return this._name;
  4406. }
  4407. Media.ControlsWidget.SharePlugin.prototype.actionName = function() {
  4408.     return "share";
  4409. }
  4410. Media.ControlsWidget.SharePlugin.prototype.pluginType = function() {
  4411.     return "Share";
  4412. }
  4413.