Auto search from google after coverting speech to text javascript - javascript

After some speech-to-text conversion into the $searchText variable, I show a button.
By clicking this button, you trigger a search from google.
However, I want to enter a text which automatically starts a search (without clicking on a button).
Example: If, after 3 seconds, $searchText is not empty, it searches automatically without clicking a button. I am a beginner. Can you help?
$button.addEventListener('click', () => {
if ($searchText.value !== '') {
var url = 'https://www.google.com/search?q=' + $searchText.value;
window.open(url, '_blank');
}
});

I have added an input box for simplifying. I believe you want something like this.
<!DOCTYPE html>
<html lang="en">
<body>
<!-- Your searchbox -->
<input type="text" id="searchText">
<script>
let timerID = null;
const $searchText = document.getElementById("searchText");
$searchText.addEventListener('input', () => {
clearTimeout(timerID)
if (!$searchText.value) {
return ;
}
timerID = setTimeout(() => {
const url = 'https://www.google.com/search?q=' + $searchText.value;
window.open(url, '_blank');
}, 3000 /* 3 seconds */)
});
</script>
</body>
</html>

Related

How to make addEventListener stream continuously on button submit

I am trying to stream a list of json objects from my servers endpoint to my frontend using javascript and html. Below is my code. Currently addEventListener works fine when I click my form button (HTML also added below for reference). Heres my problem:
The list of objects my server endpoint returns is a single list which is continuously having objects appended to the list. So I want my front end to refresh automatically every second to show the latest version. And so I am finding a way for my addEventListener to rerun the function each time after clearing the HTML it is pushing. Currently, I have to click on my button to achieve that and the previously pushed HTML is not getting cleared either. So each time I click on the button, I am getting all the existing HTML displayed as many times as I have clicked the button (old versions) plus the latest version of my endpoint data.
The solution I want to achieve is to be able to click on my start stream button once, and have the function run every X seconds after clearing the older data each time to only show the latest list returned by fetch.
const startStream = document.querySelector('form')
const messageOne = document.querySelector('#message-1')
startStream.addEventListener('submit', (e) => {
e.preventDefault()
messageOne.textContent = 'Streaming...'
function fetchData() {
fetch('http://localhost:1337/dashboard')
.then(response => {
if (!response.ok) {
throw Error('ERROR')
}
response.json().then(events => {
events.forEach(event => {
const html = `<div class="event">
Event: ${event.name}
</div>
`
let div = document.createElement('div');
div.setAttribute("id", "app");
div.innerHTML = html;
document.body.appendChild(div);
})
})
.catch(error => {
console.log(error)
})
})
}
fetchData()
});
<h1>Dashboard</h1>
<form>
<button>Start Stream</button>
</form>
<p id="message-1"></p>
Is the question just how to run a function every X seconds? If so, the function you're looking for is setInterval, which is like setTimeout but it continues running over and over. For example:
setInterval( () => console.log("hello"), 100 )
will log "hello" once every 100ms
This is a detailed example but try this approach it may work for you any corrections will be great:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Repeating Event example</title>
</head>
<body>
<div>
<button id="start-stream-btn">Start Streaming</button>
<p id="message-section"></p>
<div id="app-data-div"></div>
</div>
<script>
window.onload = function () {
var streamButton = document.getElementById("start-stream-btn");
var messageContainer = document.getElementById("message-section");
var appDataContainer = document.getElementById("app-data-div");
function handleFetchError(appDataContainerRef, messageContainerRef) {
messageContainerRef.innerText = "There was an Error fetching data!";
// optional clear previous data or leave it by commenting the line below
appDataContainerRef.innerHTML = "";
}
// Define the function that fetches our data
function fetchData(appDataContainerRef, messageContainerRef, timerRef) {
fetch('http://localhost:1337/dashboard')
.then(response => {
if (!response.ok) {
throw Error('ERROR')
}
response.json().then(events => {
events.forEach(event => {
// Create your string here with a loop
const htmlString = `<div class="event">
Event: ${event.name}
</div>`;
// Set your string here - replacing any previous
appDataContainerRef.innerHTML = htmlString;
})
})
.catch(error => {
console.log(error);
handleFetchError(appDataContainerRef, messageContainerRef);
// optional clear timer on error, you can comment this out if you want the timer to continue
clearInterval(timerRef);
});
}).catch(error => {
console.log(error);
handleFetchError(appDataContainerRef, messageContainerRef);
// optional clear timer on error, you can comment this out if you want the timer to continue
clearInterval(timerRef);
});
}
var timerRef;
// Attach event listener to your button
streamButton.addEventListener("click", function (e) {
e.preventDefault(); //if it is in a form or if you have any form on your current page
messageContainer.innerText = "Streaming...";
timerRef = setInterval(function () {
// check and clear your timer before adding another timer here on click
if (!!timerRef) clearInterval(timerRef);
fetchData(appDataContainer, messageContainer, timerRef);
}, 1000); // X seconds intervals i.e. for now 1s = 1000ms
});
}
</script>
</body>
</html>

