HTML not calling Javascript onclick - javascript

I am having difficulty figuring out what is wrong with these files. Firebug loads the HTML and the .js files but when you push the button on the HTML file it does not do anything. Putting breakpoints in firebug shows that the .js code is not talking to the HTML file. I do not know if Javascript is not working because of something else in the code or I have a really silly mistake in the HTML file. Thanks for any help.
HTML file:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Dice Roller</title>
<style type="text/css">
#import "main.css";
</style>
<script type="text/javascript" src="roller.js"></script>
<script type="text/javascript" src="roller_library.js"></script>
</head>
<body>
<div id="content">
<h1>Dice Roller</h1><br/><br/>
Die 1: <span id="die_1"> </span><br /><br />
Die 2: <span id="die_2"> </span><br /><br />
<label>Message: </label>
<span id="message"> </span><br/><br />
<label> </label>
<input type="button" id="roll" value="Roll the Dice" /> <br/>
</div>
</body>
</html>
roller.js
var die = new Die();
var pairofDice = PairofDice();
var $ = function (id) { return document.getElementById(id); }
var update_display = function() {
var specialMsg;
var die_1 = ParseInt(Die.getValue1());
var die_2 = ParseInt(Die.getValue2());
$("die_1").value = die_1;
$("die_2").value = die_2;
var sum = PairofDice.getSum(die_1, die_2);
switch (sum){
case "2":
specialMsg = "Snake eyes"
break;
case "7":
specialMsg = "Craps";
break;
case "12":
specialMsg = "Box Cars";
break;
}
$("message").value = specialMsg;
}
var rollDice_click = function() {
$("die_1").value = "";
$("die_2").value = "";
update_display();
}
window.onload = function() {
$("roll").onclick = rollDice_click;
}
roller_library.js
var Die = function(sides) {
this.sides = 6;
return this;
}
Die.prototype.roll = function(sides) {
this.sides = sides;
do{
number = parseInt (10 * Math.random());
} while (number >this.sides || number <1);
return number;
}
Die.prototype.getValue = function() {
this.roll = Die.roll();
return this;
}
var PairofDice = function(sides) {
this.sides = 6;
return this;
}
PairofDice.prototype.roll = function() {
Die.roll(6);
return number;
}
PairofDice.prototype.getValue1 = function() {
Die.getValue();
return;
}
PairofDice.prototype.getValue2 = function() {
Die.getValue();
return;
}
PairofDice.prototype.getSum = function(d1,d2) {
var sum;
var die1 = parseInt(d1);
var die2 = parseInt(d2);
sum = die1 + die2;
return sum;
}
The other option is that I am not understanding what I should be doing, if that is the case please let me know so I can get more one on one help.

roller.js is being run before roller_library.js is even loaded so neither Die nor PairOfDice are defined when Die is used on line 1 of roller.js. So the roller.js JavaScript aborts with a failure at that point and the window.onload line is never executed.

Ok, so I entirely jumped the gun on the onclick issue, so I took a more indepth look at the code. Theres a couple of problems, the code won't even run nevermind the onclick not working. So, I fixed it and added some comments that might help you figure our where you went wrong if you compare it to your code. This is by no means best practice code, I've just tried to translate your code idea into working code so hopefully you can learn from it.
Please let me know if it helps or you need anything clarified :)
// Can't do this at the start of the script as they are undefined
//var die = new Die();
//var pairofDice = PairofDice();
// This is a good idea
var $ = function(id) {
return document.getElementById(id);
}
// Let's include the model code ahead of the application code
// Our Die, when rolled it should have update it's value
var Die = function(sides) {
// Let's use the parameter to decide how many sides our die has
// " || 6" means that if sides has no value, it will default to 6
// This helps us prevent errors from having no number of sides
// defined when we roll the dice
this.sides = sides || 6;
// We will be able to access the value from elsewhere, but let's give
// it an initial random value!
this.value = this.roll();
return this;
}
// Extending our Die's prototype to allow rolling!
// We don't need the sides parameter anymore, compare this old version
Die.prototype.old_roll = function(sides) {
// This would remove any value we have previously assigned to sides
this.sides = sides;
// This loop will create a bias in the random numbers generated and if
// the number of sides is greater than 10, it will never show it
do {
number = parseInt(10 * Math.random());
} while (number > this.sides || number < 1);
return number;
}
// Cleaner version of roll
Die.prototype.roll = function() {
// Get a random number [ This will be a decimal number between 0 and 1]
var random_number = Math.random()
// Multiply it by (#no of sides - 1)
// [This will be a decimal value between 0 and the (#no of sides - 1)]
var scaled_number = (this.sides - 1) * random_number
// We round the number so it's always an integer number
// We also add one to the result so we get a number between (1..# of sides)
// It should be clear that we had to subtract from the number of sides before
// we multiplied so that whenever we add one here we don't go outside our
// desired range of numbers (else the dice would read 1..7 with only 6 sides
var result = Math.round(scaled_number) + 1
// Assign the result to our die for future reference
this.value = result
// Return the result
return result
}
/* We have no need for getValue as we can access the value of the dice
Die.prototype.getValue = function() {
this.roll = Die.roll();
return this;
}*/
// The PairofDice should help us manage 2 dice
var PairofDice = function(sides) {
// The sides parameter will help us initialise the two dice
this.dice1 = new Die(sides);
this.dice2 = new Die(sides);
return this;
}
// When we roll the pair, it should roll each dice individually
// It will return an array with the value of each roll, for convenience
PairofDice.prototype.roll = function() {
var roll1 = this.dice1.roll();
var roll2 = this.dice2.roll();
return [roll1, roll2];
}
// Return the value of the first dice
PairofDice.prototype.getValue1 = function() {
return this.dice1.value;
}
// Likewise for the second dice
PairofDice.prototype.getValue2 = function() {
return this.dice2.value;
}
// Return the total score for all dices, there is no need to take
// any parameters to this function as we have all the data within
// our PairOfDice instace (referenced by 'this' keyword)
PairofDice.prototype.getSum = function() {
// No need to parseInt on these values as we only store integer values
var sum = this.dice1.value + this.dice2.value;
return sum;
}
// Now we can define our variables
// There is no need to make an instance of Die as we can just use
// PairofDice to manage 2 dice for us, make sure to use the new keyword!
//var die = new Die();
var pairofDice = new PairofDice();
// Updating the display when a roll is made
var update_display = function() {
var specialMsg;
// We can simplify this a lot now
//var die_1 = ParseInt(Die.getValue1());
//var die_2 = ParseInt(Die.getValue2());
// value doesn't set the text on span, so we will use innerText
$("die_1").innerText = pairofDice.getValue1();
$("die_2").innerText = pairofDice.getValue2();
// Get the sum of the roll
//var sum = PairofDice.getSum(die_1, die_2);
var sum = pairofDice.getSum();
// In the switch statement, it should be integer cases instead of string
switch (sum) {
case 2:
specialMsg = "Snake eyes"
break;
case 7:
specialMsg = "Craps";
break;
case 12:
specialMsg = "Box Cars";
break;
// we add a default message incase there is no special, because then it will print 'undefined'
default:
specialMsg = "No luck";
}
// Show the message!
$("message").innerText = specialMsg;
}
var rollDice_click = function() {
// These aren't needed as the value will always be updated
//$("die_1").value = "";
//$("die_2").value = "";
// Roll the dice..
pairofDice.roll();
// Show the results!
update_display();
}
window.onload = function() {
$("roll").onclick = rollDice_click;
}​

Related

How do I stop my program from outputting the same thing twice in a row?

So, I have created this HTML page with some JavaScript in it. And I have this button that outputs one out of six emojis. It worked fine and then I added some code to stop the program from outputting the same emoji twice in a row, but it doesn't make any difference and I don't know why.
This is my code:
function randEmoji()
{
var oldEmoji = emoji;
var emojiList = [";)", ":D", "xD", ":O", ":X", ":P"];
var emoji = emojiList[Math.floor(Math.random() * emojiList.length)];
if (oldEmoji == emoji)
{
randEmoji();
}
else
{
document.getElementById("emojiText").innerHTML = "Look how fun! ---> " + emoji + " <--- An emoji!";
console.log(emoji);
}
}
I'm not very good at programming and have no idea what's causing this problem.
Please help me!
you have to declare your variables outside the function and set them inside. otherwise their values get reset in each function call.
Try this:
var oldEmoji = '';
var emoji = '';
var emojiList = [";)", ":D", "xD", ":O", ":X", ":P"];
function randEmoji() {
oldEmoji = emoji;
emoji = emojiList[Math.floor(Math.random() * emojiList.length)];
if (oldEmoji == emoji) {
randEmoji();
} else {
console.log(emoji);
}
}
var i = 0;
while (i < 20) {
randEmoji();
i += 1;
}
The problem is that any variables local to the function scope (meaning declared inside the function) are thrown away after the function completes its execution. Thus, every time you run the function emoji and oldEmoji are reinstantiated from undefined
One solution would be to move one of those declarations to a parent scope, like so:
var oldEmoji;
function randEmoji() {
var emojiList = [";)", ":D"];
var emoji = emojiList[Math.floor(Math.random() * emojiList.length)];
if (oldEmoji == emoji) {
randEmoji();
} else {
console.log(emoji);
oldEmoji = emoji;
}
}
randEmoji();
randEmoji();
randEmoji();
randEmoji();
randEmoji();
randEmoji();
randEmoji();
See here, we never actually get a repeat.
In addition to #full-stack answer, you could:
var oldEmoji = '';
var emoji = '';
var emojiList = [";)", ":D", "xD", ":O", ":X", ":P"];
function randEmoji(){
// remove old emoji first to avoid doing a recursive call
var check = oldEmoji? emojiList.filter(e => e !== oldEmoji ) : emojiList;
var emoji = check[Math.floor(Math.random() * check.length)];
oldEmoji = emoji
document.getElementById("emojiText").innerHTML = "Look how fun! ---> " + emoji + " <--- An emoji!";
console.log(emoji);
}

