I am using the p5.js library, and I am working on a speech recognition - text to speech project. Kind of a chatbot.
Input is voice input which becomes a string.
I am outputting the result from a txt file, using a markov chain. Output is a string contained in a div.
My question is:
Is there a way to hide/show the div containing my input/output (.myMessage and .robotMessage) in intervals?
I want the whole screen first showing only the input when I am talking, then input disappears and only output showing, then when the computer voice finishes speaking my input is shown in the screen and so on...
Here some parts of the code, let me know if it is clear enough.
//bot
function setup() {
noCanvas();
//reads and checks into the text file
for (var j = 0; j < names.length; j++) {
var txt = names[j];
for (var i = 0; i <= txt.length - order; i++) {
var gram = txt.substring(i, i + order);
if (i == 0) {
beginnings.push(gram);
}
if (!ngrams[gram]) {
ngrams[gram] = [];
}
ngrams[gram].push(txt.charAt(i + order));
}
}
//voice recognition
let lang = 'en-US';
let speechRec = new p5.SpeechRec(lang, gotSpeech);
let continuous = true;
let interim = false;
speechRec.start(continuous, interim);
//text-to-speach
speech = new p5.Speech();
speech.onLoad = voiceReady;
function voiceReady() {
console.log('voice ready');
}
//input-ouput
function gotSpeech() {
if (speechRec.resultValue) {
var p = createP(speechRec.resultString);
p.class('myMessage');
}
markovIt();
chooseVoice();
speech.speak(answer);
}
}
and
function markovIt() {
var currentGram = random(beginnings);
var result = currentGram;
for (var i = 0; i < 100; i++) {
var possibilities = ngrams[currentGram];
if (!possibilities) {
break;
}
var next = random(possibilities);
result += next;
var len = result.length;
currentGram = result.substring(len - order, len);
}
var answer = result;
window.answer = answer;
var p2 = createP(answer);
p2.class('robotMessage');
}
how the HTML looks
<div class="container">
<div class="myMessage"></div>
<div class="robotMessage"></div>
</div>
Use select() to get a document element by its id, class, or tag name. e.g:
let my_div = select("myMessage");
Change the style of an element by style().
e.g hide:
my_div.style("display", "none");
e.g. show:
my_div.style("display", "block");
See also Toggle Hide and Show
Related
I am trying to add a moreLink in full calendar on each day i have events and in the more link i want to force displaying all the events on that day!
this is the solutin i choose because the title of the events are very long and do not fit in a tablet or phone screen!
so far i am unsuccesfull on the days i have one single event because the function computeRowLevelLimit returns false!
i am open to any crazy idea that helps me but keep in mind that i am a java dev with minimal kowledge of js and add some extra info if possible
since i was under presure i took the matter in my own hands so here is the resolve
here i added the last else in order to be able to execute 2 methods when levelLimit is false
limitRows: function (levelLimit) {
var rowStructs = this.eventRenderer.rowStructs || [];
var row; // row #
var rowLevelLimit;
for (row = 0; row < rowStructs.length; row++) {
this.unlimitRow(row);
if (!levelLimit) {
rowLevelLimit = false;
}
else if (typeof levelLimit === 'number') {
rowLevelLimit = levelLimit;
}
else {
rowLevelLimit = this.computeRowLevelLimit(row);
}
if (rowLevelLimit !== false) {
this.limitRow(row, rowLevelLimit);
} else {
this.unlimitRow2(row);
this.addMoreLink(row);
}
}
},
The added metod are:
- one for clearing the existing links
- second for adding new links - remember this is for days with only one event
the methods are the following:
unlimitRow2: function (row) {
var rowStruct = this.eventRenderer.rowStructs[row];
var cellMatrix;
var oneDayCell;
cellMatrix = rowStruct.cellMatrix;
var _this = this;
for (i = 0; i < cellMatrix.length; i++) {
// console.log("celmatrix ", cellMatrix[i]);
oneDayCell = cellMatrix[i];
console.log("outati", oneDayCell)
if (oneDayCell.moreEls) {
oneDayCell.moreEls.remove();
oneDayCell.moreEls = null;
}
if (oneDayCell.limitedEls) {
oneDayCell.limitedEls.removeClass('fc-limited');
oneDayCell.limitedEls = null;
}
}
},
and,
addMoreLink: function (row) {
// console.log("inside addMoreMethod", row);
var rowStruct = this.eventRenderer.rowStructs[row];
var cellMatrix;
var oneDayCell;
var coloana;
var nrCol;
var td, moreWrap, moreLink;
var moreNodes = [];
var segsBelow;
// console.log ("structura randului", rowStruct);
cellMatrix = rowStruct.cellMatrix;
var _this = this;
for (i = 0; i < cellMatrix.length; i++) {
// console.log("celmatrix ", cellMatrix[i]);
oneDayCell = cellMatrix[i];
for (j = 0; j < oneDayCell.length; j++) {
coloana = oneDayCell[j];
nrCol = j;
segsBelow = _this.getCellSegs(row, nrCol);
console.log($(coloana));
moreLink = _this.renderMoreLink(row, nrCol, segsBelow);
moreWrap = $('<div/>').append(moreLink);
coloana.append(moreWrap);
moreNodes.push(moreWrap[0]);
// rowStruct.limitedEls = $(limitedNodes);
}
rowStruct.moreEls = $(moreNodes); // for easy undoing later
}
},
and for the rest i manipulated a litle bit limitRow: function (row, levelLimit)
also i had to hide the text and i choose a nasty method, not proud of it but ...
in getMoreLinkText(num) i added a last else if
else if (num === 0 ){
return '';
}
In a webpage there is a textarea (id="text") and also a button (id="dlButton3").
What I have to do is to enter the text into the textarea. And when I press the button, then the following will be happened:
Text in the text area will be loaded into the function,
The text will be spitted with delimiters ""
There is a for loop to compare all the lengths of the strings, and
Print the longest one value
The problem is, with the following code, I can take the string from the text area but dun know why I cannot split the string, and it returns the error "Uncaught ReferenceError: targetString is not defined"
The code is as followed
function findlongestword(){
var testing = document.getElementById('text').value;
console.log(testing);
var strText = testing.split(" ");
var length = 0;
for (var i=0; i < strText.length; i++) {
if (length < strText[i].length) {
length = strText[i].length;
targetString = strText[i]
}
}
console.log (targetString);
}
window.onload = function(){
findlongestword();
document.getElementById("dlButton3").onclick = findlongestword;
}
What can be the error?
Many thanks for your help in advance!
Read more about block scope targetString only exists within the loop
function findlongestword() {
var testing = document.getElementById('text').value;
var strText = testing.split(" ");
var length = 0;
var targetString = '';
for (var i=0; i < strText.length; i++) {
if (length < strText[i].length) {
length = strText[i].length;
targetString = strText[i]
}
}
console.log (targetString);
}
window.onload = function() {
findlongestword();
document.getElementById("dlButton3").onclick = findlongestword;
}
"Uncaught ReferenceError: targetString is not defined"
You did not declare targetString before using it within your loop. Therefore javascript did not know where to find or 'Refer' to it after the loop ended.
By adding var targetString = ""; before the loop begins the problem will be solved.
function findlongestword(){
var testing = document.getElementById('text').value;
console.log(testing);
var strText = testing.split(" ");
//ADD HERE
var targetString = "";
var length = 0;
for (var i=0; i < strText.length; i++) {
if (length < strText[i].length) {
length = strText[i].length;
targetString = strText[i]
}
}
console.log (targetString);
}
window.onload = function(){
findlongestword();
document.getElementById("dlButton3").onclick = findlongestword;
}
I am trying to write a script that will convert all characters to lowercase if a particular nested style is applied. I can't seem to figure out the correct syntax to get the text.
I originally tried the following, which worked to an extend, but lowercased the entire paragraph rather than only the text that has the character style applied:
function lowerCaseNest(myPStyle, myCStyle){
var myDocument = app.documents.item(0);
//Clear the find/change preferences.
app.findTextPreferences = NothingEnum.nothing;
app.changeTextPreferences = NothingEnum.nothing;
//Set the find options.
app.findChangeTextOptions.caseSensitive = false;
app.findChangeTextOptions.includeFootnotes = false;
app.findChangeTextOptions.includeHiddenLayers = false;
app.findChangeTextOptions.includeLockedLayersForFind = false;
app.findChangeTextOptions.includeLockedStoriesForFind = false;
app.findChangeTextOptions.includeMasterPages = false;
app.findChangeTextOptions.wholeWord = false;
app.findTextPreferences.appliedParagraphStyle = myPStyle;
var missingFind = app.activeDocument.findText();
var myDoc = app.documents[0];
for ( var listIndex = 0 ; listIndex < missingFind.length; listIndex++ ) {
for (i = missingFind[listIndex].nestedStyles.length-1;i>=0; i--) {
for (j = missingFind[listIndex].nestedStyles[i].parent.characters.length-1;j>=0; j--) {
if (missingFind[listIndex].nestedStyles[i].parent.characters[j].contents.appliedCharacterStyle(myCStyle)) {
var myString = missingFind[listIndex].nestedStyles[i].parent.characters[j].contents;
if (typeof(myString) == "string"){
var myNewString = myString.toLowerCase();
missingFind[listIndex].nestedStyles[i].parent.characters[j].contents = myNewString;
}
}
}
}
app.findTextPreferences = NothingEnum.nothing;
app.changeTextPreferences = NothingEnum.nothing;
}
I then tried playing around with appliedNestedStyles, but can't seem to figure out how to retrieve the text that the nested style is applied to.
Could anyone help with this?
Thanks!
John
Unless I am wrong the appliedNestedStyle can be looked after in the F/C dialog by targeting the applied characterStyle:
GREP
Find : .+
Format : character style => myCharStyle
then
var found = doc.findGrep();
…
I actually took a different tack, and figured out something that works:
function lowerCaseNest(myPStyle, myCStyle){
for (var i = 0; i < app.activeDocument.stories.length; i++){
for (var j = 0; j < app.activeDocument.stories[i].paragraphs.length; j++){
var myP = app.activeDocument.stories[i].paragraphs[j];
if (myP.appliedParagraphStyle.name==myPStyle) {
for (k=0; k<myP.characters.length; k++) {
if(typeof(myP.characters[k].appliedNestedStyles[0]) != 'undefined'){
if(myP.characters[k].appliedNestedStyles[0].name == myCStyle) {
var myC = myP.characters[k].contents;
if (typeof(myC)=='string'){
var myNewString = myC.toLowerCase();
myP.characters[k].contents = myNewString;
}
}
}
}
}
}
}
}
Still would be interested in knowing if there's an easier way to handle this, as I'm afraid this may take longer to run on long documents, since it's dealing with every paragraph individually.
I've created a program where you can choose a set of images by checking checkboxes. The image URL's and the alt-texts are stored in two arrays. When clicking av button on the HTML-page you open a new window that calls on the arrays with window.opener.
When closing the new window I would like to empty the arrays. Otherwise the pictures chosen in the first round are displayed in the slideshow when opening it the second time. I understand you can empty arrays by this method: array.length= 0;
But where do I add the code? I'm quite lost. I'm pasting the code, perhaps someone can give me a hand.
var imgUrlList = [], imgTextList = [], //These arrays need to be emptied
windVar = null;
function init() {
var tags, i, openWindow;
tags = document.getElementsByClassName("unmarkedImg");
openWindow = document.getElementById("slideShowBtn");
openWindow.onclick = savePicsForSlideshow;
for (i = 0; i < tags.length; i++) {
tags[i].parentNode.onmouseover = showLargePict;
tags[i].parentNode.onmouseout = hideLargePict;
}
}
window.onload = init;
function showLargePict() {
var largePictTagDiv = this.getElementsByClassName("innerBox")[0];
var largePictTagParentDiv = largePictTagDiv.parentNode;
var imgTag = largePictTagParentDiv.getElementsByTagName('img')[0];
var checkBoxlargePict = largePictTagDiv.getElementsByTagName('input')[0];
if (checkBoxlargePict.checked)
imgTag.className = "markedImg";
else imgTag.className = "unmarkedImg";
largePictTagDiv.style.visibility = "visible";
} // End showLargePict
function hideLargePict() {
var largePictTag;
largePictTag = this.getElementsByClassName("innerBox")[0];
largePictTag.style.visibility = "hidden";
}
function savePicsForSlideshow() {
var innerBoxes = document.getElementsByClassName("innerBox");
for (i = 0; i < innerBoxes.length; i++) {
checkBoxlargePict = innerBoxes[i].getElementsByTagName('input')[0];
if (checkBoxlargePict.checked) {
var imgTagSrc = innerBoxes[i].getElementsByTagName('img')[0].src;
imgUrlList.push(imgTagSrc);
var spanTagText = innerBoxes[i].getElementsByTagName('span')[0].innerHTML;
imgTextList.push(spanTagText);
}
}
if (imgTextList.length > 0) {
newWindow(500, 600, "slideshow.htm");
}
}
function newWindow(width, height, filename) {
var windowProperties;
windowProperties = "top=100,left=100,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=no,width=" + width + ",height=" + height;
if (windVar != null) if (windVar.closed == false) windVar.close();
windVar = window.open(filename, "", windowProperties);
}
Please excuse my programming and English grammar shortcomings. I'm new to javascript.
//Henrik, Göteborg, Sweden.
At the beginning of the savePicsForSlideshow function, empty out each array.
imgUrlList.length = 0;
imgTextList.length = 0;
You can check if thw window is close with the property closed of the object window
if(window.closed)
{
array.length = 0;
}
I'm using the unscramble plugin from Jason Frame's Grab Bag.
But it seems only to work with text that has no format. I want that the text formatting remains unchanged.
Example: http://jsfiddle.net/G6BdX/
The unscramble plugin:
$.fn.unscramble = function() {
this.each(function() {
var $ele = $(this), str = $ele.text(), replace = /[^\s]/,
state = [], choose = [], reveal = 25, random = randomAlphaNum;
for (var i = 0; i < str.length; i++) {
if (str[i].match(replace)) {
state.push(random());
choose.push(i);
} else {
state.push(str[i]);
}
}
shuffle(choose);
$ele.text(state.join(''));
var timer = setInterval(function() {
var i, r = reveal;
while (r-- && choose.length) {
i = choose.pop();
state[i] = str[i];
}
for (i = 0; i < choose.length; i++) state[choose[i]] = random();
$ele.text(state.join(''));
if (choose.length == 0) clearInterval(timer);
}, 100);
});
return this;
};
As you can see when pressed 'Unscramble me' the text format and the <br> tags are removed.
Due to my lack of skills in making jQuery plug-ins, I don't know what the problem is. I think it goes wrong when replacing /[^\s]/ but I'm not sure.
Somebody has an answer?
Thanks in advance.