JS Prevent multiple functions running simultaneously

I am trying to make a page which redirect users to different pages after 20s using different buttons or elements and I want to prevent multiple timeouts I mean i want to keep 20s interval between redirecting to any site.
function redirect1(){
window.open('https://youtube.com', '_blank')
}
function redirect2(){
window.open('https://google.com', '_blank')
}
<html>
<p onclick='settimeout(redirect1, 20000)'>Youtube</p>
<p onclick='settimeout(redirect2, 20000)'>Google</p>
</html>
In the code below timeouts[site] = timeouts[site] || makes sure that the button can be clicked only once every 20 seconds
Also, created a single function so as not to have repetitive code
const redirect = (() => {
let timeouts = {};
return (site, delay) => {
timeouts[site] = timeouts[site] || setTimeout(() => {
window.open(site, '_blank');
timeouts[site] = null;
}, delay);
};
})();
<html>
<p onclick="redirect('https://youtube.com', 20000)">Youtube</p>
<p onclick="redirect('https://google.com', 20000)">Google</p>
</html>

twitter share button quirk

Link to my in codepen: codepen.io/neel111/pen/dRBQNY?editors=1010
When the tweet button is clicked then it redirect to the page to tweet in the twitter, with a preselected text to tweet.
The JavaScript code used there is given below just for a quick look:
//-------------quotes--------
(function(){
window.addEventListener("load", makeRequest);
function makeRequest(mk){
document.getElementsByClassName("buttonQ")[0].addEventListener("click", makeRequest);
function reqListener(rl) {
if(httpR.readyState === XMLHttpRequest.DONE) {
var quote;
if(httpR.status === 200) {
quote = JSON.parse(httpR.responseText);
document.getElementsByClassName("quote")[0].innerHTML = quote[0].body;
} else {
alert("There was a problem with the request!")
}
}
}
var httpR;
httpR = new XMLHttpRequest();
httpR.onreadystatechange = reqListener
httpR.open("GET", "https://quote-api.glitch.me/pull/1", true);
httpR.send();
}
//----------------------tweet-------------------
window.addEventListener("load", function() {
document.getElementsByClassName("buttonT")[0].addEventListener("click", tweetEvent);
})
function tweetEvent(twt) {
//twt.preventDefault();
document.getElementsByClassName("quote")[0].normalize();
var tweetBody = document.getElementsByClassName("quote")[0].childNodes[0].nodeValue;
var URLBase = document.getElementsByClassName("twitter-share-button")[0].getAttribute("href");
var URLExtended = URLBase + "?hashtags=quotes&text=" + encodeURIComponent(tweetBody);
document.getElementsByClassName("twitter-share-button")[0].setAttribute("href", URLExtended);
}
})();
Quirk:
when the tweet button is clicked for the first time after the page is loaded/refreshed then the preselected text in the redirected page to tweet is
Preselected_text(quote)_from_the_main_page #tweet
But after the first click, everytime the tweet button is click the preselected text in the redirected page to tweet is
Preselected_text(quote)_from_the_main_page?hashtags=quotes #quotes
Where i am doing wrong?
So I think the problem is that you are modifying the href of the anchor tag and inserting the modified href into the dom. What I would do instead is to get rid of the in the button and build the url like you are but instead of modifying something in the dom just call window.open(extendedUrl);
Something like this should get you started:
window.addEventListener("load", function() {
document.getElementsByClassName("buttonT")[0].addEventListener("click", tweetEvent);
})
function tweetEvent(twt) {
//twt.preventDefault();
document.getElementsByClassName("quote")[0].normalize();
var tweetBody = document.getElementsByClassName("quote")[0].childNodes[0].nodeValue;
var url = "https://twitter.com/intent/tweet?hashtags=quote&text="+encodeURIComponent(tweetBody);
return window.open(url);
}
})
As you can see I have simplified the url building and then passed the resulting url to window.open which will open the url in a new window/tab (depending on user preference in their browser... find more on that here).

