Skip to content

Instantly share code, notes, and snippets.

@kzkamiya
Last active August 29, 2015 14:10
Show Gist options
  • Save kzkamiya/453f38bd3abf9a4f2568 to your computer and use it in GitHub Desktop.
Save kzkamiya/453f38bd3abf9a4f2568 to your computer and use it in GitHub Desktop.
speech-input
<!DOCTYPE html>
<html>
<!--
https://bl.ocks.org/kzkamiya/raw/453f38bd3abf9a4f2568/
-->
<head>
<meta chraset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
</head>
<body>
<label class="fieldname1 font" for="keyword"><strong>キーワード</strong></label>
<style>
.si-wrapper {
display: inline-block;
position: relative;
}
.si-wrapper input {
margin: 0;
}
.si-wrapper button {
position: absolute;
top: 0;
right: 0;
height: 18px;
width: 18px;
margin: 0;
border: 0;
padding: 0;
background: none;
font: 0/0 a;
}
.si-mic,
.si-mic:after,
.si-holder,
.si-holder:before,
.si-holder:after {
position: absolute;
background: #333;
}
/* Microphone icon */
.si-mic {
display: block;
height: 25%; /* 8px / 32px */
top: 9.375%; /* 3px / 32px */
left: 37.5%; /* 12px / 32px */
right: 37.5%; /* 12px / 32px */
-webkit-border-radius: 99px 99px 0 0;
-moz-border-radius: 99px 99px 0 0;
border-radius: 99px 99px 0 0;
}
.si-mic:before,
.si-mic:after,
.si-holder {
-webkit-border-radius: 0 0 99px 99px;
-moz-border-radius: 0 0 99px 99px;
border-radius: 0 0 99px 99px;
}
.si-mic:before {
position: absolute;
z-index: 1;
content: '';
width: 150%; /* 12px / 8px */
height: 137.5%; /* 11px / 8px */
top: 100%; /* 8px / 8px */
left: -25%; /* -2px / 8px */
background: #fff;
}
.si-mic:after {
z-index: 1;
content: '';
width: 100%; /* 10px / 10px */
height: 100%; /* 10px / 10px */
top: 110%; /* 11px / 10px */
left: 0;
}
.si-holder {
display: block;
height: 40.625%; /* 13px / 32px */
width: 50%; /* 16px / 32px */
left: 25%; /* 8px / 32px */
top: 37.5%; /* 12px / 32px */
}
.si-holder:after {
content: '';
width: 66.666%; /* 8px / 16px */
height: 18.182%; /* 2px / 13px */
bottom: -30.769%; /* -4px / 13px */
left: 16.667%; /* 2px / 16px */
}
.si-holder:before {
content: '';
width: 33.333%; /* 4px / 16px */
height: 27.273%; /* 3px / 13px */
top: 92.308%; /* 12px / 13px */
left: 33.333%; /* 4px / 16px */
}
</style>
<div class="si-wrapper">
<input class="queryParam si-input" type="text" name="keyword" placeholder="keyword"/>
<button class="si-btn">
speech input
<span class="si-mic"></span>
<span class="si-holder"></span>
</button>
</div>
<script>
/*global webkitSpeechRecognition */
(function() {
'use strict';
if (! ('webkitSpeechRecognition' in window) ) return;
var talkMsg = '音声入力してください';
var patience = 10;
function capitalize(str) {
return str.length ? str[0].toUpperCase() + str.slice(1) : str;
}
var speechInputWrappers = document.getElementsByClassName('si-wrapper');
[].forEach.call(speechInputWrappers, function(speechInputWrapper) {
// find elements
var inputEl = speechInputWrapper.querySelector('.si-input');
var micBtn = speechInputWrapper.querySelector('.si-btn');
// size and position them
var inputHeight = inputEl.offsetHeight;
var inputRightBorder = parseInt(getComputedStyle(inputEl).borderRightWidth, 10);
var buttonSize = 0.8 * inputHeight;
micBtn.style.top = 0.1 * inputHeight + 'px';
micBtn.style.height = micBtn.style.width = buttonSize + 'px';
inputEl.style.paddingRight = buttonSize - inputRightBorder + 'px';
speechInputWrapper.appendChild(micBtn);
// setup recognition
var finalTranscript = '';
var recognizing = false;
var timeout;
var oldPlaceholder = null;
var recognition = new webkitSpeechRecognition();
recognition.lang = "ja-JP";
recognition.continuous = true;
function restartTimer() {
timeout = setTimeout(function() {
recognition.stop();
}, patience * 1000);
}
recognition.onstart = function() {
oldPlaceholder = inputEl.placeholder;
inputEl.placeholder = talkMsg;
recognizing = true;
micBtn.classList.add('listening');
restartTimer();
};
recognition.onend = function() {
recognizing = false;
clearTimeout(timeout);
micBtn.classList.remove('listening');
if (oldPlaceholder !== null) inputEl.placeholder = oldPlaceholder;
};
recognition.onresult = function(event) {
clearTimeout(timeout);
for (var i = event.resultIndex; i < event.results.length; ++i) {
if (event.results[i].isFinal) {
finalTranscript += event.results[i][0].transcript;
}
}
finalTranscript = capitalize(finalTranscript);
inputEl.value = finalTranscript;
restartTimer();
};
micBtn.addEventListener('click', function(event) {
event.preventDefault();
if (recognizing) {
recognition.stop();
return;
}
inputEl.value = finalTranscript = '';
recognition.start();
}, false);
});
})();
</script>
</body
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment