10

I'm updating a div in a page using jquery mobile in order to play some animations.

The animations also play sound through use of document.createElement('audio');

My problem is, when I update the page to another animation, the old sound keeps playing.

Sorry, this is my first question and if it seems like im not phrasing it properly I apologise.

Here is my code..

Here is the code of the animation to be loaded into the #animation div

<!DOCTYPE HTML>
<html>
  <head>
    <style>
      body {
        margin: 0px;
        padding: 0px;
      }
    </style>
  </head>
<body>
    <div id="container"></div>
    <script src="scripts/kinetic-v4.3.2.min.js"></script>
    <script src="scripts/jquery-1.9.1.js"></script>
    <script>
    /*BABY SCENE*/
    var stage = new Kinetic.Stage({
        container: 'container',
        width: 578,
        height: 400
    });
    var babyLayer = new Kinetic.Layer();
    var backLayer = new Kinetic.Layer();


    var imageObj = new Image();
    var backObj = new Image();
    imageObj.onload = function() {
    var baby = new Kinetic.Image({
      x: stage.getWidth() / 2 -100 ,
      y: stage.getHeight() / 2 -100,
      image: imageObj,
      width: 200,
      height: 200,
      opacity: 0.0
    });

    var background = new Kinetic.Image({
      x: 0,
      y: 0,
      image: backObj,
      width: 578,
      height: 400,
      opacity: 0.0
    });

    // add the shape to the layer
    babyLayer.add(baby);
    backLayer.add(background);

    // add the layer to the stage
    stage.add(babyLayer);
    stage.add(backLayer);
    babyLayer.moveToTop();
    babyLayer.draw();

    /*ANIMATION TIMELINE
     * 
     * FIRST EVENT: FADE IN BABY
     * SECOND EVENT: BABY TRANSITION
     * THIRD EVENT: FADE IN BACKGROUND
     */

    /*1) Fade in Baby*/
    setTimeout(function() {
        baby.transitionTo({
        opacity: 1,
        duration: 1
    });
    }, 200);

    setTimeout(function() {
    /*JQuery Baby Speech*/
       $(document).ready(function() {
        var babySpeech = document.createElement('audio');
        babySpeech.setAttribute('src', '../Animations/sounds/babyspeech.mp3');
        babySpeech.setAttribute('autoplay', 'autoplay');
        //audioElement.load()
        $.get();
        babySpeech.addEventListener("load", function() {
        babySpeech.play();
        }, true);
    });
    }, 800);

    /*2) Baby Transition*/
    setTimeout(function() {
        baby.transitionTo({
        x: 140,
        y: stage.getHeight() / 2 + 59,
        width: 106,
        height: 118,
        opacity: 1,
        duration: 3
    });
    }, 3000);

    setTimeout(function() {
    /*JQuery Baby Giggle*/
       $(document).ready(function() {
        var baby = document.createElement('audio');
        baby.setAttribute('src', '../Animations/sounds/baby.mp3');
        baby.setAttribute('autoplay', 'autoplay');
        //audioElement.load()
        $.get();
        baby.addEventListener("load", function() {
        baby.play();
        }, true);
    });
    }, 3000);

    /*3) Fade in Background*/
    setTimeout(function() {
        background.transitionTo({
        opacity: 1,
        duration: 3
    });
    }, 3200);

    setTimeout(function() {
    /*Second JQuery Baby Speech*/
       $(document).ready(function() {
        var babySpeech = document.createElement('audio');
        babySpeech.setAttribute('src', '../Animations/sounds/babyspeech.mp3');
        babySpeech.setAttribute('autoplay', 'autoplay');
        //audioElement.load()
        $.get();
        babySpeech.addEventListener("load", function() {
        babySpeech.play();
        }, true);
    });
    }, 8700);


  };
  imageObj.src = '../Animations/images/baby.png';
  backObj.src = '../Animations/images/background/babyroom.jpg';

</script>

Here is the main page code. It gets the filename of the animation page to be loaded into #animation from an array when you click the next button.