Using History API for Ajax div load

In my WP site I have post content loaded into a div with ajax on a click event.
I need it now to change the url for the current post, would prefer not using hashes.
How would I implement this using my js?
JS:
jQuery(document).ready(function() {
jQuery('#main-content').on('click', '.page a', function(e) {
e.preventDefault();
var url = jQuery(this).attr('href');
jQuery('#main-content').html('<h4>Loading...</h4>').load(url+ ' #main-content');
});
});
I have researched History API but I'm not sure how to implement it with my js.
I haven't done this yet myself, but this should be very simple using the pushState: https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history
var stateObj = { foo: "bar" };
history.pushState(stateObj, "New Page Title", "newPath.html");
Here's an extended example, where you would replace the content, path, and title with the results from your WordPress query that would grab the next post.
<!doctype html>
<html>
<head>
<title>Push State Testing</title>
<script type='text/javascript'>
var i = 1;
function goToPage( pageNumber, pushState ) {
var content = "Hello World " + pageNumber,
path = "hello_world_" + pageNumber,
title = content,
stateObj = {"content":content}
;
document.title = title;
document.getElementById('content').innerHTML = content;
if( pushState ) {
history.pushState({index:pageNumber}, title, path);
}
i = pageNumber;
}
function nextPage() {
goToPage( i+1, true );
}
window.onload = function() {
goToPage(1);
history.replaceState({index:1}, "Hello World 1", "hello_world_1");
}
window.onpopstate = function(event) {
goToPage(event.state.index, false);
}
</script>
</head>
<body>
<div id='content'>Push State Testing</div>
<button type='button' onclick='nextPage()'>Next</button>
</body>
</html>
In answer to the question in the comments. No, you don't need to know the path of the URL until you know the content. You replace the content and do the pushState at the exact same time:
$('#mainContent').html( contentFromWp );
history.pushState( state, titleFromWp, pathFromWp );
Okay, so to take the above and try to write it for you, which I can't test, so I can't guarantee that this will be working like my above examples...it would be something like this:
jQuery(document).ready(function() {
jQuery('#main-content').on('click', '.page a', function(e) {
e.preventDefault();
var url = jQuery(this).attr('href'),
title = jQuery(this).attr('title')
;
jQuery('#main-content').html('<h4>Loading...</h4>').load(url+ ' #main-content');
document.title = title;
history.pushState({url:url,title:title}, title, url );
});
});
window.onpopstate = function(event) {
document.title = event.state.title;
jQuery('#main-content').html('<h4>Loading...</h4>').load(event.state.url+ ' #main-content');
}
Note the need for onpopstate to make the back button work. You will also want to call a history.replaceState when your webpage first loads like I did in my example so that when users go back to the very first page the first page they were on will reload...otherwise, the user will only be able to go back to the second page they navigated to since going back to the first won't have a stateObj.

history.js stops firing statechange event after pressing back button 2 times

