Submit button becomes invisible after speech input (Web Speech API) - user-interface

This code contains the user interface of the banking chatbot. I have used Mozilla's Web Speech API to implement the speech to text feature. After implementing it, I have faced a major bug. As soon as the user starts the speech recognition by clicking on the "Speak" button; the textarea automatically increases in size and covers or hides the Submit button which is preventing the user from submitting his/her query. I haven't been able to locate the error.
//initialize speech recognition API
window.SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
const recognition = new SpeechRecognition(); //initialize my instance of speech recognition
recognition.interimResults = true; //return results while still working on current recognition
//this is where your speech-to-text results will appear
let p = document.createElement("p")
const words = document.querySelector(".words-container")
words.appendChild(p)
//I want to select and change the color of the body, but this could be any HTML element on your page
let body = document.querySelector("body")
let cap_css_colors = ["AliceBlue","AntiqueWhite","Aqua","Aquamarine","Azure","Beige","Bisque","Black","BlanchedAlmond","Blue","BlueViolet","Brown","BurlyWood","CadetBlue","Chartreuse","Chocolate","Coral","CornflowerBlue","Cornsilk","Crimson","Cyan","DarkBlue","DarkCyan","DarkGoldenRod","DarkGray","DarkGrey","DarkGreen","DarkKhaki","DarkMagenta","DarkOliveGreen","Darkorange","DarkOrchid","DarkRed","DarkSalmon","DarkSeaGreen","DarkSlateBlue","DarkSlateGray","DarkSlateGrey","DarkTurquoise","DarkViolet","DeepPink","DeepSkyBlue","DimGray","DimGrey","DodgerBlue","FireBrick","FloralWhite","ForestGreen","Fuchsia","Gainsboro","GhostWhite","Gold","GoldenRod","Gray","Grey","Green","GreenYellow","HoneyDew","HotPink","IndianRed","Indigo","Ivory","Khaki","Lavender","LavenderBlush","LawnGreen","LemonChiffon","LightBlue","LightCoral","LightCyan","LightGoldenRodYellow","LightGray","LightGrey","LightGreen","LightPink","LightSalmon","LightSeaGreen","LightSkyBlue","LightSlateGray","LightSlateGrey","LightSteelBlue","LightYellow","Lime","LimeGreen","Linen","Magenta","Maroon","MediumAquaMarine","MediumBlue","MediumOrchid","MediumPurple","MediumSeaGreen","MediumSlateBlue","MediumSpringGreen","MediumTurquoise","MediumVioletRed","MidnightBlue","MintCream","MistyRose","Moccasin","NavajoWhite","Navy","OldLace","Olive","OliveDrab","Orange","OrangeRed","Orchid","PaleGoldenRod","PaleGreen","PaleTurquoise","PaleVioletRed","PapayaWhip","PeachPuff","Peru","Pink","Plum","PowderBlue","Purple","Red","RosyBrown","RoyalBlue","SaddleBrown","Salmon","SandyBrown","SeaGreen","SeaShell","Sienna","Silver","SkyBlue","SlateBlue","SlateGray","SlateGrey","Snow","SpringGreen","SteelBlue","Tan","Teal","Thistle","Tomato","Turquoise","Violet","Wheat","White","WhiteSmoke","Yellow","YellowGreen"];
const CSS_COLORS = cap_css_colors.map(color => {
//I need to change all color names to lower case, because comparison between words will be case sensitive
return color.toLowerCase()
})
//once speech recognition determines it has a "result", grab the texts of that result, join all of them, and add to paragraph
recognition.addEventListener("result", e => {
const transcript = Array.from(e.results)
.map(result => result[0])
.map(result => result.transcript)
.join("")
p.innerText = transcript
//once speech recognition determines it has a final result, create a new paragraph and append it to the words-container
//this way every time you add a new p to hold your speech-to-text every time you're finished with the previous results
if (e.results[0].isFinal) {
p = document.createElement("p")
words.appendChild(p)
}
//for each result, map through all color names and check if current result (transcript) contains that color
//i.e. see if a person said any color name you know
CSS_COLORS.forEach(color => {
//if find a match, change your background color to that color
if (transcript.includes(color)) {
body.style.backgroundColor = color;
}
})
})
//add your functionality to the start and stop buttons
function startRecording() {
recognition.start();
recognition.addEventListener("end", recognition.start)
document.getElementById("stop").addEventListener("click", stopRecording)
}
function stopRecording() {
console.log("okay I'll stop")
recognition.removeEventListener("end", recognition.start)
recognition.stop();
}
ul {
list-style: none;
padding: 0;
}
p {
color: #444;
}
button:focus {
outline: 0;
}
.container {
max-width: 700px;
margin: 0 auto;
padding: 100px 50px;
text-align: center;
}
.container h1 {
margin-bottom: 20px;
}
.page-description {
font-size: 1.1rem;
margin: 0 auto;
}
.tz-link {
font-size: 1em;
color: #1da7da;
text-decoration: none;
}
.no-browser-support {
display: none;
font-size: 1.2rem;
color: #e64427;
margin-top: 35px;
}
.app {
margin: 40px auto;
}
#note-textarea {
margin: 20px 0;
}
#recording-instructions {
margin: 15px auto 60px;
}
#notes {
padding-top: 20px;
}
.note .header {
font-size: 0.9em;
color: #888;
margin-bottom: 10px;
}
.note .delete-note,
.note .listen-note {
text-decoration: none;
margin-left: 15px;
}
.note .content {
margin-bottom: 40px;
}
#media (max-width: 768px) {
.container {
padding: 50px 25px;
}
button {
margin-bottom: 10px;
}
}
/* -- Demo ads -- */
#media (max-width: 1200px) {
#bsaHolder{ display:none;}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>MJ BOT </title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="{{ url_for('static', filename='styles/style.css') }}">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<!-- partial:index.partial.html -->
<section class="msger">
<header class="msger-header">
<div class="msger-header-title">
<i class=""></i> MJ Chatbot <i class=""></i>
</div>
</header>
<main class="msger-chat">
<div class="msg left-msg">
<div class="msg-img" style="background-image: url(https://image.flaticon.com/icons/svg/145/145867.svg)"></div>
<div class="msg-bubble">
<div class="msg-info">
<div class="msg-info-name"></div>
</div>
<div class="msg-text">
<p> {{ questionAsked }} </p>
</div>
</div>
</div>
</main>
<article>
<main class="msger-chat">
<div class="msg right-msg">
<div class="msg-img" style="background-image: url(https://image.flaticon.com/icons/svg/327/327779.svg)"></div>
<div class="msg-bubble">
<div class="msg-info">
<div class="msg-info-name"></div>
</div>
<div class="msg-text">
<p> {{ response }}</p>
</div>
</div>
</div>
</article>
</main>
<form id="output" class="msger-inputarea" action="signup" method="post">
<input id="output" class="msger-input" type="text" name="question"></input>
<input id='play' class="msger-send-btn" type="submit" value="Submit Message !" > </input>
<input type="button" value="Speak" onclick="runSpeechRecognition()"></input>
<button id='stop'></button>
</form>
<button id=play style="font-size:24px">Listen <i class="fas fa-file-audio"></i></button>
Send Query to Agent !
</section>
<script >onload = function() {
if ('speechSynthesis' in window) with(speechSynthesis) {
var playEle = document.querySelector('#play');
var pauseEle = document.querySelector('#pause');
var stopEle = document.querySelector('#stop');
var flag = false;
playEle.addEventListener('click', onClickPlay);
pauseEle.addEventListener('click', onClickPause);
stopEle.addEventListener('click', onClickStop);
function onClickPlay() {
if(!flag){
flag = true;
utterance = new SpeechSynthesisUtterance(document.querySelector('article').textContent);
utterance.voice = getVoices()[0];
utterance.onend = function(){
flag = false; playEle.className = pauseEle.className = ''; stopEle.className = 'stopped';
};
playEle.className = 'played';
stopEle.className = '';
speak(utterance);
}
if (paused) { /* unpause/resume narration */
playEle.className = 'played';
pauseEle.className = '';
resume();
}
}
function onClickPause() {
if(speaking && !paused){ /* pause narration */
pauseEle.className = 'paused';
playEle.className = '';
pause();
}
}
function onClickStop() {
if(speaking){ /* stop narration */
/* for safari */
stopEle.className = 'stopped';
playEle.className = pauseEle.className = '';
flag = false;
cancel();
}
}
}
else { /* speech synthesis not supported */
msg = document.createElement('h5');
msg.textContent = "Detected no support for Speech Synthesis";
msg.style.textAlign = 'center';
msg.style.backgroundColor = 'red';
msg.style.color = 'white';
msg.style.marginTop = msg.style.marginBottom = 0;
document.body.insertBefore(msg, document.querySelector('div'));
}
}
</script>
<script>
/* JS comes here */
function runSpeechRecognition() {
// get output div reference
var output = document.getElementById("output");
// get action element reference
var action = document.getElementById("help");
// new speech recognition object
var SpeechRecognition = SpeechRecognition || webkitSpeechRecognition;
var recognition = new SpeechRecognition();
// This runs when the speech recognition service starts
recognition.onstart = function() {
action.innerHTML = "<small>listening, please speak...</small>";
};
recognition.onspeechend = function() {
action.innerHTML = "<small>stopped listening, hope you are done...</small>";
recognition.stop();
}
// This runs when the speech recognition service returns result
recognition.onresult = function(event) {
var transcript = event.results[0][0].transcript;
var confidence = event.results[0][0].confidence;
output.innerHTML = "<b></b> " + transcript + "<br/> <b></b> " ;
output.classList.remove("hide");
};
// start recognition
recognition.start();
}
</script>
<!-- partial -->
<script src='https://use.fontawesome.com/releases/v5.0.13/js/all.js'></script>
</body>
</html>

