Let website speak by itself - chrome extensions!
Hello! guys, I’m Clark. In this post I want to share how to use chrome extensions and some method of javaScript let website speak by itself!
In the project below, I will use Time For Kids as an example, make a chrome extensions to catch content in article of Time For Kids, When I get content of article, I will use SpeechSynthesisUtterance and SpeechSynthesis to speak text, they are method of JavaScript.
Create A Project Of Chrome Extensions
Ok so first of all, we need to create a project for chrome extensions, so like npm project need package.json, you should create a file manifest.json, if you expect your project can be a chrome extensions.
The content of manifest.json below:
{
"manifest_version": 2,
"name": "Reciting articles of time for kinds",
"description": "Reciting articles of time for kinds",
"version": "1.0.0",
"icons": {
"16": "icon.png",
"48": "icon.png",
"128": "icon.png"
},
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"activeTab"
],
"content_scripts": [
{
"matches": [
"https://www.timeforkids.com/*"
],
"js": [
"execute.js"
]
}
]
}
We need to pay attention to a few points:
icons
: You must to put a same name’s file in the root folder, it is your icon of chrome extensionsbrowser_action
: It have two attributes, The first isdefault_icon
,default_icon
mean same toicons
above, The second isdefault_popup
,default_popup
’s value is a HTML file, we can use it to trigger event.content_scripts
: It is a very interesting attributes, It have two attributes, The first ismatches
and the second isjs
,matches
can defined a domain, if users visit webpages at the this domain, then chrome extensions will auto load code of specified JavaScript file byjs
.
So far we already know through manifest.json file that we need to create another two files, that is popup.html and execute.js.
popup.html
Our HTML don’t need too complex, only two button is enough, the one is start, the another one is stop:
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml" style="width:100px;">
<head>
<title>Reciting articles</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body id="body">
<button id="recite">Start Recite</button>
<button id="stopRecite">Stop Recite</button>
<script src="./popup.js"></script>
</body>
</html>
If you observe the code above, you can find that I secretly loaded a JavaScript file call in popup.html, The JavaScript file is popup.js:
const getSelectedTab = (tabs) => {
const tabId = tabs[0].id;
const sendMessage = messageObj => (
chrome.tabs.sendMessage(tabId, messageObj)
);
document.getElementById('recite').addEventListener(
'click', () => sendMessage({ action: 'RECITE' })
);
document.getElementById('stopRecite').addEventListener(
'click', () => sendMessage({ action: 'STOP_RECITE' })
);
};
chrome.tabs.query({ currentWindow: true, }, getSelectedTab);
Except we can add event listener of click to button of start and stop in popup.js, we also can use the API from chrome to control webpages, like the following two:
The first is chrome.tabs.query, it can find all tabs currently open in chrome browser, The first parameter set the currently using tab, The second parameter is a callback function.
callback function in the code above is getSelectedTab
and getSelectedTab
receive a parameter called tabs
, tabs
is array type, in the tabs
will have all match conditional tab data, did you remember my conditions? I set the currently active tab, so only will have a tab in the tabs, even so the tabs
still is a array type, so we need to get currently tab data by tabs[0]
.
The second is chrome.tabs.sendMessage, if currently webpages have chrome.runtime.onMessage.addListener, then we can let chrome extensions communication currently webpages by send message through chrome.tabs.sendMessage
But at this moment, maybe you will think: “All webpages does have chrome.runtime.onMessage.addListener, how is that possible?”
Yes! you are right! That is impossible, so we failed?
No! did you remember we have a very interesting attributes in the manifest.json? It is content_scripts
, Is it the same as you think?
execute.js
So though the target webpage doesn’t have chrome.runtime.onMessage.addListener, but we still can add it in the target webpages by execute.js of content_scripts
:
const onMessage = (message) => {
switch (message.action) {
case 'RECITE':
/* play */
break;
case 'STOP_RECITE':
/* stop */
break;
default:
break;
}
}
chrome.runtime.onMessage.addListener(onMessage);
Because our popup.html have two button, so I need to use switch
to set two type event for execute, the one is start recite, the another one is stop recite, then we can write down some code for event of start and stop.
First event of start, we have to get content of article, so I observe HTML tag on the webpages of time for kids, I can find content of article, it is in the second div
of class is columns small-12 medium-offset-2 medium-8 end
:
So I can write down a function to get content text:
const getArticleContent = () => {
let articleContent = '';
const article = document.body.getElementsByClassName('columns small-12 medium-offset-2 medium-8 end')[1];
const paragraphs = article.querySelectorAll('p:not([class])');
paragraphs.forEach((paragraph) => { articleContent += `${paragraph.innerText} `; });
return articleContent;
};
Next we need to use SpeechSynthesisUtterance and SpeechSynthesis to speak text:
const recite = () => {
const articleContent = getArticleContent();
const utterThis = new SpeechSynthesisUtterance(articleContent);
utterThis.lang = 'en-US';
const synth = window.speechSynthesis;
synth.speak(utterThis);
};
But you need to attention pay to that SpeechSynthesisUtterance have many national intonation, and I expect time for kinds is english article, so I set utterThis.lang
to en-US
, if you want to know other land, you can visit DEMO of mdn to try it.
Now we are finished a function for recite, so we can add the function to the case 'RECITE'
of switch
, and the another case 'STOP_RECITE'
we can use cancel
of SpeechSynthesis directly stop recite:
const onMessage = (message) => {
switch (message.action) {
case 'RECITE':
recite();
break;
case 'STOP_RECITE':
window.speechSynthesis.cancel();
break;
default:
break;
}
}
chrome.runtime.onMessage.addListener(onMessage);
Finally, we have to test if the chrome extension is correct execute, open your chrome and go to the extensions:
Next click load the unpacked extension, then choose your chrome extension project folder.
When you finish all steps above, You can go to a any article of Time For Kids and use your chrome extensions let webpages speak by itself!
I would all code above put in my GitHub, welcome guys clone it and try yourself!
You guys can commit the message below if you have any question!