One of my customer has a lot of webistes based on lots of CMS (Wordpress, Drupal and so on). He wanted a generic directory, where professionals can register and share information. It is "generic", as it can be installed on any website (declined according to the website's business).
I developed it inside an iframe, as this can be installed on any CMS, and there were other good reasons to do it this way (CSS, SEO...). But as iframe-browsing is transparent for the navigation bar, I needed to do some tricks to allow visitors to copy/paste professionals's urls, share and fav them. I used history.js to update the navbar's URL, and when direct-accessing the iframe I redirect the user to the right "main website"'s page.
But my problem come when clicking the "back" button. For some reasons, the "statechange" event is not properly fired when clicking "back" a second time.
I developed a demo, you can see my problem live here, and you can download it here.
As you can see on the log div, when you click B and C, you'll get:
Push: /a.html
Push: /b.html
statechange trigered
Push: /c.html
statechange trigered
If you go back once, you'll get:
statechange trigered
Pop: /b.html
And if you go back a second time, you'll get:
Push: /c.html
statechange trigered
Instead of:
statechange trigered
Pop: /a.html
So my question:
What is going on here ?
main.html
<iframe id="my-test" src="a.html" width="500" height="500"></iframe>
<div id="log"></div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-browser/0.0.6/jquery.browser.min.js"></script>
<script src="history.js/scripts/bundled/html4+html5/jquery.history.js"></script>
<script type="text/javascript">
var test_url = 'http://so.ocarina.fr/test';
// used to avoid listening events trigered by the script itself
var manual_state_change = true;
// used to avoid pushing the previous page
var is_back = false;
$(document).ready(function () {
$('#my-test').load(function () {
// when iframe has loaded, we replace the navbar's url by
// the one from iframe's source.
if (!window.is_back) {
window.manual_state_change = false;
var History = window.History;
if (History.enabled) {
var url = $('#my-test').get(0).contentWindow.location.href;
if (url.indexOf('blank') > 0) {
return;
}
if (url.indexOf('test') > 0) {
url = url.substring(url.indexOf('test') + 4);
if (url.length === 0) {
url = '/';
}
}
$('#log').append('Push: ' + url + '<br/>');
var title = $("#my-test").contents().find("title").html();
document.title = title;
History.pushState({url: decodeURIComponent(url + '')}, title, window.test_url + decodeURIComponent(url + ''));
window.manual_state_change = true;
}
}
window.is_back = false;
}).trigger('load'); // triggered once to replace main.html by a.html
var History = window.History;
if (History.enabled) {
History.Adapter.bind(window, 'statechange', function () {
// if user clicks back, we should change the iframe's location
// to the backward url from history stack.
$('#log').append('statechange trigered <br/>');
if (window.manual_state_change === true) {
window.manual_state_change = false;
var state = History.getState();
var url = state.data.url;
$('#log').append('Pop: ' + url + '<br/>');
window.is_back = true;
$('#my-test').attr('src', window.test_url + url);
$('#my-test')[0].contentWindow.location = window.test_url + url;
window.manual_state_change = true;
}
});
}
});
</script>
a.html
<title>Test A</title>
<script type="text/javascript">
if (top.location === self.location) {
window.location = 'main.html';
}
</script>
<div id="content">
<p>This is test A</p>
Go to test B
</div>
b.html
<title>Test B</title>
<script type="text/javascript">
if (top.location === self.location) {
window.location = 'main.html';
}
</script>
<div id="content">
<p>This is test B</p>
Go to test C
</div>
c.html
<title>Test C</title>
<script type="text/javascript">
if (top.location === self.location) {
window.location = 'main.html';
}
</script>
<div id="content">
<p>This is test C</p>
<p>Go back to A using your backward button...</p>
</div>
I finally found my mistake: when clicking on my iframe's links, browser already add an entry to the history, so I shouldn't add an entry using pushState, but simply replace the current history entry using replaceState.
Bonus: we don't need to handle statechange, browser does anything as naturally as usual. Cool!
See the working demo here.
My code becomes:
<iframe id="my-test" src="a.html" width="500" height="500"></iframe>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-browser/0.0.6/jquery.browser.min.js"></script>
<script src="history.js/scripts/bundled/html4+html5/jquery.history.js"></script>
<script type="text/javascript">
var test_url = 'http://so.ocarina.fr/test2';
$(document).ready(function () {
$('#my-test').load(function () {
// when iframe has loaded, we replace the navbar's url by
// the one from iframe's source.
var History = window.History;
if (History.enabled) {
var url = $('#my-test').get(0).contentWindow.location.href;
if (url.indexOf('blank') > 0) {
return;
}
if (url.indexOf('test') > 0) {
url = url.substring(url.indexOf('test2') + 5);
if (url.length === 0) {
url = '/';
}
}
var title = $("#my-test").contents().find("title").html();
document.title = title;
History.replaceState({}, title, window.test_url + decodeURIComponent(url + '')); // YES!
}
}).trigger('load'); // triggered once to replace main.html by a.html
});
</script>

Categories