recognition.onend = (event) => {
//insert your code to display button here
}

Related

Getting value using Xpath from web page but cannot find the value

I write some python code and want to use xpath to read a value from webpage "http://www.aastocks.com/en/stocks/quote/detail-quote.aspx?symbol=00371", but it shows "IndexError: list index out of range". After I check the page.content, I cannot find the value of field "P/B Ratio" in the content. Does anyone know how to get the "P/B Ratio" value? Thanks!
My code as below:
```
#TestXPath.py
from lxml import html
import requests
import threading
URL = 'http://www.aastocks.com/en/stocks/quote/detail-quote.aspx?symbol=00371'
XPATH = '//*[#id="tbPBRatio"]/div[2]'
def getValue():
page = requests.get(URL)
print (page.content)
tree = html.fromstring(page.content)
value = tree.xpath(XPATH)
print('value={0!s}'.format(value[0]))
if __name__ == "__main__":
getValue()
```
Captured an image for reference
The part of the output of page.content is here:
<script type="text/javascript">_gaq.push(['a2._setAccount', 'UA-129684769-1']); _gaq.push(['a2._trackPageview']);</script><meta property="fb:app_id" content="280135662816939" /><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta name="keywords" content="HK Stocks, Quote, Detailed Quote, Fund, Warrants, CBBCs, Call, Put, News, Technical Chart, Blocked Trade, HK Indices, CN Indices" /><meta name="description" content="HK Stock Detail Quote provides information including Free HK-share Real-time Quote, HK-share Chart, HK-share Historical Performance, HK-share Technical Chart, Related A-share Quote, HK-share PE Ratio, HK-share Yield, HK-share Earnings Per Share, HK-share Dividend Payout, HK-share PB Ratio, HK-share Moneyflow, HK-share NAV, A + H + ADR, HK-share News, HK-share related warrants, HK-share related CBBC" /><link href="/en/favicon.ico?v=1.2.0" rel="icon" /><link href="/en/favicon.ico?v=1.2.0" rel="shortcut icon" type="image/x-icon" /><title>
Detail Quote
</title></head> <body id="stock" class="eng resizeable"> <div id="divFSMask" style="position:absolute; filter:alpha(opacity=80); zoom:1; opacity:0.8; top:0px; left:0px; width:100%; background:black; height:100%; z-index:100; display:none"></div> <div id="CrazyiPadPopup"><script type='text/javascript'>OA_show('Crazy_iPad_popup');</script></div> <div class="div980"></div> <script type="text/javascript">
is980Mode = $(".div980").is(":visible");
curWidth980Mode = is980Mode;
$(window).resize(function () {
is980Mode = $(".div980").is(":visible");
});
</script> <form method="post" action="detail-quote.aspx?symbol=00371" id="mainForm"> <div class="aspNetHidden"> <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="Z9MEfrcXHWZHLrGNyFqv+7SMlO6SiAMa7mXGDMSld4HEXzCSEoFrPdihSEdNmeLlfp2baKFj4zokP6U4qIkQHqDHMWXV/jmGUoqV4SMh5eVDRMAt9R/uTpjoNRENJ1gJvpq1WfDuqhOk4bgLGuMIkVrrNVEeulw+uPlpfk6+IKGUlf+oGGm8+uEqAJVbXuwF7hwKJVAhb+gPc1EHEzmjBIzKhwYZjVkVemPXQREWHgctAZfQ3kZ+m/+hQp5V6+DW/SNkXGj9RrdVnH8CGZW3RXbgouS/d8cUOOFkzBEApi5R5S+TDmf5xuXNPFuJk256LtjbwXKQUVvM14wt+6GuXYyBpKnaRmwypcbUrmbtCd0dN0Y0" /> </div> <div class="container"> </div> <div class="container" style="position:relative; z-index:3;" id="divMasterHead"> <div id="topPanel"> <div class="blue-line"> <div class="container"> <div class="float_l AASTOCKSHome" style="position:relative; top:10px; "> <div style="height: 20px; line-height: 20px; padding-left:0px;" class="float_l icon_marginright" onclick="setHomepage()"><div class="header_icon_map icon_sethome jshoverwithclass" hover="hoveron"></div></div> <div style="height: 20px; line-height: 20px; padding-left:0px;" class="float_l icon_marginright"><div class="header_icon_map icon_contact jshoverwithclass" hover="hoveron"></div></div> <div style="width:1px; height: 20px; line-height: 20px; background-color:#006e97;" class="float_l icon_marginright"></div> <div style="height: 20px; line-height: 20px;" class="float_l icon_marginright lang-btn"><a id="bLang1" class="jshoverwithclass tc" hover="hoveron" href="javascript:toLang('tc')">繁</a></div> <div style="height: 20px; line-height: 20px;" class="float_l icon_marginright lang-btn"><a id="bLang2" class="jshoverwithclass sc" hover="hoveron" href="javascript:toLang('sc')">简</a></div> <div style="width:1px; height: 20px; line-height: 20px; background-color:#006e97;" class="float_l icon_marginright"></div> <div style="height: 20px; line-height: 20px; padding-left:0px;" class="float_l icon_marginright"><div class="header_icon_map icon_facebook jshoverwithclass" hover="hoveron"></div></div> <div style="width:1px; height: 20px; line-height: 20px; background-color:#006e97;" class="float_l icon_marginright"></div> <div style="height: 20px; line-height: 20px;" class="float_l icon_marginright"> <div class="topslidebox"> <div style="position:absolute; width:100%; height:100%; z-index:1;"></div> <table><tr><td><div class="header_icon_map icon_topiphone"></div></td><td style="padding-left:9px;"><span style="white-space:nowrap;">Market+ (iPhone)</span></td></tr></table> </div> </div> <div style="height: 20px; line-height: 20px;" class="float_l icon_marginright"> <div class="topslidebox"> <div style="position:absolute; width:100%; height:100%; z-index:1;"></div> <table><tr><td><div class="header_icon_map icon_topandroid"></div></td><td style="padding-left:9px;"><span style="white-space:nowrap;">Market+ (Android)</span></td></tr></table> </div> </div> <div style="height: 20px; line-height: 20px;" class="float_l"> <div class="topslidebox"> <div style="position:absolute; width:100%; height:100%; z-index:1;"></div> <table><tr><td><div class="header_icon_map icon_topmobile"></div></td><td style="padding-left:13px;"><span style="white-space:nowrap;">Mobile Site</span></td></tr></table> </div> </div> </div> <div class="tp-box float_r usq " onclick="window.location.href='/en/usq/default.aspx'"> <div class="bold jshoverwithclass" hover="hoveron">US STOCKS</div> </div> <div class="tp-box float_r " onclick="window.location.href='/en/funds/default.aspx'"> <div class="bold jshoverwithclass" hover="hoveron">FUNDS</div> </div> <div class="tp-box float_r " onclick="window.location.href='/en/forex/default.aspx'"> <div class="bold jshoverwithclass" hover="hoveron">FOREX</div> </div> <div class="tp-box float_r " onclick="window.location.href='/en/cnhk/default.aspx'"> <div class="bold jshoverwithclass" hover="hoveron">SH/SZ-HK</div> </div> <div class="tp-box float_r sel" onclick="window.location.href='/en/'"> <div class="bold " hover="hoveron">HK STOCKS</div> </div> <div class="tp-box float_r aabest" onclick="gotoAABEST('https://www.aabest.com/en/default.aspx');"> <div class="float_l header_icon_map icon_aabest"></div> </div> <div class="clear"></div> </div> </div> <script type="text/javascript">
/* Forex Function */
function forexquote() {
quote($("#txtCurSymbol").val());
}
function forexchartquote() {
fxchart($("#txtCurSymbol").val());
}
function fxchart(value) {
window.location.href = "/en/forex/quote/chart.aspx?symbol=" + value;
}
function quote(value) {
if (value == "UDI") {
window.location.href = "/en/forex/quote/dollarindex.aspx";
} else {
window.location.href = "/en/forex/quote/quote.aspx?symbol=" + value;
}
}
/* End of Forex Function */
/* US Function */
function uschart(value) {
window.location.href = "/en/usq/quote/chart.aspx?symbol=" + encodeURIComponent(value);
}
function usquotewvalue() {
usquote($("#txtUSQuote").val());
}
function usquotewvalue2() {
usquote($("#txtCurSymbol").val());
}
function uschartwvalue() {
uschart($("#txtUSQuote").val());
}
function uschartwvalue2() {
uschart($("#txtCurSymbol").val());
}
function usquote(value) {
window.location.href = "/en/usq/quote/quote.aspx?symbol=" + encodeURIComponent(value);
}
// End of US Function
// Stock Function
function hkquotewvalue() {
var symbol = $("#txtHKQuote").val();
symbol = ('Code/Name' == symbol ? '00001' : symbol);
hkquote(symbol);
}
function hkchartwvalue() {
var symbol = $("#txtHKQuote").val();
symbol = ('Code/Name' == symbol ? '00001' : symbol);
hkchart(symbol);
}
function hkquote(value) {
window.location.href = "/en/stocks/quote/quick-quote.aspx?symbol=" + encodeURIComponent(value);
}
function hkchart(value) {
window.location.href = '/en/stocks/quote/detailchart.aspx?symbol=' + encodeURIComponent(value);
}
function hknewswvalue(value) {
var symbol = value;
symbol = ('Code/Name' == symbol ? '00001' : symbol);
window.location.href = '/en/stocks/analysis/stock-aafn/{0}/{1}/{2}/{3}'.replace("{0}", symbol).replace("{1}", "0").replace("{2}", "all").replace("{3}", "1");
}
function hknews() {
var symbol = $("#txtHKQuote").val();
symbol = ('Code/Name' == symbol ? '00001' : symbol);
window.location.href = '/en/stocks/analysis/stock-aafn/{0}/{1}/{2}/{3}'.replace("{0}", symbol).replace("{1}", "0").replace("{2}", "all").replace("{3}", "1");
}
function hknews2(value) {
window.location.href = '/en/stocks/analysis/stock-aafn/{0}/{1}/{2}/{3}'.replace("{0}", value).replace("{1}", "0").replace("{2}", "all").replace("{3}", "1");
}
/* End of Stock Function */
/* CN Quote Function */
function cnquote(value) {
if (GetDefaultQuoteSetting() == "QQ")
window.location.href = "/en/cnhk/quote/quick-quote.aspx?shsymbol=" + encodeURIComponent(value);
else
window.location.href = "/en/cnhk/quote/detail-quote.aspx?shsymbol=" + encodeURIComponent(value);
}
function cnchart(value) {
window.location.href = "/en/cnhk/analysis/tech-chart.aspx?shsymbol=" + encodeURIComponent(value);
}
function cnnews(value) {
window.location.href = '/en/cnhk/quote/stock-news/{0}/{1}/{2}/{3}/'.replace("{0}", encodeURIComponent(value)).replace("{1}", "0").replace("{2}", "all").replace("{3}", "1");
}
function cnquotewvalue() {
var symbol = $("#txtCNQuote").val();
symbol = ("Code/Name" == symbol ? '600000' : symbol);
cnquote(symbol);
}
function cnchartwvalue() {
var symbol = $("#txtCNQuote").val();
symbol = ('Code/Name' == symbol ? '600000' : symbol);
cnchart(symbol);
}
function cnnewswvalue() {
var symbol = $("#txtCNQuote").val();
symbol = ('Code/Name' == symbol ? '600000' : symbol);
window.location.href = '/en/cnhk/quote/stock-news/{0}/{1}/{2}/{3}/'.replace("{0}", symbol).replace("{1}", "0").replace("{2}", "all").replace("{3}", "1");
}
function shhkquote(s, type, passInMarket) {
type = type == undefined ? 'quote' : type;
var market = 'SH';
if (passInMarket == 'US') {
market = 'US';
s = ('Code/Name' == s ? 'AAPL' : s);
} else {
if (s.length == 6) {
market = 'SH';
} else {
s = ('Code/Name' == s ? '00001' : s);
s = '00000' + s;
s = s.substr(s.length - 5, 5)
market = 'HK';
}
}
switch (type) {
case 'quote':
$("#mainForm").submit(function (e) { return false; });
if (market == 'SH')
cnquote(s);
else if (market == 'US')
usquote(s);
else {
SetLTP(fullCookiesDomain);
hkquote(s);
}
break;
case 'chart':
$("#mainForm").submit(function (e) { return false; });
if (market == 'SH')
cnchart(s);
else if (market == 'US')
uschart(s);
else
hkchart(s);
break;
case 'news':
$("#mainForm").submit(function (e) { return false; });
if (market == 'SH')
cnnews(s);
else
hknewswvalue(s);
break;
}
return false;
}
/* End of CN Quote Function */
/* DZH Function */
function dzhquotewvalue() {
dzhquote($("#txtCurSymbol").val());
}
function dzhquote(value) {
window.location.href = "/en/dzh/quote/quote.aspx?symbol=" + value;
}
function dzhchart(value) {
window.location.href = "/en/dzh/quote/chart.aspx?symbol=" + value;
}
function dzhnews(value) {
window.location.href = "/en/dzh/quote/news.aspx?symbol=" + value;
}
/* End of DZH Function */
function toLang(v) {
var pathname = window.location.pathname;
var search = window.location.search;
var hash = window.location.hash;
if (pathname != undefined && pathname != null) {
pathname = pathname.toLowerCase();
}
if (pathname.indexOf("/tc/") >= 0) {
$.cookie("mLang", "TC", { expires: GetExpiryDate(), path: '/', domain: subCookiesDomain });
window.location.href = pathname.replace("/tc/", "/" + v + "/") + search + hash;
} else if (pathname.indexOf("/sc/") >= 0) {
$.cookie("mLang", "SC", { expires: GetExpiryDate(), path: '/', domain: subCookiesDomain });
window.location.href = pathname.replace("/sc/", "/" + v + "/") + search + hash;
} else if (pathname.indexOf("/en/") >= 0) {
$.cookie("mLang", "EN", { expires: GetExpiryDate(), path: '/', domain: subCookiesDomain });
window.location.href = pathname.replace("/en/", "/" + v + "/") + search + hash;
} else {
window.location.href = "/" + v + pathname + search + hash;
}
}
</script>

Polymer 3 animation not working for shadow dom elements

I'm attempting to update the Polymer 2 grain-masonry project to use Polymer 3 and I'm 90% there, but I cannot get the animation for adding new elements to work correctly. The artifacts are added through the shadow dom and it seems that even though the class name is added, the animation doesnt work.
I've tried changing how the keyframes are added to the javascript file as well as putting the animate classes on the ":host" as opposed to ":host ::slotted"
index.html
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes">
<title>masonry-layout demo</title>
<script src="../node_modules/#webcomponents/webcomponentsjs/webcomponents-loader.js"></script>
<script type="module">
import '#polymer/iron-demo-helpers/demo-pages-shared-styles';
import '#polymer/iron-demo-helpers/demo-snippet';
</script>
<script>
function addBelow() {
let newArticle = document.createElement('article');
newArticle.innerHTML = 'added below';
document.getElementById('masonry').appendChild(newArticle);
}
function addAbove() {
let newArticle = document.createElement('article');
let masonry = document.getElementById('masonry');
newArticle.innerHTML = 'added above';
document.getElementById('masonry').prependChild(newArticle);
}
</script>
<script type="module" src="../masonry-layout.js"></script>
<custom-style>
<style is="custom-style" include="demo-pages-shared-styles">
</style>
<style>
article {
background: #36abcc;
width: 29%;
height: 200px;
margin: 2%;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
}
grain-masonry {
background: #ccc;
}
</style>
</custom-style>
</head>
<body>
<div class="vertical-section-container centered">
<h3>Basic masonry-layout demo</h3>
<button onclick="addBelow();">add below</button>
<button onclick="addAbove();">add above</button>
<demo-snippet>
<template>
<masonry-layout id="masonry">
<article>
Power
</article>
<article style="height: 100px;">
To
</article>
<article style="height: 190px;">
The
</article>
<article style="height: 310px;">
People
</article>
<article>
Power
</article>
<article style="height: 140px;">
To
</article>
<article style="height: 210px;">
The
</article>
<article style="height: 230px;">
People
</article>
</masonry-layout>
</template>
</demo-snippet>
</div>
</body>
</html>
masonry-layout.js
import {html, PolymerElement} from '#polymer/polymer/polymer-element.js';
import {afterNextRender} from '#polymer/polymer/lib/utils/render-status.js';
import { FlattenedNodesObserver } from '#polymer/polymer/lib/utils/flattened-nodes-observer.js';
import './masonry.pkgd.min.js';
/**
* `masonry-layout`
* Polymer 3 wrapper for masonry javascript library
*
* #customElement
* #polymer
* #demo demo/index.html
*/
class MasonryLayout extends PolymerElement {
static get is() {
return 'masonry-layout'
}
static get properties() {
return {
itemSelector: {
type: String,
reflectToAttribute: true,
value: 'article'
},
transitionDuration: {
type: Number,
reflectToAttribute: true,
value: 0
}
};
}
static get template() {
return html`
<style>
#keyframes containerMasonryMoveToOrigin {
from {
opacity: 0;
}
to { transform: translateY(0); opacity: 1; }
}
:host {
display: block;
width: 100%;
}
:host .masonry-layout-animate-move-up) {
transform: translateY(200px);
opacity: 0;
animation: containerMasonryMoveToOrigin 5s ease forwards;
}
.masonry-layout-animate-move-down) {
transform: translateY(-200px);
opacity: 0;
animation: containerMasonryMoveToOrigin 0.65s ease forwards;
}
</style>
<slot id="slot"></slot>
`;
}
init() {
this.raw = new Masonry(this, {
itemSelector: this.itemSelector,
transitionDuration: this.transitionDuration,
initLayout: false
});
afterNextRender(this, function () {
this.layout();
});
}
connectedCallback() {
super.connectedCallback();
this.init();
this._loadObserver = function (event) {
let target = event.target;
if (target.tagName === 'IMG') {
this.layout();
}
}.bind(this);
this.addEventListener('load', this._loadObserver, true);
this.toggleSlotObsever = false;
this._slotObserver = new FlattenedNodesObserver(this.$.slot, (info) => {
if (this.toggleSlotObsever) {
let addedElements = info.addedNodes.filter((node) => {
return (node.nodeType === Node.ELEMENT_NODE && node.nodeName === this.itemSelector.toUpperCase())
});
let removedElements = info.removedNodes.filter((node) => {
return (node.nodeType === Node.ELEMENT_NODE && node.nodeName === this.itemSelector.toUpperCase())
});
if (addedElements.length > 0 || removedElements.length > 0) {
this.reInit();
}
}
this.toggleSlotObsever = true;
});
}
disconnectedCallback() {
this._slotObserver.disconnect();
this.removeEventListener('load', this._loadObserver);
}
layout() {
this.raw.layout();
}
reInit() {
this.raw.destroy();
this.init();
}
appendChild(element) {
this.toggleSlotObsever = false;
element.classList.add('masonry-layout-animate-move-up');
element.addEventListener('animationend', function (event) {
//event.target.classList.remove('masonry-layout-animate-move-up');
});
super.appendChild(element);
this.raw.addItems(element);
afterNextRender(this, function () {
this.layout();
this.toggleSlotObsever = true;
});
}
appendChildren(elements) {
for (let element of elements) {
this.appendChild(element);
}
}
prependChild(element) {
this.insertBefore(element, this.children[0]);
}
prependChildren(elements) {
for (let element of elements) {
this.prependChild(element);
}
}
insertBefore(element, before) {
if (element.nodeName === '#document-fragment') {
element = element.querySelector(this.itemSelector);
}
this.toggleSlotObsever = false;
element.classList.add('masonry-layout-animate-move-down');
element.addEventListener('animationend', function (event) {
//event.target.classList.remove('masonry-layout-animate-move-down');
});
super.insertBefore(element, before);
this.raw.prepended(element);
afterNextRender(this, function () {
this.layout();
this.toggleSlotObsever = true;
});
}
}
window.customElements.define('masonry-layout', MasonryLayout);

How to make a typing effect in vuejs

hello j try to make a Typing effect on vuejs here is my code.
i'm trying to call setTimeout but it's the effect i want.
template:
<template>
<div>
<span class="back" #click="goToMenu"> 戻る</span>
<div class="img-container" >
<img v-bind:src="getCharacter.headImage" class="responsive-image">
<div class="conversation">
<span class="name">{{getCharacter.name}}</span>
<p class="text typewriter-text"> {{outputText}}</p>
</div>
<button>Start</button>
</div>
<Counter ></Counter>
</div>
SCRIPT :
export default {
name: "Practice",
methods: {
outText() {
if (this.inc < this.text1.length) {
this.outputText += this.text1.charAt(this.inc);
this.inc ++;
setTimeout(this.outText() , 100000)
}
}
},
mounted() {
this.outText()
},
data() {
return {
text1 :'こんにちは。あなたの日本語聞かせてほしいな!まずは練習!',
outputText : '',
inc:0
}
}
}
css :
<style scoped>
.text {
background-color: #ababab;
padding: 4%;
border-radius: 0 14px 14px 14px;
margin: 0;
width: 85vw;
height: 10vh;
}
You should not be calling the outText method when you pass it as an argument to setTimeout, doing so will call the method immediately, instead you want to pass the method to setTimeout so it can be called later after the timeout has elapsed.
Incorrect:
setTimeout(this.outText(), 100000)
Correct:
setTimeout(this.outText, 100000)
Also 100000ms (100s) is too long of a delay to notice anything.