<div id="nav" data-role="content" style="width: 600px; margin: 0 auto; text-align: center; position: relative; top:450px">
    <a href="#animation" data-role="button" data-inline="true" id ="back">Back</a>
    <a href="#animation" data-role="button" data-inline="true" data-theme="b" id="next">Next</a>
    <script>
        var count=0;
        var link_array = ['baby', 'bed', 'book', 'cat', 'chair', 'daddy', 'dog', 'mummy', 'shoe', 'teddy'];
        $("#next").click(function(e) {
            if(count!==9)
            { 
                $('audio').stop();
                count+=1;
            }
            $('#animation1wl').load('../Animations/' + link_array[count] + '.html');
            $('#animation1wl').trigger('create');
        }); 
        $("#back").click(function(e) {
            if(count !==0)
            {
                count-=1;
            }
            $('#animation1wl').load('../Animations/' + link_array[count] + '.html');
            $('#animation1wl').trigger('create');
        }); 
    </script>
</div>

<div id="animation" data-role="content" style="width: 600px; margin: 0 auto; text-align: left">Problem Loading Resource LNW</div>

When I click the forward or back buttons, I want the audio from the previous animation loaded into #animation to stop playing..

Here is the code rendered inside #animation

<div id="animation1wl" data-role="content" style="width: 600px; margin: 0 auto; text-align: left" class="ui-content" role="main">


    <style>
      body {
        margin: 0px;
        padding: 0px;
      }
    </style>


    <div id="container"><div style="position: relative; display: inline-block; width: 578px; height: 400px;" class="kineticjs-content"><canvas width="578" style="width: 578px; height: 400px; position: absolute;" height="400"></canvas><canvas width="578" style="width: 578px; height: 400px; position: absolute;" height="400"></canvas></div></div>
    <script src="scripts/kinetic-v4.3.2.min.js"></script>
    <script src="scripts/jquery-1.9.1.js"></script>
    <script>
      /*BABY SCENE*/
      var stage = new Kinetic.Stage({
        container: 'container',
        width: 578,
        height: 400
      });
      var babyLayer = new Kinetic.Layer();
      var backLayer = new Kinetic.Layer();


      var imageObj = new Image();
      var backObj = new Image();
      imageObj.onload = function() {
        var baby = new Kinetic.Image({
          x: stage.getWidth() / 2 -100 ,
          y: stage.getHeight() / 2 -100,
          image: imageObj,
          width: 200,
          height: 200,
          opacity: 0.0
        });

        var background = new Kinetic.Image({
          x: 0,
          y: 0,
          image: backObj,
          width: 578,
          height: 400,
          opacity: 0.0
        });

        // add the shape to the layer
        babyLayer.add(baby);
        backLayer.add(background);

        // add the layer to the stage
        stage.add(babyLayer);
        stage.add(backLayer);
        babyLayer.moveToTop();
        babyLayer.draw();

        /*ANIMATION TIMELINE
         * 
         * FIRST EVENT: FADE IN BABY
         * SECOND EVENT: BABY TRANSITION
         * THIRD EVENT: FADE IN BACKGROUND
         */

        /*1) Fade in Baby*/
        setTimeout(function() {
            baby.transitionTo({
            opacity: 1,
            duration: 1
        });
        }, 200);

        setTimeout(function() {
        /*JQuery Baby Speech*/
           $(document).ready(function() {
            var babySpeech = document.createElement('audio');
            babySpeech.setAttribute('src', '../Animations/sounds/babyspeech.mp3');
            babySpeech.setAttribute('autoplay', 'autoplay');
            //audioElement.load()
            $.get();
            babySpeech.addEventListener("load", function() {
            babySpeech.play();
            }, true);
        });
        }, 800);

        /*2) Baby Transition*/
        setTimeout(function() {
            baby.transitionTo({
            x: 140,
            y: stage.getHeight() / 2 + 59,
            width: 106,
            height: 118,
            opacity: 1,
            duration: 3
        });
        }, 3000);

        setTimeout(function() {
        /*JQuery Baby Giggle*/
           $(document).ready(function() {
            var baby = document.createElement('audio');
            baby.setAttribute('src', '../Animations/sounds/baby.mp3');
            baby.setAttribute('autoplay', 'autoplay');
            //audioElement.load()
            $.get();
            baby.addEventListener("load", function() {
            baby.play();
            }, true);
        });
        }, 3000);

        /*3) Fade in Background*/
        setTimeout(function() {
            background.transitionTo({
            opacity: 1,
            duration: 3
        });
        }, 3200);

        setTimeout(function() {
        /*Second JQuery Baby Speech*/
           $(document).ready(function() {
            var babySpeech = document.createElement('audio');
            babySpeech.setAttribute('src', '../Animations/sounds/babyspeech.mp3');
            babySpeech.setAttribute('autoplay', 'autoplay');
            //audioElement.load()
            $.get();
            babySpeech.addEventListener("load", function() {
            babySpeech.play();
            }, true);
        });
        }, 8700);

        console.log($('animation1wl').find('audio')[0]);

      };
      imageObj.src = '../Animations/images/baby.png';
      backObj.src = '../Animations/images/background/babyroom.jpg';

    </script>