Html5 & JavaScript Text to Speech conversion [duplicate]

I am getting a problem when trying to use Speech Synthesis API in Chrome 33. It works perfectly with a shorter text, but if I try longer text, it just stops in the middle. After it has stopped once like that, the Speech Synthesis does not work anywhere within Chrome until the browser is restarted.
Example code (http://jsfiddle.net/Mdm47/1/):
function speak(text) {
var msg = new SpeechSynthesisUtterance();
var voices = speechSynthesis.getVoices();
msg.voice = voices[10];
msg.voiceURI = 'native';
msg.volume = 1;
msg.rate = 1;
msg.pitch = 2;
msg.text = text;
msg.lang = 'en-US';
speechSynthesis.speak(msg);
}
speak('Short text');
speak('Collaboratively administrate empowered markets via plug-and-play networks. Dynamically procrastinate B2C users after installed base benefits. Dramatically visualize customer directed convergence without revolutionary ROI. Efficiently unleash cross-media information without cross-media value. Quickly maximize timely deliverables for real-time schemas. Dramatically maintain clicks-and-mortar solutions without functional solutions.');
speak('Another short text');
It stops speaking in the middle of the second text, and I can't get any other page to speak after that.
Is it a browser bug or some kind of security limitation?
I've had this issue for a while now with Google Chrome Speech Synthesis. After some investigation, I discovered the following:
The breaking of the utterances only happens when the voice is not a native voice,
The cutting out usually occurs between 200-300 characters,
When it does break you can un-freeze it by doing speechSynthesis.cancel();
The 'onend' event sometimes decides not to fire. A quirky work-around to this is to console.log() out the utterance object before speaking it. Also I found wrapping the speak invocation in a setTimeout callback helps smooth these issues out.
In response to these problems, I have written a function that overcomes the character limit, by chunking the text up into smaller utterances, and playing them one after another. Obviously you'll get some odd sounds sometimes as sentences might be chunked into two separate utterances with a small time delay in between each, however the code will try and split these points at punctuation marks as to make the breaks in sound less obvious.
Update
I've made this work-around publicly available at https://gist.github.com/woollsta/2d146f13878a301b36d7#file-chunkify-js. Many thanks to Brett Zamir for his contributions.
The function:
var speechUtteranceChunker = function (utt, settings, callback) {
settings = settings || {};
var newUtt;
var txt = (settings && settings.offset !== undefined ? utt.text.substring(settings.offset) : utt.text);
if (utt.voice && utt.voice.voiceURI === 'native') { // Not part of the spec
newUtt = utt;
newUtt.text = txt;
newUtt.addEventListener('end', function () {
if (speechUtteranceChunker.cancel) {
speechUtteranceChunker.cancel = false;
}
if (callback !== undefined) {
callback();
}
});
}
else {
var chunkLength = (settings && settings.chunkLength) || 160;
var pattRegex = new RegExp('^[\\s\\S]{' + Math.floor(chunkLength / 2) + ',' + chunkLength + '}[.!?,]{1}|^[\\s\\S]{1,' + chunkLength + '}$|^[\\s\\S]{1,' + chunkLength + '} ');
var chunkArr = txt.match(pattRegex);
if (chunkArr[0] === undefined || chunkArr[0].length <= 2) {
//call once all text has been spoken...
if (callback !== undefined) {
callback();
}
return;
}
var chunk = chunkArr[0];
newUtt = new SpeechSynthesisUtterance(chunk);
var x;
for (x in utt) {
if (utt.hasOwnProperty(x) && x !== 'text') {
newUtt[x] = utt[x];
}
}
newUtt.addEventListener('end', function () {
if (speechUtteranceChunker.cancel) {
speechUtteranceChunker.cancel = false;
return;
}
settings.offset = settings.offset || 0;
settings.offset += chunk.length - 1;
speechUtteranceChunker(utt, settings, callback);
});
}
if (settings.modifier) {
settings.modifier(newUtt);
}
console.log(newUtt); //IMPORTANT!! Do not remove: Logging the object out fixes some onend firing issues.
//placing the speak invocation inside a callback fixes ordering and onend issues.
setTimeout(function () {
speechSynthesis.speak(newUtt);
}, 0);
};
How to use it...
//create an utterance as you normally would...
var myLongText = "This is some long text, oh my goodness look how long I'm getting, wooooohooo!";
var utterance = new SpeechSynthesisUtterance(myLongText);
//modify it as you normally would
var voiceArr = speechSynthesis.getVoices();
utterance.voice = voiceArr[2];
//pass it into the chunking function to have it played out.
//you can set the max number of characters by changing the chunkLength property below.
//a callback function can also be added that will fire once the entire text has been spoken.
speechUtteranceChunker(utterance, {
chunkLength: 120
}, function () {
//some code to execute when done
console.log('done');
});
Hope people find this as useful.
I have solved the probleme while having a timer function which call the pause() and resume() function and callset the timer again. On the onend event I clear the timer.
var myTimeout;
function myTimer() {
window.speechSynthesis.pause();
window.speechSynthesis.resume();
myTimeout = setTimeout(myTimer, 10000);
}
...
window.speechSynthesis.cancel();
myTimeout = setTimeout(myTimer, 10000);
var toSpeak = "some text";
var utt = new SpeechSynthesisUtterance(toSpeak);
...
utt.onend = function() { clearTimeout(myTimeout); }
window.speechSynthesis.speak(utt);
...
This seem to work well.
A simple and effective solution is to resume periodically.
function resumeInfinity() {
window.speechSynthesis.resume();
timeoutResumeInfinity = setTimeout(resumeInfinity, 1000);
}
You can associate this with the onend and onstart events, so you will only be invoking the resume if necessary. Something like:
var utterance = new SpeechSynthesisUtterance();
utterance.onstart = function(event) {
resumeInfinity();
};
utterance.onend = function(event) {
clearTimeout(timeoutResumeInfinity);
};
I discovered this by chance!
Hope this help!
The problem with Peter's answer is it doesn't work when you have a queue of speech synthesis set up. The script will put the new chunk at the end of the queue, and thus out of order. Example: https://jsfiddle.net/1gzkja90/
<script type='text/javascript' src='http://code.jquery.com/jquery-2.1.0.js'></script>
<script type='text/javascript'>
u = new SpeechSynthesisUtterance();
$(document).ready(function () {
$('.t').each(function () {
u = new SpeechSynthesisUtterance($(this).text());
speechUtteranceChunker(u, {
chunkLength: 120
}, function () {
console.log('end');
});
});
});
/**
* Chunkify
* Google Chrome Speech Synthesis Chunking Pattern
* Fixes inconsistencies with speaking long texts in speechUtterance objects
* Licensed under the MIT License
*
* Peter Woolley and Brett Zamir
*/
var speechUtteranceChunker = function (utt, settings, callback) {
settings = settings || {};
var newUtt;
var txt = (settings && settings.offset !== undefined ? utt.text.substring(settings.offset) : utt.text);
if (utt.voice && utt.voice.voiceURI === 'native') { // Not part of the spec
newUtt = utt;
newUtt.text = txt;
newUtt.addEventListener('end', function () {
if (speechUtteranceChunker.cancel) {
speechUtteranceChunker.cancel = false;
}
if (callback !== undefined) {
callback();
}
});
}
else {
var chunkLength = (settings && settings.chunkLength) || 160;
var pattRegex = new RegExp('^[\\s\\S]{' + Math.floor(chunkLength / 2) + ',' + chunkLength + '}[.!?,]{1}|^[\\s\\S]{1,' + chunkLength + '}$|^[\\s\\S]{1,' + chunkLength + '} ');
var chunkArr = txt.match(pattRegex);
if (chunkArr[0] === undefined || chunkArr[0].length <= 2) {
//call once all text has been spoken...
if (callback !== undefined) {
callback();
}
return;
}
var chunk = chunkArr[0];
newUtt = new SpeechSynthesisUtterance(chunk);
var x;
for (x in utt) {
if (utt.hasOwnProperty(x) && x !== 'text') {
newUtt[x] = utt[x];
}
}
newUtt.addEventListener('end', function () {
if (speechUtteranceChunker.cancel) {
speechUtteranceChunker.cancel = false;
return;
}
settings.offset = settings.offset || 0;
settings.offset += chunk.length - 1;
speechUtteranceChunker(utt, settings, callback);
});
}
if (settings.modifier) {
settings.modifier(newUtt);
}
console.log(newUtt); //IMPORTANT!! Do not remove: Logging the object out fixes some onend firing issues.
//placing the speak invocation inside a callback fixes ordering and onend issues.
setTimeout(function () {
speechSynthesis.speak(newUtt);
}, 0);
};
</script>
<p class="t">MLA format follows the author-page method of in-text citation. This means that the author's last name and the page number(s) from which the quotation or paraphrase is taken must appear in the text, and a complete reference should appear on your Works Cited page. The author's name may appear either in the sentence itself or in parentheses following the quotation or paraphrase, but the page number(s) should always appear in the parentheses, not in the text of your sentence.</p>
<p class="t">Joe waited for the train.</p>
<p class="t">The train was late.</p>
<p class="t">Mary and Samantha took the bus.</p>
In my case, the answer was to "chunk" the string before adding them to the queue. See here: http://jsfiddle.net/vqvyjzq4/
Many props to Peter for the idea as well as the regex (which I still have yet to conquer.) I'm sure the javascript can be cleaned up, this is more of a proof of concept.
<script type='text/javascript' src='http://code.jquery.com/jquery-2.1.0.js'></script>
<script type='text/javascript'>
var chunkLength = 120;
var pattRegex = new RegExp('^[\\s\\S]{' + Math.floor(chunkLength / 2) + ',' + chunkLength + '}[.!?,]{1}|^[\\s\\S]{1,' + chunkLength + '}$|^[\\s\\S]{1,' + chunkLength + '} ');
$(document).ready(function () {
var element = this;
var arr = [];
var txt = replaceBlank($(element).text());
while (txt.length > 0) {
arr.push(txt.match(pattRegex)[0]);
txt = txt.substring(arr[arr.length - 1].length);
}
$.each(arr, function () {
var u = new SpeechSynthesisUtterance(this.trim());
window.speechSynthesis.speak(u);
});
});
</script>
<p class="t">MLA format follows the author-page method of in-text citation. This means that the author's last name and the page number(s) from which the quotation or paraphrase is taken must appear in the text, and a complete reference should appear on your Works Cited page. The author's name may appear either in the sentence itself or in parentheses following the quotation or paraphrase, but the page number(s) should always appear in the parentheses, not in the text of your sentence.</p>
<p class="t">Joe waited for the train.</p>
<p class="t">The train was late.</p>
<p class="t">Mary and Samantha took the bus.</p>
Here is what i ended up with, it simply splits my sentences on the period "."
var voices = window.speechSynthesis.getVoices();
var sayit = function ()
{
var msg = new SpeechSynthesisUtterance();
msg.voice = voices[10]; // Note: some voices don't support altering params
msg.voiceURI = 'native';
msg.volume = 1; // 0 to 1
msg.rate = 1; // 0.1 to 10
msg.pitch = 2; //0 to 2
msg.lang = 'en-GB';
msg.onstart = function (event) {
console.log("started");
};
msg.onend = function(event) {
console.log('Finished in ' + event.elapsedTime + ' seconds.');
};
msg.onerror = function(event)
{
console.log('Errored ' + event);
}
msg.onpause = function (event)
{
console.log('paused ' + event);
}
msg.onboundary = function (event)
{
console.log('onboundary ' + event);
}
return msg;
}
var speekResponse = function (text)
{
speechSynthesis.cancel(); // if it errors, this clears out the error.
var sentences = text.split(".");
for (var i=0;i< sentences.length;i++)
{
var toSay = sayit();
toSay.text = sentences[i];
speechSynthesis.speak(toSay);
}
}
2017 and this bug is still around. I happen to understand this problem quite well, being the developer of the award-winning Chrome extension Read Aloud. OK, just kidding about the award winning part.
Your speech will get stuck if it's longer than 15 seconds.
I discover that Chrome uses a 15 second idle timer to decide when to deactivate an extension's event/background page. I believe this is the culprit.
The workaround I've used is a fairly complicated chunking algorithm that respects punctuation. For Latin languages, I set max chunk size at 36 words. The code is open-source, if you're inclined: https://github.com/ken107/read-aloud/blob/315f1e1d5be6b28ba47fe0c309961025521de516/js/speech.js#L212
The 36-word limit works well most of the time, staying within 15 seconds. But there'll be cases where it still gets stuck. To recover from that, I use a 16 second timer.
I ended up chunking up the text and having some intelligence around handling of various punctucations like periods, commas, etc. For example, you don't want to break the text up on a comma if it's part of a number (i.e., $10,000).
I have tested it and it seems to work on arbitrarily large sets of input and it also appears to work not just on the desktop but on android phones and iphones.
Set up a github page for the synthesizer at: https://github.com/unk1911/speech
You can see it live at: http://edeliverables.com/tts/
new Vue({
el: "#app",
data: {
text: `Collaboratively administrate empowered markets via plug-and-play networks. Dynamically procrastinate B2C users after installed base benefits. Dramatically visualize customer directed convergence without revolutionary ROI. Efficiently unleash cross-media information without cross-media value. Quickly maximize timely deliverables for real-time schemas. Dramatically maintain clicks-and-mortar solutions without functional solutions.`
},
methods:{
stop_reading() {
const synth = window.speechSynthesis;
synth.cancel();
},
talk() {
const synth = window.speechSynthesis;
const textInput = this.text;
const utterThis = new SpeechSynthesisUtterance(textInput);
utterThis.pitch = 0;
utterThis.rate = 1;
synth.speak(utterThis);
const resumeInfinity = () => {
window.speechSynthesis.resume();
const timeoutResumeInfinity = setTimeout(resumeInfinity, 1000);
}
utterThis.onstart = () => {
resumeInfinity();
};
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button #click="talk">Speak</button>
<button #click="stop_reading">Stop</button>
</div>
As Michael proposed, Peter's solutions is really great except when your text is on different lines. Michael created demo to better illustrate the problem with it. - https://jsfiddle.net/1gzkja90/ and proposed another solution.
To add one maybe simpler way to solve this is to remove line breaks from textarea in Peter's solution and it works just great.
//javascript
var noLineBreaks = document.getElementById('mytextarea').replace(/\n/g,'');
//jquery
var noLineBreaks = $('#mytextarea').val().replace(/\n/g,'');
So in Peter's solution it might look the following way :
utterance.text = $('#mytextarea').val().replace(/\n/g,'');
But still there's problem with canceling the speech. It just goes to another sequence and won't stop.
Other suggestion do weird thing with dot or say DOT and do not respect speech intonnation on sentence end.
var CHARACTER_LIMIT = 200;
var lang = "en";
var text = "MLA format follows the author-page method of in-text citation. This means that the author's last name and the page number(s) from which the quotation or paraphrase is taken must appear in the text, and a complete reference should appear on your Works Cited page. The author's name may appear either in the sentence itself or in parentheses following the quotation or paraphrase, but the page number(s) should always appear in the parentheses, not in the text of your sentence. Joe waited for the train. The train was late. Mary and Samantha took the bus.";
speak(text, lang)
function speak(text, lang) {
//Support for multipart text (there is a limit on characters)
var multipartText = [];
if (text.length > CHARACTER_LIMIT) {
var tmptxt = text;
while (tmptxt.length > CHARACTER_LIMIT) {
//Split by common phrase delimiters
var p = tmptxt.search(/[:!?.;]+/);
var part = '';
//Coludn't split by priority characters, try commas
if (p == -1 || p >= CHARACTER_LIMIT) {
p = tmptxt.search(/[,]+/);
}
//Couldn't split by normal characters, then we use spaces
if (p == -1 || p >= CHARACTER_LIMIT) {
var words = tmptxt.split(' ');
for (var i = 0; i < words.length; i++) {
if (part.length + words[i].length + 1 > CHARACTER_LIMIT)
break;
part += (i != 0 ? ' ' : '') + words[i];
}
} else {
part = tmptxt.substr(0, p + 1);
}
tmptxt = tmptxt.substr(part.length, tmptxt.length - part.length);
multipartText.push(part);
//console.log(part.length + " - " + part);
}
//Add the remaining text
if (tmptxt.length > 0) {
multipartText.push(tmptxt);
}
} else {
//Small text
multipartText.push(text);
}
//Play multipart text
for (var i = 0; i < multipartText.length; i++) {
//Use SpeechSynthesis
//console.log(multipartText[i]);
//Create msg object
var msg = new SpeechSynthesisUtterance();
//msg.voice = profile.systemvoice;
//msg.voiceURI = profile.systemvoice.voiceURI;
msg.volume = 1; // 0 to 1
msg.rate = 1; // 0.1 to 10
// msg.rate = usersetting || 1; // 0.1 to 10
msg.pitch = 1; //0 to 2*/
msg.text = multipartText[i];
msg.speak = multipartText;
msg.lang = lang;
msg.onend = self.OnFinishedPlaying;
msg.onerror = function (e) {
console.log('Error');
console.log(e);
};
/*GC*/
msg.onstart = function (e) {
var curenttxt = e.currentTarget.text;
console.log(curenttxt);
//highlight(e.currentTarget.text);
//$('#showtxt').text(curenttxt);
//console.log(e);
};
//console.log(msg);
speechSynthesis.speak(msg);
}
}
https://jsfiddle.net/onigetoc/9r27Ltqz/
I want to say that through Chrome Extensions and Applications, I solved this quite irritating issue through using chrome.tts, since chrome.tts allows you to speak through the browser, instead of the window which stops the talk when you close the window.
Using the below code, you can fix the above issue with large speakings:
chrome.tts.speak("Abnormally large string, over 250 characters, etc...");
setInterval(() => { chrome.tts.resume(); }, 100);
I'm sure that will work, but I did this just to be safe:
var largeData = "";
var smallChunks = largeData.match(/.{1,250}/g);
for (var chunk of smallChunks) {
chrome.tts.speak(chunk, {'enqueue': true});
}
Hope this helps someone! It helped make my application work more functionally, and epicly.
Yes, the google synthesis api will stop at some point during speaking a long text.
We can see onend event, onpause and onerror event of SpeechSynthesisUtterance won't be fired normally when the sudden stop happens, so does the speechSynthesis onerror event.
After several trials, found speechSynthesis.paused is working, and speechSynthesis.resume() can help resume the speaking.
Hence we just need to have a timer to check the pause status during the speaking, and calling speechSynthesis.resume() to continue.
The interval should be small enough to prevent glitch when continuing the speak.
let timer = null;
let reading = false;
let readText = function(text) {
if (!reading) {
speechSynthesis.cancel();
if (timer) {
clearInterval(timer);
}
let msg = new SpeechSynthesisUtterance();
let voices = window.speechSynthesis.getVoices();
msg.voice = voices[82];
msg.voiceURI = 'native';
msg.volume = 1; // 0 to 1
msg.rate = 1.0; // 0.1 to 10
msg.pitch = 1; //0 to 2
msg.text = text;
msg.lang = 'zh-TW';
msg.onerror = function(e) {
speechSynthesis.cancel();
reading = false;
clearInterval(timer);
};
msg.onpause = function(e) {
console.log('onpause in ' + e.elapsedTime + ' seconds.');
}
msg.onend = function(e) {
console.log('onend in ' + e.elapsedTime + ' seconds.');
reading = false;
clearInterval(timer);
};
speechSynthesis.onerror = function(e) {
console.log('speechSynthesis onerror in ' + e.elapsedTime + ' seconds.');
speechSynthesis.cancel();
reading = false;
clearInterval(timer);
};
speechSynthesis.speak(msg);
timer = setInterval(function(){
if (speechSynthesis.paused) {
console.log("#continue")
speechSynthesis.resume();
}
}, 100);
reading = true;
}
}

Javascript error: object is not a function in a video poker script

So I have been writing a script to play a video (or really text-based) poker game as an exercise in learning Javascript. I have everything working to play through an instance of the game once, but on trying to run it a second time, it develops an error: "Uncaught TypeError: object is not a function"
This error comes up when trying to create a new hand.
Here is the relevant code, I left a few functions out that don't seem to be causing any issues:
//object constructor for card
function card(suite, faceValue) {
this.suite = suite,
this.faceValue = faceValue
}
//object constructor for hand
function hand(cards, handName, score, docHandName) {
this.cards = cards,
this.handName = handName,
this.score = score,
this.docHandName = docHandName
}
var deck = new Array;
var buildDeck = function() {
for (var i = 0; i <= 52; i++) {
if (i < 13) {
deck[i] = new card("Spades", i + 2);
}
else if (i < 26) {
deck[i] = new card("Clubs", i - 11);
}
else if (i < 39) {
deck[i] = new card("Hearts", i - 24);
}
else if (i < 52) {
deck[i] = new card("Diamonds", i - 37);
}
}
}
//pulls a card from location in deck specified by randomSpot()
var pullCard = function(spot) {
var newCard = deck[spot];
deck.splice(spot, 1);
return newCard;
}
//takes away a card each time
//passes into pullCard(spot) as spot
var pullCount = 0;
var randomSpot = function() {
var x = Math.floor(Math.random() * (52 - pullCount));
pullCount++;
return x;
}
var dealFiveCards = function() {
var card1 = pullCard(randomSpot());
var card2 = pullCard(randomSpot());
var card3 = pullCard(randomSpot());
var card4 = pullCard(randomSpot());
var card5 = pullCard(randomSpot());
var fiveCards = [card1, card2, card3, card4, card5];
return fiveCards;
}
function createNewHand() {
newHand = new hand();
newHand.cards = dealFiveCards();
return newHand;
}
var playOneGame = function() {
buildDeck();
hand = createNewHand();
hand.cards.sort(compare);
assignHandScore();
wager = prompt("How much do you bet?");
printHandValue();
dealAgain();
hand.cards.sort(compare);
assignHandScore();
payout = pays(wager);
printHandValue();
printPayout();
}
playAgain = "Y";
while (playAgain === "Y") {
playOneGame();
playAgain = prompt("Would you like to play again? Y/N").toUpperCase();
}
So the error occurs when trying to run the playOneGame() function a second time. The first time runs fine and a hand is created. The second time when it gets to hand = createNewHand(); it gives the object is not a function error.
To be clear, I have the hand created as an object, which contains properties cards, handName, score, docHandName where cards is an array of card objects, themselves containing properties of suite, faceValue.
The error gives the line newHand = new hand(); in function createNewHand() as the reference line.
Help?
The second line of playOneGame is overriding your global hand function with an instance of hand. So when createNewHand runs again hand it is no longer the same thing.
You should probably rename the function hand to Hand.

Increment letters in javascript

I'm trying to increment a letter used in a recurring function, This function is called every time a user selects another possible end point. However it keeps using the name B, is there a way to increment it each time?
var tempEnd = String.fromCharCode('A'.charCodeAt(0) + 1);
/* create end point */
function end_point(t) {
calculate_start = false;
name = tempEnd;
marker = new nokia.maps.map.StandardMarker(coordinate, {
text: name,
draggable: true,
e_num: end_ar.length
});
marker.addListener("drag", dragAndDrop, true);
marker.addListener("dragend", dragAndDrop, false);
document.getElementById("points").style.display = 'none';
map.objects.add(marker);
if (t == true) {
map.zoomTo(map.getBoundingBox());
}
end_ar.push(coordinate);
createTable();
};
Thanks
Just replace it with
var tempEnd='A';
tempEnd = String.fromCharCode(tempend.charCodeAt(0) + 1);
Seems like you want to use tempEnd to increment, in which case you could store name externally and then call it each time you want to increment:
//store name
var name = "A"
//create tempEnd incrementation
function tempEnd(str){
var number = 1;
letter = String.fromCharCode(str.charCodeAt(0) + number);
number++;
return letter;
}
//call name on tempEnd
name=tempEnd(name);
name=tempEnd(name);
//name is now "C"

Javascript array results returning undefined

I have been working on a simple math game and am having problems getting the overall answer results to return after the end of the game.
Here is what my return function looks like
function pShowResults() {
var pNumResults = document.getElementById("results");
for (var i = 0; i <= 10; i++) {
pNumStore.push(pNumGuess[i]);
var pNumTable = document.createElement("div");
pNumTable.innerHTML = (pNumGuess[i]);
pNumResults.appendChild(pNumTable);
}
}
Here is the full script
Pretty much need debugging help. I new to this so I'm guessing there is a ton that's off, but as long as I can get the results fed back I should be fine.
You are not passing the value of x in many placess
$(document).ready(function () {
//declare arrays and variables for use below
var pNum1 = [];
var pNum2 = [];
var pNumAns = [];
var pNumGuess = [];
var pNumStore = [];
var pNumCarry = 0;
var pNumTrack = 0;
var pNumMessageRight = ['Awesome Job!', 'Correct!', 'Great Job!'];
var pNumMessageWrong = ['Oh No! That Was Wrong!', 'Incorrect!', 'That\'s Wrong'];
$(".Play").click(function () {
$("#popup").attr("class", "on");
pNumTrack = 0;
pNumGen(pNumTrack);
});
$(".pNumSubmit").click(function () {
pNumCalc(pNumTrack-1);
});
$(".pNumNext").click(function () {
pNumGen(pNumTrack);
});
function pNumGen(x) {
pNum1[x] = (Math.round(Math.random() * 51));
pNum2[x] = (Math.round(Math.random() * 51));
pNumAns[x] = pNum1[x] + pNum2[x];
$(".pNum1").html(pNum1[x]);
$(".pNum2").html(pNum2[x]);
$(".pNumGuess").val("");
$(".pNum1").html(pNumTrack[x]);
if (pNumTrack == 2) {
$(".pNumNext").html("");
$(".pNumSubmit").html("Close");
pShowResults();
}
pNumTrack++;
}
function pNumCalc(x) {
pNumGuess[x] = $(".pNumGuess").val();
if (pNumGuess[x] == pNumAns[x]) {
$(".message").html(pNumMessageRight[Math.floor(Math.random() * pNumMessageRight.length)]);
$(".pNumNext").html("Next Question >")
} else {
$(".message").html(pNumMessageWrong[Math.floor(Math.random() * pNumMessageWrong.length)]);
$(".pNumNext").html("Maybe The Next Question >")
}
}
function pShowResults() {
var pNumResults = document.getElementById("results");
for (var i = 0; i < pNumGuess.length; i++) {
pNumStore.push(pNumGuess[i]);
var pNumTable = document.createElement("div");
pNumTable.innerHTML = (pNumGuess[i]);
pNumResults.appendChild(pNumTable);
}
}
});
Demo: Fiddle
There is a function called pNumCalc in your code which you have set to take in an argument, but you never pass one in. You use the argument to store the results in the pNumGuess array, but since the argument is never passed in, the guesses are never stored, and you end up with undefined as the answers the user gave.
Updated fiddle: http://jsfiddle.net/dwdX9/2/. Not sure how close this is to what you actually want though, but hopefully it gets you on the right track.
Because StackOverflow wants code to to be included when JSFiddle is...:
pNumCalc(pNumTrack)
You forget to define array before use it.
function pShowResults() {
var pNumStore = new Array();
var pNumResults = document.getElementById("results");
for (var i = 0; i <= 10; i++) {
pNumStore.push(pNumGuess[i]);
var pNumTable = document.createElement("div");
pNumTable.innerHTML = (pNumGuess[i]);
pNumResults.appendChild(pNumTable);
}
}
I must suggest you should use jquery instead.
After visiting your Fiddle seems like there are many problems with the code. and also your question is unclear.
for e.g.
$(".pNumSubmit").click(function () {
//why x value not passed?
pNumCalc();
});
function pNumCalc(x) {
pNumGuess[x] = $(".pNumGuess").val();
if (pNumGuess[x] == pNumAns[x]) {
$(".message").html(pNumMessageRight[Math.floor(Math.random() * pNumMessageRight.length)]);
$(".pNumNext").html("Next Question >")
} else {
$(".message").html(pNumMessageWrong[Math.floor(Math.random() * pNumMessageWrong.length)]);
$(".pNumNext").html("Maybe The Next Question >")
}
}
Please clear which array is returning undefined so that others can help you.

Categories