Tooltips with rich HTML content does not help in creating desired UI?

I have an XYChart with data object like
chart.data = [{
"Area": "Korangi",
"AreaNumber": 120,
"SubArea": [{
"SubAreaName": "Korangi-1",
"SubAreaNumber": 60
}, {
"SubAreaName": "Korangi-2",
"SubAreaNumber": 60
}
]
}];
and a series tooltipHTML adapter as
series.tooltipHTML = `<center><strong> {Area}:</strong>
<strong> {AreaNumber}%</strong></center>
<hr />`;
series.adapter.add("tooltipHTML",
function (html, target) {
if (
target.tooltipDataItem.dataContext &&
target.tooltipDataItem.dataContext.SubArea &&
target.tooltipDataItem.dataContext.SubArea.length
) {
var nameTalClientsNumberCells = "";
Cells = "";
target.tooltipDataItem.dataContext.SubArea.forEach(part => {
if (part.SubAreaName != null) {
nameTalClientsNumberCells +=
`<tr><td><strong>${part.SubAreaName}</strong>:&nbsp ${part
.SubAreaNumber}%</td></tr>`;
}
//TalClientsNumberCells += `<td>${part.SubAreaNumber}</td>`;
});
html += `<table>
${nameTalClientsNumberCells}
</table>`;
}
return html;
});
For I have tried bootstrap classes but non of them works in tooltipHTML.
what I want is like this
but I tried so far is like this
Please help or refer if there is another way of adding really rich HTML in tooltip
A link to the codepen
What you're doing is fine. I just didn't see you used any bootstrap4 css class. You can achieve what you want with either bootstrap4 built-in classes, or your own custom styles.
//I don't need to set tooltipHTML since I have the adapter hook up to return
// custom HTML anyway
/*
series.tooltipHTML = `<center><strong> {Area}:</strong>
<strong> {AreaNumber}%</strong></center>
<hr />`;
*/
series.adapter.add("tooltipHTML", function (html, target) {
let data = target.tooltipDataItem.dataContext;
if (data) {
let html = `
<div class="custom-tooltip-container">
<div class="col-left">
<h5>${data.Area}</h5>
<ul class="list-unstyled">
${data.SubArea.map(part =>
`
<li class="part">
<span class="name">${part.SubAreaName}</span>
<span class="area">${part.SubAreaNumber}%</span>
</li>
`
).join('')}
</ul>
</div>
<div class='col-right'>
<span class="badge badge-pill badge-success">${data.AreaNumber}%</span>
</div>
</div>
`;
return html;
}
return '';
});
And here is the custom styles:
#chart {
height: 31rem;
}
.custom-tooltip-container {
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
min-width: 13rem;
}
.custom-tooltip-container .col-left {
width: 70%;
}
.custom-tooltip-container .col-right {
width: 30%;
text-align: center;
}
.custom-tooltip-container .col-right .badge {
font-size: 1.1rem;
}
.custom-tooltip-container .part {
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
}
Again, you can do whatever you want. Here as demo I just quickly put things together.
demo: https://jsfiddle.net/davidliang2008/6g4u2qw8/61/