</div>

Any help would be great..

Thanks very much.

Omar
  • 32,302
  • 9
  • 69
  • 112
David Folksman
  • 225
  • 3
  • 8
  • 24
  • 1
    when leaving a page, use this `$(document).on('pagebeforehide', '#pageID', function() { //stop audio });` or on showing a page `$(document).on('pagebeforeshow', '#pageID', function() { //stop audio });` – Omar Apr 10 '13 at 15:57
  • Thanks for this, but I tried to insert this code block and it doesnt stop the audio as I cilick next. Where should I be inserting it? And how do I stop the audio? pologies again, i'm very new to all this.. – David Folksman Apr 11 '13 at 09:25
  • When click next, do you go to another page, or stay in the same page? – Omar Apr 11 '13 at 09:44
  • Just update one portion of the page div with another page – David Folksman Apr 11 '13 at 09:55
  • `.stop()` in jQuery stops animation, while `.pause()` stops audio. Try `.pause()` instead. – Omar Apr 11 '13 at 10:14
  • That doesn't do it either sorry :( Uncaught TypeError: Object [object Object] has no method 'pause' $('audio').pause(); – David Folksman Apr 11 '13 at 10:21
  • 1
    Ok, try `$('audio')[0].pause()` and post the markup of `#animation` after loading it. – Omar Apr 11 '13 at 10:30
  • Animation is just a DIV
    Problem Loading Resource LNW
    ('audio')[0].pause() gives the error Uncaught TypeError: Cannot call method 'pause' of undefined (11:42:03:926 | error, javascript) at (public_html/Main/index.html:269:39) at jQuery.event.dispatch (public_html/Main/splitviewSrc/jquery-1.7.1.js:3256:16) at elemData.handle.eventHandle (public_html/Main/splitviewSrc/jquery-1.7.1.js:2875:33)
    – David Folksman Apr 11 '13 at 10:44
  • you need to fetch the name of the audio file and `.pause()`. `$('audio')` returns an array. – Omar Apr 11 '13 at 10:46
  • I've updated my code above. – David Folksman Apr 11 '13 at 10:52
  • 1
    add this and show me what you get if `console.log($('animation').find('audio')[0]);`. – Omar Apr 11 '13 at 11:01
  • undefined (12:06:51:098) at public_html/Main/index.html:193 The audio is created in the other file baby.html, but loaded into the div in the main file. – David Folksman Apr 11 '13 at 11:07
  • hmmmm, what's the structure of `../Animations/bird.html` html code. – Omar Apr 11 '13 at 11:08
  • bird? Do you mean Baby? I've added the code that creates the audio in baby.html to the above code example. – David Folksman Apr 11 '13 at 11:10
  • lol any, i thought there was a bird, yea baby or book. all have the same structure right? – Omar Apr 11 '13 at 11:10
  • Yes they all have the lines var audio = document.createElement('audio'); as above – David Folksman Apr 11 '13 at 11:12
  • ok but what is insde baby.html what's the code. – Omar Apr 11 '13 at 11:13
  • added it above, i'm actually pretty embarrassed adding my code as i'm a total newbie. Sorry if it is awful! Thanks for helping me I appreciate it. – David Folksman Apr 11 '13 at 11:19
  • You shouldn't be embarrassed at all. if you're Chrome, open your page and then hit 'f12' to open DevTools window. on that window, go to Elements and copy '#animation' rendered code. – Omar Apr 11 '13 at 12:30
  • the code rendered in animation is listed above. When I go into the rendered code, it lists the code verbatim as above. – David Folksman Apr 11 '13 at 13:07
  • I've added it to the end of the example code above anyway. – David Folksman Apr 11 '13 at 13:09
  • put this `` in the main page. tell me what your get. – Omar Apr 11 '13 at 13:51
  • undefined (15:29:33:889) at public_html/Main/index.html:132 undefined (15:29:34:146) – David Folksman Apr 11 '13 at 14:29
  • 1
    ok try `$('#animation1wl audio').pause()` instead of `$('audio').stop().` – Omar Apr 11 '13 at 14:35
  • ncaught TypeError: Object [object Object] has no method 'pause' (15:38:12:692 | error, javascript) at (public_html/Main/index.html:147:50) – David Folksman Apr 11 '13 at 14:38
  • 1
    send me an email to omarmt[at]gmail.com i need to see the rendered code not the source. – Omar Apr 11 '13 at 14:48
  • Do you want me to send you the files? – David Folksman Apr 11 '13 at 15:12
  • Sure, if you dont mind. – Omar Apr 11 '13 at 15:29
  • Id love to send you the files, but I have another problem. This code doesnt work outside of netbeans because of the way chrome's security settings are set up (apparently). I can't link to a local file inside of my project, only to an external URL or the content in the #animation div wont load... i'll send you it anyway... – David Folksman Apr 11 '13 at 15:49
  • a live link to your project is enough if applicable. – Omar Apr 11 '13 at 15:51
  • Its not going live, I have to run it in a webview as part of an android app – David Folksman Apr 11 '13 at 16:13

