Nikolaus
Nikolaus

Reputation: 253

Run 2 functions with one button Javascript

I use this HTML and JS code, which I downloaded from the web to record audio, but there is a problem because after the page is loaded on the screen immediatelly appears message to allow microphone. It is because of window.onload = function init()in source code record.js. But I want to show the message after clicking on button.

For this reason I tried to call two functions with this button - toggleRecording(button) and init() but there was a problem with "button" element, so it didn't work, but I think it could work if it will be written in good form. Can you show me example how to modify this two functions init and toggleRecording to be called by this button? I am new in JS and I don't know how it works exactly.

index.html

<button type="submit" onclick="toggleRecording()" data-run="0"></button>

record.js

//starts by click on button
  function toggleRecording() {
    var run = parseInt(getAttribute('data-run')); //

      if(run === 1) {
      recorder && recorder.stop();
      recorder && recorder.exportWAV(function(blob) {
        uploadAudioFromBlob(blob);
      });
      __log('Recording is  stopped.');
      button.setAttribute('data-run', 0);

    } 

    else {
      recorder && recorder.clear();
      recorder && recorder.record();
      __log('Speak...');
      button.setAttribute('data-run', 1);
    }
  }

  function __log(e, data) {     
showInfo("\n" + e + " " + (data || ''));  
  }

  var audio_context;
  var recorder;
  function startUserMedia(stream) { 
    var input = audio_context.createMediaStreamSource(stream); 
    recorder = new Recorder(input); 
    __log('Systém for recording is available.'); 
  }

  function startRecording(button) {   
    recorder && recorder.clear(); 
    recorder && recorder.record(); 
    button.nextElementSibling.disabled = false;
    __log('Talk...'); 
  }

   window.onload=function init() {
    try { 
      window.AudioContext = window.AudioContext || window.webkitAudioContext; 
      navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;   
      window.URL = window.URL || window.webkitURL;      
      audio_context = new AudioContext;      
    } catch (e) { 
      alert('This browser do not support audio!');
    }    
    navigator.getUserMedia({audio: true}, startUserMedia, function(e) {
      __log('No audio was detected: ' + e);
    });
  };

UPDATE: Now this system works in this steps: 1. function init() runs immediatelly when page is loaded and after user allows microphone then startusermedia function runs 2.after clicking on button runs toggleRecording(button) function which starts recording 3.second click on button runs toggleRecording function which stop recording

I want to work this system in this steps if it is possible: 1.first click on button run functions init and startusermedia and togglerecording so recording will starts immediately after clicking 2.second click will call toggleRecording function to stop recording

Upvotes: 3

Views: 2451

Answers (4)

cнŝdk
cнŝdk

Reputation: 32175

In your case the init function is directly attached to the window.onload event and can't be called with the button, to ensure its call in the two events declare it as a global function and then attach it to the onload event like this:

JavaScript:

//function declaration
init = function init() {
try { 
  window.AudioContext = window.AudioContext || window.webkitAudioContext; 
  navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;   
  window.URL = window.URL || window.webkitURL;      
  audio_context = new AudioContext;      
} catch (e) { 
  alert('This browser do not support audio!');
}    
navigator.getUserMedia({audio: true}, startUserMedia, function(e) {
  __log('No audio was detected: ' + e);
});
};

//Call
 window.onload = init();

HTML:

<button type="submit" onclick="init();toggleRecording()" data-run="0"></button>

That should do it.

EDIT:

In order to achieve what you want, you have to attach the init() function to the window.onload event and the toggleRecording() function to the onclick event of the run button, like this:

//Call
 window.onload = init();
 document.getElementById("run").onclick = toggleRecording();

And give your button the id="run":

<button type="submit" id="run" onclick="init();toggleRecording()" data-run="0"></button>

Upvotes: 0

Scott
Scott

Reputation: 5379

It's not working because init() is actually a variable attached to window.onload. Try removing window.onload=function init() and replacing it with just function init() (so it no longer runs when the page loads), then call:

<button type="submit" onclick="init();toggleRecording()" data-run="0"></button>

When you're setting up event handlers like that, you don't even need to give the function a name. Something like window.onload = function() { ... } is perfectly valid - they're called anonymous functions.

I also noticed some implementation troubles with toggleRecording(), so I've done my best to fix those too. getAttribute() needs an element, of course, so we can pass the button using this, and receive it in toggleRecording() as the button variable.

Your full code is now:

//starts by click on button
function toggleRecording(button) {
  var run = parseInt(button.getAttribute('data-run')); //

  if (run === 1) {
    recorder && recorder.stop();
    recorder && recorder.exportWAV(function(blob) {
      uploadAudioFromBlob(blob);
    });
    __log('Recording is  stopped.');
    button.setAttribute('data-run', 0);

  } else {
    recorder && recorder.clear();
    recorder && recorder.record();
    __log('Speak...');
    button.setAttribute('data-run', 1);
  }
}

function __log(e, data) {
  //TODO: Uncomment this, I have it commented so there are no errors in the StackSnippet
  //showInfo("\n" + e + " " + (data || ''));
  console.log(e.data);
}

var audio_context;
var recorder;

function startUserMedia(stream) {
  var input = audio_context.createMediaStreamSource(stream);
  recorder = new Recorder(input);
  __log('Systém for recording is available.');
}

function startRecording(button) {
  recorder && recorder.clear();
  recorder && recorder.record();
  button.nextElementSibling.disabled = false;
  __log('Talk...');
}

function init() {
  try {
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;
    window.URL = window.URL || window.webkitURL;
    audio_context = new AudioContext;
  } catch (e) {
    alert('This browser do not support audio!');
  }
  navigator.getUserMedia({
    audio: true
  }, startUserMedia, function(e) {
    __log('No audio was detected: ' + e);
  });
};
<button onclick="init(); toggleRecording(this)">Click me</button>

Upvotes: 2

Cagatay Ulubay
Cagatay Ulubay

Reputation: 2559

If you want to make the code work after the Button is pressed, you should remove the onload event, because this will make the code work after the page is loaded.

You can create a second function and place it in there, Example:

function secondFunction(){
    // Put Code inside here
}

In the toggleRecording(button) function you can call like:

function toggleRecording(button) {
    // .. the existing code
    secondFunction();
}

If you want the second called first, place it over your existing code.

You also could to following:

<button type="submit" onclick="toggleRecording();init();" data-run="0"></button>

But you still need to remove the onload event and wrap it around a function like above.

You also could do following (recommended):

<button id="record" type="submit" onclick="toggleRecording()" data-run="0"</button>

Code:

var button = document.getElementById( 'record' );

var button.onclick = function(e){
     toggleRecording(e);
     secondFunction();
}

Also again.. remove the onloadevent if you don't want to do it when the page has loaded.

The last example selects the button element with the ID record (I added it to your button-Tag) and adds an onclick-Event on it with onclick = function(){} which will be called when "onclick" of course.

Last but least: Don't just copy code, try to understand it so you can solve your problems easily by yourself :)

Upvotes: 0

Carl
Carl

Reputation: 1816

You can attach multiple actions to a button programmatically using addEventListener if you wanted to.

So you may have:

<button id="test" type="submit" onclick="toggleRecording()" data-run="0"></button>
<script>
   var btn = document.getElementById("test");
   btn.addEventListener("click", init);
   btn.addEventListener("click", toggleRecording);
   // More if wanted.
</script>

Upvotes: 0

Related Questions