Should I use ReactDOMServer.renderToString() or any other way to render a react component to a string?

I am extacting a tiny component from a bigger map component on an app using Leafet and it seems impossible to include the JSX into the html string of Leafet DivIcon.
bigger map component render part:
render () {
const {tobject, strings} = this.props
let circle = classes.redCircle
if (tobject.lastPoint.activeEvents.ignition) {
circle = classes.greenCircle
}
const icon = new window. L. DivIcon({
html:
` <div class= ${classes.tobjecticon}><span class= ${classes.tobjecticontext}><div class= ${circle}></div></span></div> `
})
newly extacted component StatusCircle.js:
import React from 'react'
import classes from './StatusCircle.scss'
export const StatusCircle = ({ status}) => {
let circle = classes.redCircle
if (status) {
circle = classes.greenCircle
}
return (
<div className={circle} ></div>
)
}
export default StatusCircle
My question seems similar to this one. I've tried renderToString() of StatusCircle, but using ReactDOM (deprecated there) and not ReactDOMServer and it didn't work saying there is no such function. Is it okay to use ReactDOMServer.renderToString() or .renderToStaticMarkup() to achieve this or is it better to leave unchanged without extraction?
It is OK to leave inner html inside of parent component. But here is the way to render it to markup without using ReactDOMServer. It's a bit tricky way =)
class Inner extends React.Component {
render () {
return (
<span {...this.props}>Inner Element</span>
)
}
}
class Outer extends React.Component {
render () {
const span = document.createElement('span');
ReactDOM.render(<Inner className="red" />, span);
//target html
console.log(span.innerHTML);
return (
<div>
You can use this html
<pre>
{span.innerHTML}
</pre>
</div>
)
}
}
ReactDOM.render(<Outer />, document.querySelector('#root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
I don't want to add more imports to the project and depend on them, but using ReactDOM.Render instide render () is giving: "Warning: _renderNewRootComponent(): Render methods should be a pure function of props and state; triggering nested component updates from render is not allowed. If necessary, trigger nested updates in componentDidUpdate. Check the render method of StatusCircle". While ReactDOMServer.renderToStaticMarkup() works flawlessly like this:
class App extends React.Component{
render() {
let greenCircle = ReactDOMServer.renderToStaticMarkup(<StatusCircle status={true} />)
console.log(greenCircle)
let redCircle = ReactDOMServer.renderToStaticMarkup(<StatusCircle status={false} />)
console.log(redCircle)
return (
<div>
<StatusCircle status={true} />
<StatusCircle status={false} />
</div>
)
}
}
const StatusCircle = ({status}) => {
let circle = "redCircle"
if (status) {
circle = "greenCircle"
}
return <div className={circle}></div>
}
ReactDOM.render(<App />, document.querySelector('#root'))
.redCircle {
background-color: red;
border-radius: 50px;
width: 10px;
height: 10px;
margin: 10px;
}
.greenCircle {
background-color: green;
border-radius: 50px;
width: 10px;
height: 10px;
margin: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom-server.min.js"></script>
<div id="root"></div>

Resources