Search code examples
javascriptjqueryhtml5-videoswfobject

Setting a timer to wait for swfobject script to load for flash fallback video player


Hi there i have built a page that needs to display multiple videos. It tests to see if the videos can be played in the browser (mp4 format) and if so will construct an HTML5 video tag. If the video can't be played natively in the browser then it will fallback to flash. The problem i am having is that if it can't play the Mp4 file i have to load the swfobject.js file to set up the flash player - but i only want to do this once.

I am setting a global variable of swfObjLoaded to false and then trying to do an ajax load on the script. However the swfobject script seems to be loading really slowly so the registration of the swf is trying to occur before the script has fully loaded. I am therefore trying to use setInterval to repeatedly check to see if swfObjLoaded is set to true and if it is cancel the interval and run the setupFlash function.

This is not working at all and seems to be hanging my browser. Anyone know the best way to go about doing this. I know the jQuery deferred function could probably really help me out here, but unfortunately i am stuck with using jQuery 1.3.2 which doesn't contain the deferred function. Any ideas?

Here is my code:

<html>
    <head>
        <title>HTML5 multiple videos test</title>
        <script type="text/javascript" src="http://media.topshop.com/javascript/3.3.2.3/lib/jquery/jquery.js"></script>
    </head>
    <body>

        <div style="width: 640px; height: 360px;">
            <div style="background-color: #ffe9db; width: 100%; height: 100%;">
                <div class="video_container_1" style="display: block; width: 420px; height: 236px;">
                    <a class="html5_vid" href="http://media.topshop.com/cms/pages/static/static-0000035506/flash/topshop_unique_2012_420x236.mp4">
                        <img src="http://media.topshop.com/wcsstore/ConsumerDirectStorefrontAssetStore/images/colors/color7/cms/pages/static/static-0000035506/images/VIDEO_LEFT.jpg" alt="Download the Nick Knight video" />
                    </a>
                </div>
            </div>
        </div>
        <div style="width: 640px; height: 360px;">
            <div style="background-color: #ffe9db; width: 100%; height: 100%;">
                <div class="video_container_2" style="display: block; width: 407px; height: 224px;">
                    <a class="html5_vid" href="http://www.topshop.com/cms/pages/static/static-0000035506/flash/NEW_MAKEUP-HAIR-NAILS_02_a420X236.mp4">
                        <img src="http://media.topshop.com/wcsstore/ConsumerDirectStorefrontAssetStore/images/colors/color7/cms/pages/static/static-0000035506/images/VIDEO_RIGHT.jpg" alt="Download the Nick Knight video" />
                    </a>
                </div>
            </div>
        </div>

    <script type="text/javascript">

      var vidLink = $("a.html5_vid"),
          canPlay = false,
          v = document.createElement("video"),
          vidCounter = 1,
          swfObjLoaded = false,
          interval,
          flashCode = '<object id="flash_vid_vidCount" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="vidWidth" height="vidHeight"><param name="movie" value="http://media.topshop.com/flash_content/player_page/videoPlayer.swf" \/><param name="allowFullScreen" value="true" \/><param name="allowScriptAccess" value="always" \/><param name="wmode" value="transparent" \/><param name="bgcolor" value="#ffffff" \/><param name="FlashVars" value="source=vidUrl&amp;still=posterUrl" \/><object width="vidWidth" height="vidHeight" type="application/x-shockwave-flash" flashvars="source=vidUrl&amp;still=posterUrl" data="http://media.topshop.com/flash_content/player_page/videoPlayer.swf" allowfullscreen="true" allowscriptaccess="always" wmode="transparent" bgcolor="#ffffff"><a title="Get Flash Player" href="http://www.adobe.com/go/getflashplayer"><img src="posterUrl" border="0" alt="Get Flash Player" width="vidWidth" height="vidHeight" \/><\/a><\/object><\/object>';

      if(v.canPlayType && v.canPlayType("video/mp4").replace(/no/, "")) {
        canPlay = true;
      } else {
        $.ajax({
            url: 'http://media.topshop.com/javascript/behaviour/swfobject.js',
            dataType: "script",
            async: false,
            success: function() {
                console.log("loaded the file via ajax");
                swfObjLoaded = true;
            }
        });
      }

      $.each(vidLink, function() {
        var currentLink = $(this);
        currentLink.css("display", "none");
        var vidUrl = currentLink.attr("href"),
            posterUrl = currentLink.children("img").attr("src"),
            vidContainer = currentLink.parent(),
            vidContainerParent = vidContainer.parent(),
            vidWidth = vidContainer.css("width").replace("px", ""),
            vidHeight = vidContainer.css("height").replace("px", "");

        if (canPlay === true) {
          console.log("canPlay is true");
          newVid = document.createElement("video");
          currentLink.replaceWith(newVid);
          $("div.video_container_" + vidCounter + " video").attr({id: "html_vid_" + vidCounter, controls: "controls", width: vidWidth, height: vidHeight}).append("<source src=" + vidUrl + " \/>");
          if(!$("div.video_container_" + vidCounter + " video").children("source").length) {
            $("div.video_container_" + vidCounter + " video").attr("src", vidUrl );
          }
          if (navigator.userAgent.toLowerCase().search("android") > -1) {
            var vid = document.getElementById("html_vid_" + vidCounter);
            vid.onclick = function() {
              if (vid.paused) {
                vid.play();
              } else {
                vid.pause();
              }
            }
          }
        } else {
          console.log("canPlay is false");
            function setupFlash() {
                vidContainerParent.hide();
                var tempFlashCode = flashCode.replace(/vidCount/g, vidCounter);
                    tempFlashCode = tempFlashCode.replace(/vidWidth/g, vidWidth);
                    tempFlashCode = tempFlashCode.replace(/vidHeight/g, vidHeight);
                    tempFlashCode = tempFlashCode.replace(/vidUrl/g, vidUrl);
                    tempFlashCode = tempFlashCode.replace(/posterUrl/g, posterUrl);
                swfobject.registerObject("flash_vid_" + vidCounter, "9.0.0");
                currentLink.replaceWith(tempFlashCode);
                vidContainerParent.show();
            }

            function checkSwfObj() {
                if (swfObjLoaded !== true) {
                    console.log("still not loaded");
                    var timer = setInterval(function(){checkSwfObj()},100);
                } else {
                    console.log("bloody thing is finally loaded");
                    clearInterval(timer);
                    setupFlash();
                }
            }
            checkSwfObj();
        }
        vidCounter++;
      });
    </script>
    </body>
    </html>

Solution

  • You can define simple loader object like:

    var SwfLoader = {
        requestSend: false,
        hasResponse: false,
        callbacks: [],
    
        bind: function (func) {
            if (this.hasResponse) {
                func();
                return;
            }
            this.callbacks.push(func);
            if (!this.requestSend) this.sendRequest();
        },
    
        sendRequest: function () {
    
            this.requestSend = true;
    
            $.ajax({
                // ....
                // Your request parameters here
                // ....
                success:function () {
                    this.hasResponse = true;
                    SwfLoader.executeHandlers();
                }
            });
        },
    
        executeHandlers: function () {
            for (var i = 0; i < this.callbacks.length; i++) {
                this.callbacks[i]();
            }
        }
    };
    

    And then use SwfLoader.bind(function () {/* you code to setup flash player */}); when browser can't play the movie