2 Answers2

33

You can do something like this:

$('audio').each(function(){
    this.pause(); // Stop playing
    this.currentTime = 0; // Reset time
}); 
Niels
  • 48,601
  • 4
  • 62
  • 81
  • I was changing my answer in the meanwhile. So it was not up to date yet. – Niels Apr 10 '13 at 15:42
  • Thanks for the reply but I still can't get it to work. Where do I insert this code? I put it into the #next block but still the audio plays when I click the next animation. – David Folksman Apr 11 '13 at 09:25
  • 1
    Be aware that this might throw an error if the the audio element wasn't initialized yet (i.e. no playhead due to mobile preloading policies). Wrap it in a try cath and you should be fine. – m90 Apr 11 '13 at 10:54
  • How do you add code to comments? >-<! I've tried inserting this code after $("#next").click(function(e) { but it doesnt do anything. The audio from the previous animation still plays. – David Folksman Apr 11 '13 at 11:00
  • No I mean how to I make code in these comments appear as you do in the grey styled blocks. – David Folksman Apr 11 '13 at 11:08
  • If you only have one initialised audio you can do: $('audio')[0].pause(); – anoldermark Feb 25 '16 at 11:14
1

Ihad to rewrite the code but, I got this working in the end by loading the animation in its entirety when you click on the next button rather than just updating a single div.

It's a workaround but at least its working now.

Thanks to Omar who helped a lot with this problem.

David Folksman
  • 225
  • 3
  • 8
  • 24
  • It would be nice if you'd edit the initial question to include the implementation of your solution. – Virgiliu Feb 04 '15 at 15:04