Why is my node.js etcd client getting html - node.js

My etcd instance is running locally and I can perform get and set using the cli
// set
etcdctl set /services/myservice "{\"hostname\": \"127.0.0.1\", \"port\": 3000}"
//get
etcdctl get services/myservice
// results in -> {"hostname": "127.0.0.1", "port": 3000}
but when I use the node-etc module
var Etcd = require('node-etcd');
var etcd = new Etcd(['http://localhost:2379', 'http://localhost:4001']);
etc.get('services/myservice', { wait: true}, function (err, value){
console.log(err, value);
});
I get value is HTML (see below) instead of the same result as the cli. This was working a few weeks ago so I am not sure if I have
I also find that when I don't include hosts and just use new Etcd() I get an internal HTML page with references to proxy issues: "The requested website is blocked by [insert company name] Proxy due to potential malicious activity or other security reasons."
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" data-adblockkey="MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKrfIMFkSaoTSqKmC+BrghK0CpDHc0MuVzmMHin8LIORhpXbped+iYhSnZurWnEO0zcKcVIrzp026LVc5pMB9bUCAwEAAQ==_mHzvOc3GBNo9sxVki+5Fe+E9GsbiT2+mBIEtU+yAIW6jw6Uds6VUD5RSkqMfuUSrcw4AYCrFOWaaWSRGDzU8pw==">
<head>
<script type="text/javascript">
var abp;
</script>
<script type="text/javascript" src="http://www.http.com/px.js?ch=1"></script>
<script type="text/javascript" src="http://www.http.com/px.js?ch=2"></script>
<script type="text/javascript">
function handleABPDetect() {
try {
var imglog = document.createElement("img");
imglog.src = "http://www.http.com/rg-logabpstatus.php?a=WVpqOEdZZldDTWo4VWF0M0pNa1pBek0xQnE1WVlqR2VaQ0Frd0V4TUxmcDAvOFN2WnhHYS8weFFEeTZTRHlleTM0UFk3UDhzemxqSWFRdXlFdXpIUGc9PQ==&b=" + abp;
document.body.appendChild(imglog);
} catch (err) {}
}
try {
window.onload = handleABPDetect();
} catch (err) {}
</script>
<title>http.com</title>
<meta http-equiv="Content-Type" content="text/html; charset=">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable = no">
<style type="text/css">
* {
margin: 0;
padding: 0
}
a {
text-decoration: none;
outline: none
}
a:hover {
text-indent: 0;
cursor: pointer
}
.clearfix:after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0
}
* html .clearfix {
zoom: 1
}
*:first-child+html .clearfix {
zoom: 1
}
body {
font-family: Arial, Helvetica, sans-serif;
background: url(http://c.rmgserving.com/rmgpsc/7867/body-bg.gif) 0 0 repeat #000
}
/*.arrows{background:url(http://b.rmgserving.com/rmgpsc/7867/arrows.jpg)}*/
#main-wrap {
background: url(http://a.rmgserving.com/rmgpsc/7867/header-bg.jpg) top center no-repeat;
background-size: 100% 100px
}
.container {
width: 960px;
margin: 0 auto
}
.header {
height: 100px
}
/*commented for new design */
/*.leftblk{float:left; overflow:hidden}
.leftblk img{float: left; margin-top: 23px; padding-right: 15px;}*/
/*.domain_name{float:left; line-height:100px; font-size:26px; font-weight:normal; color:#fff}*/
.searchbox {
float: right;
width: 410px;
* width: 420px;
_width: 420px;
height: 28px !important;
padding-top: 2px;
margin-top: 35px;
/*padding-left:33px;background:url(http://d.rmgserving.com/rmgpsc/7868/srch-bg-caf2.gif) 0 0 no-repeat*/
}
.content {
padding-bottom: 10px;
background: #202020
}
/**RESPOSIVE CHANGES MADE HERE**/
.domain_name {
line-height: normal;
font-size: 26px;
font-weight: normal;
color: #fff;
margin-top: 35px
}
.leftblk {
float: left;
width: 39%;
word-wrap: break-word;
background: url(http://c.rmgserving.com/rmgpsc/7867/logo1.png) no-repeat center left;
padding-left: 70px;
height: 100px;
overflow: hidden;
}
.frt_arr {
float: left;
width: 30%;
height: 425px;
background: url(http://d.rmgserving.com/rmgpsc/7983/frst_arr.jpg);
background-position: 10px 70px;
background-repeat: no-repeat;
background-size: 90%
}
.lst_arr {
float: left;
width: 30%;
height: 425px;
background: url(http://b.rmgserving.com/rmgpsc/7983/last_arr.jpg);
background-position: 0px 70px;
background-repeat: no-repeat;
background-size: 90%
}
.kwd_bloack {
float: left;
width: 40%;
margin-top: 74px
}
/**RESPOSIVE CHANGES END HERE**/
.bottom_bg {
height: 44px;
/*background:#181818; */
margin-top: 34px
}
.bottom_rs {
width: 960px;
height: 44px;
overflow: hidden;
margin: 0 auto;
position: relative
}
#bot_rs {
padding-top: 9px
}
.separator {
position: absolute;
top: 0;
left: 156px;
width: 5px;
height: 44px;
border-left: 2px solid #282828;
background: url(http://a.rmgserving.com/rmgpsc/7867/sep-arw.gif) center center no-repeat
}
.footer-nav {
width: 100%;
height: 74px;
text-align: center;
color: #c0c0c0;
}
.footer-nav a {
font-size: 12px;
line-height: 74px;
color: #c0c0c0;
padding: 0 5px;
text-decoration: underline
}
.footer-nav a:hover {
text-decoration: none
}
.inquire {
text-align: right;
padding-top: 10px;
color: #fff
}
.inquire a {
font-size: 12px;
font-weight: normal;
color: #fff
}
.sale-msg {
background: #fff;
color: #4b4b4b;
text-align: center;
font-size: 14px;
width: 100%;
top: 0;
left: 0
}
.sale-msg a {
text-decoration: none;
color: #079ce9;
font-size: 14px;
}
.sale-msg a:hover,
.bottom_rs ul li a:hover,
.mid_rs ul li a:hover,
.inquire a:hover {
text-decoration: underline
}
#media not all and (min-width: 970px) {
.container {
width: 95%
}
.bottom_bg {
display: none
}
.footer-nav a {
line-height: 45px
}
}
#media not all and (min-width: 840px) {
.frt_arr {
display: none
}
.lst_arr {
display: none
}
.kwd_bloack {
float: none;
width: 95%;
margin: 0 auto;
padding-top: 10px
}
.leftblk {
float: none;
height: 50px;
background-size: 35px;
padding-left: 50px;
width: auto
}
.domain_name {
line-height: normal;
font-size: 20px;
margin-top: 0;
padding-top: 15px
}
.searchbox {
float: none;
margin-top: 10px;
padding-top: 0;
width: auto;
}
}
</style>
<script type="text/javascript" src="http://www.google.com/adsense/domains/caf.js"></script>
</head>
<body onload="" onunload="" onBeforeUnload="">
<noscript>
<meta http-equiv="refresh" content="0;url=http://www.http.com/rg-erdr.php?_rpo=t ntZzFFI&_rdm=9f1NJXf43BJvmfNf4.JvV&p=J1c4gcvmfN9ffFGoFgXoYVa%7C%40%7CbzGzTE%2C5f95zbT%2C5f95Et%7C%40%7CX55g.JvV%7C%40%7C%7C%40%7C%7C%40%7CZzbHzEZHE%7C%40%7CzHZZFTH%7C%40%7CK-%7C%40%7C19c4NW4cGFHzTEtTEGZGzTbT%7C%40%7Ct+nh8llbj%7C%40%7Ct+7zFZKFH&ga=5rKI1sSSBwFmmNY4RDXg%2BB7VS0yzNgnQ9JpHpsLHSsvFu0NyshpFxWu0exObFAo5IdFZQrTZujcZjrXONxp3PxtPV7ezER14zh7kWG69e5lf08niAgSfUKiyBSByBIQgw92X314XjQy5h09a65wi7JIhzrLV0PReUb%2F7SMvquCNLeg70qvVfr7kkYTx9Z4NO&t=gnojs" />
<center>
<p style="padding:1em; font-size:1.5em;">For search results please CLICK HERE.</p>
</center>
</noscript>
<script type="text/javascript" language="javascript">
function __gpup(url, height, width, name) {
sw = window.open(url, name, 'height=' + height + ',width=' + width + ',location=no,toolbar=0,resizable=1,scrollbars=1');
if (window.focus) {
sw.focus()
};
return false;
};
</script>
<script text="text/javascript">
var design = {
'pageOptions': {
'pubId': '',
'resultsPageBaseUrl': '',
'fontFamily': 'arial',
'hl': 'en',
'maxTermLength': 29,
'adtest': 'on',
'clicktrackUrl': '',
'fontFamilyAttribution': 'arial',
'type': 'pageoptions',
'pageLoadedCallback': function(requestAccepted, status) {
document.body.style.visibility = 'visible';
if (!requestAccepted) {}
}
},
'searchboxBlock': {
'container': 'searchbox',
'type': 'searchbox',
'fontSizeSearchInput': 16,
'fontSizeSearchButton': 13,
'widthSearchInput': 215,
'colorSearchButton': '#e2e2e2',
'hideSearchInputBorder': false,
'hideSearchButtonBorder': false
},
'mainrs': {
'container': 'main_rs',
'type': 'relatedsearch',
'colorBackground': 'transparent',
'number': 6,
'fontSizeTitle': 19,
'titleBold': true,
'colorTitleLink': '#079ce9',
'noTitleUnderline': false,
'lineHeightTitle': 30,
'fontFamily': 'arial',
'horizontalAlignment': 'center',
'fontSizeAttribution': 13,
'colorAttribution': '#ababab',
'attributionBold': true,
'attributionUppercase': false,
'attributionSpacingBelow': 36,
'rolloverLinkUnderline': false,
'rolloverLinkColor': '#00c800',
'colorAdSeparator': '#202020'
}
};
</script>
<div id="main-wrap" class="clearfix">
<div class="container clearfix">
<div class="header clearfix">
<div class="leftblk">
<!-- <img src="http://c.rmgserving.com/rmgpsc/7867/logo1.png" /> -->
<h3 class="domain_name">http.com</h3>
</div>
<div class="searchbox clearfix" id="searchbox"></div>
</div>
<div class="content clearfix">
<div class="arrows frt_arr"></div>
<div class="kwd_bloack clearfix" id="main_rs"></div>
<div class="arrows lst_arr"></div>
</div>
</div>
<div class="bottom_bg clearfix">
<div class="bottom_rs clearfix">
<!--<span class="separator"></span>-->
</div>
</div>
<div class="footer-nav">
Privacy Policy </div>
</div>
<script type="text/javascript" language="javascript">
window._debug = false;
window._dumpdata = false;
var _cflp = true;
var pgld = true;
var totRS = -1;
var cntRS = 0;
var _cfstc = false;
var _cfblocker = true;
var _cfrg = true;
var _cfHelp = _cfHelp || {};
_cfHelp.design = design || {};
_cfHelp.servVars = {
"webadfl": "webads.php",
"_clhdl": "http:\/\/www.http.com\/rg-cltrack.php?&gr=%5B%7Crdr_url%7C%5D&gm=1WHI0lwrG0Sxkx4PsD8qyCOUd1dkaI2X1l8SGG1fMSd7bfeWMBF%2FyegsqR%2BZliS%2FkmMLg273bT8VsQ1oofKDtwu2BLulOOE9e9f%2FGbKVB3y9mwzTRLUiokCVqtb5Zk84C2EVcNaF2G3r9Bp3RsH1xfXrZC%2BE8YGoveyKL4ONQKcLbTlODzh%2BgHyFxmaFdMqH&gc=11101851242258318844884&gi=XYb9MaQozttVcq86LfylD8RNPuvlew8QArHjQzucy26g%2BlAY%2F2uHYh%2BA6ff50kcc1PxTBiLUWCU4jHCv3wduaWHfl%2Fk8mkRKtWu8EB0jglLzw7eeSqi3ynxhbG7655Fy%2FLKMke6nBiTt%2FuiCvqlrvF1W%2F0MGzePy07JWvEsPuPqNBujvQaw3gGby3VkjIxfm2atlkRoPbyOyKYholPIgVyyBcIBJQvM3kSCiRXOyaMpxjTprto%2B0LbFQmRT0%2Bv05GchdCqw0KwcBJr1GshmWISk5vXG28qmhuRBFtwmFZTdpEHObgOZuOhjtcRKzp6QcLHJxeH43ucmzlzBBC8rUhA%3D%3D",
"kchst": "http:\/\/www.http.com\/",
"kcpg": "render",
"kcprm": "ga=5rKI1sSSBwFmmNY4RDXg%2BB7VS0yzNgnQ9JpHpsLHSsvFu0NyshpFxWu0exObFAo5IdFZQrTZujcZjrXONxp3PxtPV7ezER14zh7kWG69e5lf08niAgSfUKiyBSByBIQgw92X314XjQy5h09a65wi7JIhzrLV0PReUb%2F7SMvquCNLeg70qvVfr7kkYTx9Z4NO&gqsg=4OVo54jg6Fc8v4dgaRWvLlUoQfiT9l0g4KypdpyKIkp3XttitvahDJPyd8JV8AMP&maxads=0&gerf=NIVtBZ66fMb06L%2FzgSYcSUpDtBcVFLddp21rUKg8Zvs%3D&wait=true",
"jtchdl": "0",
"lkwtkn": null,
"qry": null,
"cntry": "IE",
"prvid": 1566375,
"lgky": "VFJIcUJEQUZtMGQ3dVY0amZaMmFIVi8vL2g2WUVmRkQxNVp6eEJRcSs1WFl3K3cvZFFISS9aN1Y4NE1KamNIUi95TW04Q3p6ek9RejR1N1pRemlJS1hORjIzNEF2Z3d3TGkyUGhGNkJxREdyRDJLNzZoWVMraXd0cFZGK1hiWTY5aGNYRTlmOHlDa3E5bmpLTHRtelJ3PT0%3D",
"_aftrprss": "",
"wclhdl": "http:\/\/www.http.com\/webclk?&gr=%5B%7Crdr_url%7C%5D&gm=N3DjGjxerDa%2B8Ln3%2B884CDaIWdGzXLcE6PGovrvm8cwEqFKj9%2FsSAw13RemOENdu59z53RIAX7qKedB%2BbC7k6lI6gFbOxQR7qkhujpZqsJMhUo0JnsgwBv6eY8R4QxT34RDgzTHG7pSdzqCdYGLMkjkrWeoByyf1I3drNmqLJoXF8CRTdNMoZwb5HxP8G2KL&gc=11101851242258318844501&gi=3asGzSvNXUezIegH6SkVMB9oHMTe%2BRtyB0XjQzqrg%2BegxXIIXBBR%2FNpmg%2FEpOC3SbbpbaUmlcSRdngRk3viiaUqqjkydC5SRcNAQIHAVCSz4CcvOsJgD4kJKepiaVN2MkCXSlbZfRbnV4Lj3QWLNCEpoUpJaD8GoKU2ZiKd%2B2wDKToaj236za8yEZZnAejv7CqvZi7bAnoT7LFHAT4YfVQYDvpwbpObRothY86AABfVVWr%2BDuudu2Z1HgnO7kRUJx945jHKd%2BHgj7szCxsb6xBb7wBlUblacTda5uwQKPLtiF5n7ChXCCJTf%2BYsC%2FDDegcmi71Z8FBC6SLSZ%2FYvsJQ%3D%3D",
"is_webad_enabled": 0,
"loaderimage": "http:\/\/c.rmgserving.com\/rmgisc\/loader.gif",
"_afdad": 1,
"noredir": 0,
"erpub": "oversee11_3ph_adult_xml",
"erch": "372",
"erpubcln": "ca-dp-oversee11_3ph_xml",
"erchcln": "000307",
"ghu": "http:\/\/www.http.com\/rg-erdr.php?_rpo=t ntZzFFI&_rdm=9f1NJXf43BJvmfNf4.JvV&p=J1c4gcvmfN9ffFGoFgXoYVa%7C%40%7CbzGzTE%2C5f95zbT%2C5f95Et%7C%40%7CX55g.JvV%7C%40%7C%7C%40%7C%7C%40%7CZzbHzEZHE%7C%40%7CzHZZFTH%7C%40%7CK-%7C%40%7C19c4NW4cGFHzTEtTEGZGzTbT%7C%40%7Ct+nh8llbj%7C%40%7Ct+7zFZKFH&ga=5rKI1sSSBwFmmNY4RDXg%2BB7VS0yzNgnQ9JpHpsLHSsvFu0NyshpFxWu0exObFAo5IdFZQrTZujcZjrXONxp3PxtPV7ezER14zh7kWG69e5lf08niAgSfUKiyBSByBIQgw92X314XjQy5h09a65wi7JIhzrLV0PReUb%2F7SMvquCNLeg70qvVfr7kkYTx9Z4NO"
};
_cfHelp.newOpts = {
"pageoptions": {
"kw": "http",
"pubId": "dp-oversee32_3ph_xml",
"channel": "012174,test107,test49",
"hl": "",
"adtest": "off",
"resultsPageBaseUrl": "http:\/\/www.http.com\/?ga=5rKI1sSSBwFmmNY4RDXg%2BB7VS0yzNgnQ9JpHpsLHSsvFu0NyshpFxWu0exObFAo5IdFZQrTZujcZjrXONxp3PxtPV7ezER14zh7kWG69e5lf08niAgSfUKiyBSByBIQgw92X314XjQy5h09a65wi7JIhzrLV0PReUb%2F7SMvquCNLeg70qvVfr7kkYTx9Z4NO&gqsg=4OVo54jg6Fc8v4dgaRWvLlUoQfiT9l0g4KypdpyKIkp3XttitvahDJPyd8JV8AMP&maxads=0&gerf=1NwSv6zgpkznlToCcC1LUPxAge73x0kzNUyoFwPpLQw%3D&wait=true",
"clicktrackUrl": "http:\/\/www.http.com\/rg-cltrack.php?&gr=http%3A%2F%2Fgoogle.com%2F%3FRMGcaf%261437578625&gm=lCHzRGQVmF5GbI%2FoJNvHO9F0H1pK6b4imVg4sD83gr0zwhCg7kUY7A5JisFIua0ovWZYB4g4CbZlK6DDWhXlYS%2FoGwafEe2w6vLAAhtarOqSrags%2FXIb7w%2BHM0BEJgeyKmMXhVQya9xYRoVUupKo7SfWKOP26QW4BeaSRA7pvaleohDknqEJ8irgK41FOPBr&gc=11101851242258318844252&gi=dqJeJ2LIBm6EoVjrQxF%2FslKeVO2MMfAIGz5LwKTbfKTDn9L7haFS7W3vKNwbjSGhC5JthqkexETQM8mEun%2F4M5TCzM0Vphb237zGYUpoBtB1%2BdaJoSRcYUFKnr9lF6i32soKngUvevO7DHx9BHSz7sCMXYPLkJicrRb7WxfYNRWz0plNCCbrW8HYaPbhclR9gVbhSwIUdzpMjwGFrNyh%2B9iqRYF%2BX0wFzLunKbgTnLdmXJuP0Vm%2BjkU%2BC4rprcocV7pcHhlR0%2FKP2vHSKAlWTPcuCA9P04LbPqttMcdlol%2Fpm%2BAeIg79dx%2Bb28yVLKBEpMifhq6%2BT%2B2LndQdLFX%2FCoMvHjee%2BMfVwkRgY8%2F9hqFI%2B9UvBLgcgjCtTYSruCn7",
"domainRegistrant": "as-drid-2351749742621707",
"optimizeTerms": false,
"terms": "[\"Domain Registration\",\"Network Monitoring\",\"Email Hosting\",\"Website Hosting\",\"Network Monitoring Software\",\"High Speed internet\",\"Cable Internet\",\"Broadband Internet\",\"Web Security\",\"Dial-Up Internet\",\"Wireless Internet Providers\",\"Unlimited Broadband\",\"Internet Speed Check\",\"Compare Broadband\",\"Cheap Internet Service\",\"Best Broadband Deals\",\"Internet Solutions\",\"Internet Music\",\"Internet Help\",\"Internet Telephony\",\"Business Internet Providers\",\"Broadband Availability\",\"Prepaid Wireless Internet\",\"Internet Florists\",\"Mobile Wireless Internet\"]",
"uiOptimize": false,
"domainName": "http.com"
},
"relatedsearch": {
"adLoadedCallback": function(cnm, ld) {
if (pgld && !ld && _cfrg && !_cfstc && _cflp) {
cntRS++;
if (cntRS >= totRS && totRS != -1) {
window.location = "http://www.http.com/?_stc_=1"
}
}
}
},
"textads": {
"adLoadedCallback": function(cnm, ld) {}
},
"imagead": {
"adLoadedCallback": function(cnm, ld) {}
},
"ads": {
"adLoadedCallback": function(cnm, ld) {}
}
};
_cfHelp.newOpts.pageoptions["pageLoadedCallback"] = function(requestAccepted, status) {
this.onPageLoad(requestAccepted, status);
_cfblocker = false
};
try {
if (abp) {
_cfHelp.newOpts.pageoptions['channel'] = _cfHelp.newOpts.pageoptions['channel'] + ',test101'
}
} catch (e) {}
</script>
<script type="text/javascript" src="http://a.rmgserving.com/rmgdsc/newcafv2.js?1.1"></script>
</body>
</html>

Related

Inverted video player's navigation bar when video streaming

I'm building a video chat application using Node, Express, Socket.io, and WebRTC by following this tutorial: Link blog
So on my edge browser, after i enabled the video stream on my application and my webcam is activated, i noticed that when i right click on the video area (video element) and click on show all controls, i found that video player navigation bar is inverted.
Do you have any explication on why the nav bar is inverted? (check theses screenshots for inversed nav bar screenshot 1 & screenshot 2)
Below are my codes:
room.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>videoChatApp</title>
<link rel="stylesheet" href="style.css" />
<script src="/socket.io/socket.io.js"></script>
<script src="https://kit.fontawesome.com/c939d0e917.js"></script>
<script src="https://unpkg.com/peerjs#1.3.1/dist/peerjs.min.js"></script>
<script>
const ROOM_ID = "<%= roomId %>";
</script>
</head>
<body>
<div class="header">
<div class="logo">
<h3>Video Chat</h3>
</div>
</div>
<div class="main">
<div class="main__left">
<div class="videos__group">
<div id="video-grid"></div>
</div>
<div class="options">
<div class="options__left">
<div id="stopVideo" class="options__button">
<i class="fa fa-video-camera"></i>
</div>
<div id="muteButton" class="options__button">
<i class="fa fa-microphone"></i>
</div>
</div>
<div class="options__right">
<div id="inviteButton" class="options__button">
<i class="fas fa-user-plus"></i>
</div>
</div>
</div>
</div>
<div class="main__right">
<div class="main__chat_window">
<div class="messages"></div>
</div>
<div class="main__message_container">
<input
id="chat_message"
type="text"
autocomplete="off"
placeholder="Type message here..."
/>
<div id="send" class="options__button">
<i class="fa fa-plus" aria-hidden="true"></i>
</div>
</div>
</div>
</div>
</body>
<script src="script.js"></script>
</html>
script.js:
let myVideoStream;
const videoGrid = document.getElementById("video-grid");
const myVideo = document.createElement("video");
myVideo.muted = true;
navigator.mediaDevices.getUserMedia({
audio: true,
video: true,
})
.then((stream) => {
myVideoStream = stream;
addVideoStream(myVideo, stream);
});
const addVideoStream = (video, stream) => {
video.srcObject = stream;
video.addEventListener("loadedmetadata", () => {
video.play();
videoGrid.append(video);
});
};
server.js:
const express = require('express')
const app = express()
const { v4: uuidv4 } = require("uuid");
app.set('view engine', 'ejs')
app.use(express.static('public'));
app.get('/', (req, res) => {
res.redirect(`/${uuidv4()}`);
});
app.get("/:room", (req, res) => {
res.render("room", { roomId: req.param.room });
});
app.listen(3030, () => {
console.log('Server is runing on port 3030');
})
style.css:
#import url("https://fonts.googleapis.com/css2?family=Poppins:wght#400;500;600&display=swap");
:root {
--main-darklg: #1d2635;
--main-dark: #161d29;
--primary-color: #2f80ec;
--main-light: #eeeeee;
font-family: "Poppins", sans-serif;
}
* {
margin: 0;
padding: 0;
}
.header {
display: flex;
justify-content: center;
align-items: center;
height: 8vh;
position: relative;
width: 100%;
background-color: var(--main-darklg);
}
.logo > h3 {
color: var(--main-light);
}
.main {
overflow: hidden;
height: 92vh;
display: flex;
}
.main__left {
flex: 0.7;
display: flex;
flex-direction: column;
}
.videos__group {
flex-grow: 1;
display: flex;
justify-content: center;
align-items: center;
padding: 1rem;
background-color: var(--main-dark);
}
video {
height: 500px;
border-radius: 1rem;
margin: 0.5rem;
width: 900px;
object-fit: cover;
transform: rotateY(180deg);
-webkit-transform: rotateY(180deg);
-moz-transform: rotateY(180deg);
}
.options {
padding: 1rem;
display: flex;
background-color: var(--main-darklg);
}
.options__left {
display: flex;
}
.options__right {
margin-left: auto;
}
.options__button {
display: flex;
justify-content: center;
align-items: center;
background-color: var(--primary-color);
height: 50px;
border-radius: 5px;
color: var(--main-light);
font-size: 1.2rem;
width: 50px;
margin: 0 0.5rem;
}
.background__red {
background-color: #f6484a;
}
.main__right {
display: flex;
flex-direction: column;
flex: 0.3;
background-color: #242f41;
}
.main__chat_window {
flex-grow: 1;
overflow-y: scroll;
}
.main__chat_window::-webkit-scrollbar {
display: none;
}
.main__message_container {
padding: 1rem;
display: flex;
align-items: center;
justify-content: center;
}
.main__message_container > input {
height: 50px;
flex: 1;
font-size: 1rem;
border-radius: 5px;
padding-left: 20px;
border: none;
}
.messages {
display: flex;
flex-direction: column;
margin: 1.5rem;
}
.message {
display: flex;
flex-direction: column;
}
.message > b {
color: #eeeeee;
display: flex;
align-items: center;
text-transform: capitalize;
}
.message > b > i {
margin-right: 0.7rem;
font-size: 1.5rem;
}
.message > span {
background-color: #eeeeee;
margin: 1rem 0;
padding: 1rem;
border-radius: 5px;
}
#video-grid {
display: flex;
justify-content: center;
flex-wrap: wrap;
}
#showChat {
display: none;
}
.header__back {
display: none;
position: absolute;
font-size: 1.3rem;
top: 17px;
left: 28px;
color: #fff;
}
#media (max-width: 700px) {
.main__right {
display: none;
}
.main__left {
width: 100%;
flex: 1;
}
video {
height: auto;
width: 100%;
}
#showChat {
display: flex;
}
}
You are applying a 180 degree rotation to the element (i.e. mirroring it)
by using transform: rotateY(180deg) in your CSS file which also rotates the controls.
For WebRTC usage the common approach to solving this is not to use the build-in controls of the video element.

Stripe creditcard elements not loaded in Safari browser

We use stripe v.3 to add creditcard for a customer. It works on all browsers chrome and firefox. But safari returns the following error.
ReferenceError: Can't find variable: elements
Tested on physical iphone device it seems older version cant create the stripe elements leaving the input field, clumpy and not showing the CC information. Check screenshot.
The bug occurs on iOS version 11.3.1 and down. The iframe is showing in the source elements but dont add the class .StripeElement to the dom.
import {
Component,
Inject,
ViewChild,
ElementRef,
AfterViewInit,
OnDestroy,
ChangeDetectorRef,
} from '#angular/core';
import { NgForm } from '#angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '#angular/material/dialog';
import { ToastrService } from 'ngx-toastr';
import { PaymentService } from '#services/http/payment.service';
import { StateService } from '#services/Logic/state.service';
import { TranslatePipe } from '#app/pipes/translate.pipe';
#Component({
selector: 'app-add-credit-card-dialog',
templateUrl: 'addCreditCard.html',
styleUrls: ['addCreditCard.scss', '../../dialogs.scss'],
})
export class AddCreditCardDialogComponent implements AfterViewInit, OnDestroy {
#ViewChild('cardInfo', { static: true }) cardInfo: ElementRef;
card: any;
cardHandler = this.onChange.bind(this);
error: string;
cardholderName: string;
constructor(
private cd: ChangeDetectorRef,
private toastr: ToastrService,
private translatePipe: TranslatePipe,
private stateService: StateService,
private paymentService: PaymentService,
public dialogRef: MatDialogRef<AddCreditCardDialogComponent>,
#Inject(MAT_DIALOG_DATA) public data: any
) {}
ngAfterViewInit() {
this.card = elements.create('card');
this.card.mount(this.cardInfo.nativeElement);
this.card.addEventListener('change', this.cardHandler);
// Force the Element frame to paint once it is visible on the page
setTimeout(() => {
this.forceReflow('.StripeElement');
}, 1000);
}
ngOnDestroy() {
this.card.removeEventListener('change', this.cardHandler);
this.card.destroy();
}
forceReflow(selector) {
const el = document.querySelector(selector);
if (el) {
const initialDisplay = el.style.display;
el.style.display = 'none';
el.offsetHeight;
el.style.display = initialDisplay;
}
}
onChange({ error }) {
if (error) {
this.error = error.message;
} else {
this.error = null;
}
this.cd.detectChanges();
}
async onSubmit(form: NgForm) {
if (!this.cardholderName || this.cardholderName.length === 0) {
return this.toastr.error(this.translatePipe.transform('TOAST_MESSAGES.ERROR.MISSING_CARDHOLDER'));
}
this.stateService.toggleWaitingPage(true);
// create a Setup Intent for this card
const { setupIntent, error } = await stripe.handleCardSetup(
this.data.client_secret,
this.card,
{
payment_method_data: {
billing_details: { name: this.cardholderName },
},
}
);
if (error) {
this.toastr.error(error.message);
this.stateService.toggleWaitingPage(false);
} else {
// create a Payment Method from the previously created Setup Intent and attach it to the Customer
const paymentMethod = await this.paymentService
.attachPaymentMethod({ payment_method: setupIntent.payment_method })
.toPromise();
this.close(paymentMethod);
}
}
close(data: any = null): void {
this.dialogRef.close(data);
}
}
form {
display: flex;
flex-direction: column;
align-items: center;
width: 95%;
margin: auto;
.form-row {
width: 100%;
margin: 0 0 20px;
box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.2);
border-radius: 5px;
padding: 10px;
height: 40px;
#card-errors {
font-size: 12px;
color: #f82e42;
}
}
}
p {
color: #707070;
}
.input_area{
width: 100%;
text-align: center;
padding-bottom: 115px;
}
.body_area{
display: block;
height: 100%;
.attention{
display: flex;
margin: 20px 0px;
height: 100%;
padding: 5px 0px;
background-color: #F6F9FC;
.notranslate {
color: #89b153;
font-size: 18px;
margin-left: 8px;
padding-top: 2px;
padding-right: 5px;
}
p{
text-align: left !important;
margin-bottom: 0px !important;
}
.notranslate{
color: #707070;
place-self: center;
}
}
}
.header_wrapper{
display: block;
height: 100%;
.pinpay{
margin-bottom: unset !important;
font-weight: bold;
font-size: 17px;
color: #4a4a56;
}
.img {
height: 80px;
width: 80px;
margin-top: 10px;
margin: auto;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
box-shadow: 0 3px 6px 0 rgba(0, 0, 0, 0.16);
border-radius: 500px;
#media (max-width: 320px) and (max-height: 438px) { display: none; }
.image-icon{
height: 60px;
width: 60px;
margin-top: 3px;
margin-left: 8.4px;
}
}
}
#cardholder-name {
width: 95%;
margin-bottom: 20px;
box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.2);
background: transparent;
border: none;
}
<div class="dialog_container">
<div class="header_row">
<div class="header_left"></div>
<span class="close" (click)="close()">✕</span>
<h5 id="header_title">{{ 'DIALOGS.ADD_CREDIT_CARD.TITLE' | translate }}</h5>
</div>
<div class="header_wrapper">
<div class="img">
</div>
<div style="display: flex; margin-bottom: unset">
<p class="pinpay">PinployPay</p>
<span></span>™
</div>
<p class="pinpay1">Sikker handel</p>
</div>
<div class="body_area">
<div class="attention">
<mat-icon [matTooltip]="'PAGES.SETTINGS.PROFILE.COMPLETION_RATE_INFO' | translate">info</mat-icon>
<p>{{ 'DIALOGS.ADD_CREDIT_CARD.MESSAGE' | translate }}</p>
</div>
<p>
<mat-icon class="notranslate">remove_shopping_cart</mat-icon>{{
'DIALOGS.ADD_CREDIT_CARD.MESSAGE_1' | translate }}
</p>
</div>
<div class="input_area">
<input
id="cardholder-name"
[(ngModel)]="cardholderName"
[placeholder]="'DIALOGS.ADD_CREDIT_CARD.CARDHOLDER' | translate"
/>
<form #checkout="ngForm" (ngSubmit)="onSubmit(checkout)" class="checkout">
<div class="form-row">
<div id="card-info" #cardInfo></div>
<div id="card-errors" role="alert" *ngIf="error">{{ error }}</div>
</div>
<button type="submit" class="pinploy_button_v2_mobile_green">Ok</button>
</form>
</div>
</div>
index.html
<body>
<app-root></app-root>
<script src="https://js.stripe.com/v3/"></script>
<script>
const stripeKey =
window.location.origin === "https://www.pinploy.com"
? "pk_live_******q"
: "pk_test_1P******";
let stripe = Stripe(stripeKey);
let elements = stripe.elements();
</script>
</body>
</html>

How to list Items in rows of 3 in React

I have a list of items that I want to display in rows of 3 but it's not displaying in 3 rows. it works in the normal HTML but doesn't work in React.
Here is my Event Component
const Event = (props) => (
<div className="wrap">
<div className="tile">
<img src={props.event.eventImage} />
<div className="text">
<h1>{props.event.title}</h1>
<h2 className="animate-text">More lorem ipsum bacon ipsum.</h2>
<p className="animate-text">{props.event.description}</p>
<div className="dots">
<span />
<span />
<span />
</div>
</div>
</div>
</div>
);
export default class EventsList extends Component {
constructor(props) {
super(props);
this.state = { events: [] };
}
componentDidMount() {
axios
.get("http://localhost:9000/events/")
.then((response) => {
this.setState({ events: response.data });
})
.catch(function (error) {
console.log(error);
});
}
eventList() {
return this.state.events.map(function (currentEvent, i) {
return <Event event={currentEvent} key={i} />;
});
}
render() {
return (
<div>
<div className="row">{this.eventList()}</div>
</div>
);
}
}
and my css
.wrap {
margin: 50px auto 0 auto;
width: 100%;
display: flex;
align-items: space-around;
max-width: 1200px;
}
.tile {
width: 380px;
height: 380px;
margin: 10px;
background-color: #99aeff;
display: inline-block;
background-size: cover;
position: relative;
cursor: pointer;
transition: all 0.4s ease-out;
box-shadow: 0px 35px 77px -17px rgba(0, 0, 0, 0.44);
overflow: hidden;
color: white;
font-family: "Roboto";
}
.tile img {
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 0;
transition: all 0.4s ease-out;
}
.tile .text {
/* z-index:99; */
position: absolute;
padding: 30px;
height: calc(100% - 60px);
}
.tile h1 {
font-weight: 300;
margin: 0;
text-shadow: 2px 2px 10px rgba(0, 0, 0, 0.3);
}
.tile h2 {
font-weight: 100;
margin: 20px 0 0 0;
font-style: italic;
transform: translateX(200px);
}
.tile p {
font-weight: 300;
margin: 20px 0 0 0;
line-height: 25px;
/* opacity:0; */
transform: translateX(-200px);
transition-delay: 0.2s;
}
.animate-text {
opacity: 0;
transition: all 0.6s ease-in-out;
}
.tile:hover {
/* background-color:#99aeff; */
box-shadow: 0px 35px 77px -17px rgba(0, 0, 0, 0.64);
transform: scale(1.05);
}
.tile:hover img {
opacity: 0.2;
}
.tile:hover .animate-text {
transform: translateX(0);
opacity: 1;
}
.dots {
position: absolute;
bottom: 20px;
right: 30px;
margin: 0 auto;
width: 30px;
height: 30px;
color: currentColor;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
}
.dots span {
width: 5px;
height: 5px;
background-color: currentColor;
border-radius: 50%;
display: block;
opacity: 0;
transition: transform 0.4s ease-out, opacity 0.5s ease;
transform: translateY(30px);
}
.tile:hover span {
opacity: 1;
transform: translateY(0px);
}
.dots span:nth-child(1) {
transition-delay: 0.05s;
}
.dots span:nth-child(2) {
transition-delay: 0.1s;
}
.dots span:nth-child(3) {
transition-delay: 0.15s;
}
#media (max-width: 1000px) {
.wrap {
flex-direction: column;
width: 400px;
}
}
This is how it's displaying.
But this is what I want to achieve.
I am new to React and I'm learning by building a project.
Here is codepen link of what I want to achieve.
Codepen Link
I have a feeling it's your css, you have your wrap class stretching the whole row width and within it, there is a tile that's only 380px.
Consider making row a grid with three columns.
Ciao, you can use display: 'in-line' like this:
return <Event event={currentEvent} key={i} style={{display: 'in-line'}}/>;

ReactJS responsive carousel from scratch

Okay, so basically I am trying to write a carousel for ReactJS from scratch.
I've accomplished to code must of the features required as navigation, slides and so on.
The main purpose of this is to make it responsive, but that is what I am having a hard time figuring out how to do.
carousel.js
import React from 'react'
import { NavLink } from 'react-router-dom'
import classNames from 'classnames'
export default class Carousel extends React.Component {
constructor(props) {
super(props)
this.handleNext = this.handleNext.bind(this)
this.handlePrev = this.handlePrev.bind(this)
this.state = {
innerWidth: 0,
navPrevDisabled: true
}
}
componentWillMount() {
var stateItems = []
for(let i in this.props.items) {
stateItems.push(
<div className="react-item movie" key={i}>
<div className="front">
<div className="front-image" style={{backgroundImage: `url(${this.props.items[i].poster})`}}>
</div>
<div className="backdrop medium">
<div className="react-play-button fill">
<figure className="icon-content"></figure>
</div>
</div>
</div>
</div>
)
}
this.setState({
items: stateItems
})
}
componentWillUnmount() {
window.removeEventListener("resize", this.updateCarousel, false)
}
updateCarousel = () => {
var $reactItem = $('.carousel-wrapper .carousel-inner .react-item')
var maxw = $('.carousel-wrapper').width()
/*var slideItemsFit = $reactItem.filter(function () {
return $(this).position().left < maxw
}).length*/
var itemsFitSlide = Math.floor(maxw / $reactItem.outerWidth(true))
console.log(itemsFitSlide)
var margin = $reactItem.outerWidth(true) * itemsFitSlide
margin = (maxw - margin) / itemsFitSlide / 2
$reactItem.css({marginLeft: `${margin}px`, marginRight: `${margin}px`})
this.setState({
itemsShownTotal: itemsFitSlide,
itemWidth: $reactItem.outerWidth(true),
navNextDisabled: (itemsFitSlide === this.state.items.length),
itemsFitSlide: itemsFitSlide
})
}
componentDidMount() {
this.updateCarousel()
window.addEventListener("resize", this.updateCarousel, false)
}
handleNext(e) {
var state = this.state
var maxw = $('.carousel-wrapper').width()
var innerWidth = -Math.abs(state.innerWidth - (state.itemWidth * state.itemsFitSlide))
var itemsLeft = state.items.length - state.itemsShownTotal
var lastSlide = state.itemsFitSlide > itemsLeft
if(lastSlide) {
innerWidth = -Math.abs(state.innerWidth - (state.itemWidth * itemsLeft))
}
var itemsShownTotal = (lastSlide)
? state.itemsShownTotal + itemsLeft
: state.itemsShownTotal + state.itemsFitSlide
this.setState({
itemsShownTotal: itemsShownTotal,
innerWidth: innerWidth,
navPrevDisabled: false,
navNextDisabled: itemsShownTotal === state.items.length
})
}
handlePrev(e) {
var state = this.state
var innerWidth = state.innerWidth + (state.itemWidth * state.itemsFitSlide)
//var itemsLeft = state.itemsFitSlide - state.itemsShownTotal
var firstSlide = false
if(innerWidth >= 0) {
firstSlide = true
innerWidth = 0
}
var itemsShownTotal = (firstSlide)
? state.itemsFitSlide
: state.itemsShownTotal - state.itemsFitSlide
this.setState({
itemsShownTotal: itemsShownTotal,
innerWidth: innerWidth,
navPrevDisabled: firstSlide,
navNextDisabled: false
})
}
render() {
var nav = {
prev: classNames({
navigation: true,
prev: true,
disabled: this.state.navPrevDisabled,
whiteframe: true
}),
next: classNames({
navigation: true,
next: true,
disabled: this.state.navNextDisabled,
whiteframe: true
})
}
return (
<section className="block collection carousel portrait">
<div className="scaffold">
<i className={nav.prev} onClick={this.handlePrev}></i>
<i className={nav.next} onClick={this.handleNext}></i>
<header className="collection-header">
<NavLink to={this.props.route}>
<h2>{this.props.title}</h2>
</NavLink>
</header>
<div className="carousel-wrapper">
<div className="carousel-inner use-transition" style={{transform: `translateX(${this.state.innerWidth}px)`}}>
{this.state.items}
</div>
</div>
</div>
</section>
)
}
}
Basically let's say there's 5 images in a slide, but only width enough in the wrapper to fit 4 images, I then want to redo the process and margin the 4 images to fit the center of the wrapper.
carousel.css
.scaffold {
position: relative;
}
.block.collection .collection-header {
margin: 0 0 20px;
position: relative;
padding-top: 20px;
}
.block.collection .collection-header h2 {
outline: none;
text-decoration: none;
margin: 0;
color: #212d33;
font-size: 2.6rem;
letter-spacing: -0.01em;
line-height: 36px;
font-weight: normal;
}
.block.collection.carousel .carousel-wrapper {
overflow: hidden;
width: 100%;
}
.block.collection.carousel .carousel-wrapper .carousel-inner {
display: inline-block;
margin-right: 5px;
white-space: nowrap;
}
.block.collection.carousel .carousel-wrapper .carousel-inner.use-transition {
transition: transform 0.5s ease-out;
}
.block.collection.portrait .react-item {
width: 186px;
margin: 0 0px 20px 0px;
}
.block.collection.portrait .react-item.hidden {
opacity: 0;
}
.block.collection .react-item {
position: relative;
display: inline-block;
vertical-align: top;
margin-top: 10px;
margin-bottom: 10px;
}
.block.collection.portrait .react-item .front {
height: 279px;
}
.block.collection .react-item .front {
background-color: #212d33;
position: relative;
display: block;
text-decoration: none;
}
.block.collection .react-item .front .front-image {
animation: fadein 500ms;
position: absolute;
height: 100%;
width: 100%;
top: 0;
left: 0;
background-size: cover;
}
.block.collection .react-item .backdrop {
transition: opacity 0.1s ease-in-out;
opacity: 0;
height: 100%;
position: absolute;
width: 100%;
top: 0;
left: 0;
z-index: 5;
text-align: center;
background: rgba(15, 22, 26, 0.25);
}
.block.collection .react-item .backdrop:hover {
opacity: 1;
}
.react-play-button.fill {
margin: 0;
width: 100%;
height: 100%;
background-size: 68px;
}
.react-play-button {
display: flex;
align-items: center;
justify-content: center;
background-color: transparent;
border: 0;
padding: 0;
cursor: pointer;
}
.react-play-button .icon-content {
width: 68px;
height: 68px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyBoZWlnaHQ9IjEwMCUiIHdpZHRoPSIxMDAlIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgdmVyc2lvbj0iMS4wIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KICAgIDxzdHlsZT48IVtDREFUQVsKICAgICAgICBnIHsKICAgICAgICAgICAgc3Ryb2tlOiAjZmZmOwogICAgICAgIH0KICAgICAgICBnIGNpcmNsZSB7CiAgICAgICAgICAgIGZpbGw6IHJnYmEoMCwwLDAsMC4wKTsKICAgICAgICAgICAgc3Ryb2tlLXdpZHRoOiA0OwogICAgICAgIH0KICAgICAgICBnIHBvbHlsaW5lIHsKICAgICAgICAgICAgZmlsbDogdHJhbnNwYXJlbnQ7CiAgICAgICAgICAgIHN0cm9rZS13aWR0aDogMTA7CiAgICAgICAgfQogICAgXV0+PC9zdHlsZT4KCiAgICA8Zz4KICAgICAgICA8Y2lyY2xlIHI9IjQ4IiBjeD0iNTAiIGN5PSI1MCIgLz4KICAgICAgICA8cG9seWxpbmUgcG9pbnRzPSI0MSwyOCA2Myw1MCA0MSw3MiIgLz4KICAgIDwvZz4KPC9zdmc+);
background-size: contain;
background-position: center;
background-repeat: no-repeat;
}
.block.collection.carousel .navigation {
top: 49%;
border: none;
cursor: pointer;
position: absolute;
width: 66px;
background: rgba(249, 249, 251, 0.7);
width: 48px;
height: 60px;
display: block;
font-size: 0;
border-radius: 2px;
z-index: 10;
opacity: 1;
pointer-events: auto;
transition: opacity .3s ease-in-out;
}
.block.collection.carousel .navigation.disabled {
opacity: 0;
pointer-events: none;
}
.block.collection.carousel .navigation:hover {
background-color: #FFF;
}
.block.collection.carousel .navigation:hover::after {
opacity: 1;
}
.block.collection.carousel .navigation.prev {
left: -25px;
}
.block.collection.carousel .navigation.next {
right: -25px;
}
.block.collection.carousel .navigation::after {
transition: opacity .5s ease;
background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE5LjIuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAxMy40IDI0IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAxMy40IDI0OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+Cgkuc3Qwe2ZpbGw6IzIxMkQzMzt9Cjwvc3R5bGU+CjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0wLDEuNEwxMC42LDEyTDAsMjIuNkwxLjQsMjRsMTItMTJMMS40LDBMMCwxLjR6Ii8+Cjwvc3ZnPgo=) no-repeat;
width: 16px;
height: 24px;
content: '';
position: absolute;
top: 18px;
left: 18px;
opacity: 0.7;
}
.block.collection.carousel .navigation.prev::after {
left: 13px;
transform: rotate(180deg);
}

I need to automatically stop recording audio after 90 sec

I'm using jquery plugin from this site https://subinsb.com/html5-record-mic-voice and I have trouble with making audio recording stop after 90 sec
here is code, I'm not very good in JS, so thanks everyone who will help
var recLength = 0,
recBuffersL = [],
recBuffersR = [],
sampleRate;
this.onmessage = function(e) {
switch (e.data.command) {
case 'init':
init(e.data.config);
break;
case 'record':
record(e.data.buffer);
break;
case 'exportWAV':
exportWAV(e.data.type);
break;
case 'getBuffer':
getBuffer();
break;
case 'clear':
clear();
break;
}
};
function init(config) {
sampleRate = config.sampleRate;
}
function record(inputBuffer) {
recBuffersL.push(inputBuffer[0]);
recBuffersR.push(inputBuffer[1]);
recLength += inputBuffer[0].length;
}
function exportWAV(type) {
var bufferL = mergeBuffers(recBuffersL, recLength);
var bufferR = mergeBuffers(recBuffersR, recLength);
var interleaved = interleave(bufferL, bufferR);
var dataview = encodeWAV(interleaved);
var audioBlob = new Blob([dataview], {
type: type
});
this.postMessage(audioBlob);
}
function getBuffer() {
var buffers = [];
buffers.push(mergeBuffers(recBuffersL, recLength));
buffers.push(mergeBuffers(recBuffersR, recLength));
this.postMessage(buffers);
}
function clear() {
recLength = 0;
recBuffersL = [];
recBuffersR = [];
}
function mergeBuffers(recBuffers, recLength) {
var result = new Float32Array(recLength);
var offset = 0;
for (var i = 0; i < recBuffers.length; i++) {
result.set(recBuffers[i], offset);
offset += recBuffers[i].length;
}
return result;
}
function interleave(inputL, inputR) {
var length = inputL.length + inputR.length;
var result = new Float32Array(length);
var index = 0,
inputIndex = 0;
while (index < length) {
result[index++] = inputL[inputIndex];
result[index++] = inputR[inputIndex];
inputIndex++;
}
return result;
}
function floatTo16BitPCM(output, offset, input) {
for (var i = 0; i < input.length; i++, offset += 2) {
var s = Math.max(-1, Math.min(1, input[i]));
output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
}
}
function writeString(view, offset, string) {
for (var i = 0; i < string.length; i++) {
view.setUint8(offset + i, string.charCodeAt(i));
}
}
function encodeWAV(samples) {
var buffer = new ArrayBuffer(44 + samples.length * 2);
var view = new DataView(buffer);
/* RIFF identifier */
writeString(view, 0, 'RIFF');
/* RIFF chunk length */
view.setUint32(4, 36 + samples.length * 2, true);
/* RIFF type */
writeString(view, 8, 'WAVE');
/* format chunk identifier */
writeString(view, 12, 'fmt ');
/* format chunk length */
view.setUint32(16, 16, true);
/* sample format (raw) */
view.setUint16(20, 1, true);
/* channel count */
view.setUint16(22, 2, true);
/* sample rate */
view.setUint32(24, sampleRate, true);
/* byte rate (sample rate * block align) */
view.setUint32(28, sampleRate * 4, true);
/* block align (channel count * bytes per sample) */
view.setUint16(32, 4, true);
/* bits per sample */
view.setUint16(34, 16, true);
/* data chunk identifier */
writeString(view, 36, 'data');
/* data chunk length */
view.setUint32(40, samples.length * 2, true);
floatTo16BitPCM(view, 44, samples);
return view;
}
//------I guess problem is below--------------------------------------------
function restore() {
$("#record,#live").removeClass("disabled");
$(".one").addClass("disabled");
$.voice.stop();
}
$(document).ready(function() {
$(document).on("click", "#record:not(.disabled)", function() {
$("#ex1").css({
opacity: 1
});
$("#prepare").animate({
backgroundPosition: '0px,0px,0px,0px'
}, 1000).queue(function() {
$("#rec-progress").animate({
backgroundPosition: '0px,0px,0px,0px'
}, 5000);
/*I need to stop recording somewere here, I tried put .delay(30000).stop,
and things like that, but there were wrong ideas*/
elem = $(this);
$.voice.record($("#live").is(":checked"), function() {
elem.addClass("disabled");
$("#live").addClass("disabled");
$("#stop,#play,#download").removeClass("disabled");
});
});
});
$(document).on("click", "#stop:not(.disabled)", function() {
restore();
});
$(document).on("click", "#play:not(.disabled)", function() {
$.voice.export(function(url) {
$("#audio").attr("src", url);
$("#audio")[0].play();
}, "URL");
restore();
});
$(document).on("click", "#download:not(.disabled)", function() {
$.voice.export(function(url) {
$("<a href='" + url + "' download='MyRecording.wav'></a>")[0].click();
}, "URL");
restore();
});
});
* {
margin 0px;
padding: 0px;
}
h2 {
font-family: Tahoma, arial;
font-size: 2em;
width: 500px;
display: block;
margin-left: 50%;
left: -250px;
position: relative;
text-align: center;
}
body {
background: grey;
}
#progress-bar {
height: 100px;
width: 00px;
margin-left: 50%;
z-index: 10;
left: -350px;
position: relative;
}
#prepare {
background: url(https://disk.yandex.ru/preview/?id=/disk/bar.png&size=800x);
z-index: -10;
overflow: hidden;
height: 100px;
background-position: -610px, 0px, 0px, 0px;
background-repeat: no-repeat;
width: 700px;
position: absolute;
top: 0px
}
#rec-progress {
background: url(https://disk.yandex.ru/preview/?id=/disk/rec.png&size=800x);
z-index: -5;
overflow: hidden;
height: 100px;
background-position: -610px, 0px, 0px, 0px;
background-repeat: no-repeat;
width: 700px;
position: absolute;
top: 0px
}
#interface {
width: 596px;
height: 100px;
margin-left: 50%;
left: -315px;
position: relative;
}
#content {
height: 1000px;
}
#ex1 {
background: url(ex1/type1.bmp);
width: 100%;
min-width: 1340px;
min-height: 200px;
background-size: contain;
background-repeat: no-repeat;
opacity: 0;
}
.button {
width: 120px;
display: inline-block;
vertical-align: middle;
margin: 0px auto;
padding: 5px 12px;
cursor: pointer;
outline: none;
font-size: 13px;
text-decoration: none !important;
text-align: center;
color: #fff;
background-color: #4D90FE;
background-image: linear-gradient(top, #4D90FE, #4787ED);
background-image: -ms-linear-gradient(top, #4D90FE, #4787ED);
background-image: -o-linear-gradient(top, #4D90FE, #4787ED);
background-image: linear-gradient(top, #4D90FE, #4787ED);
border: 1px solid #4787ED;
box-shadow: 0 1px 3px #BFBFBF;
}
a.button {
color: #fff;
}
.button:hover {
box-shadow: inset 0px 1px 1px #8C8C8C;
}
.button.disabled {
box-shadow: none;
opacity: 0.7;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<script src="http://lab.subinsb.com/projects/jquery/core/jquery-2.1.1.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="cdn/recorder.js"></script>
<script src="http://lab.subinsb.com/projects/jquery/voice/jquery.voice.min.js"></script>
<link rel="stylesheet" type="text/css" href="cdn/main.css">
<script src="cdn/jquery.backgroundpos.min.js"></script>
<script src="cdn/record.js"></script>
<style src="cdn/main.css"></style>
<title>Title</title>
</head>
<body>
<div id="content">
<h2>Example</h2>
<div id="progress-bar">
<img src="https://disk.yandex.ru/preview/?id=/disk/progress.png&size=800x">
<div id="rec-progress"></div>
<div id="prepare"></div>
</div>
<div id="interface">
<a class="button" id="record">Start</a>
<a class="button disabled one" id="stop">restart</a>
<a class="button disabled one" id="play">listen</a>
<a class="button disabled one" id="download">save</a>
</div>
<div id="ex1"></div>
</div>
<audio controls src="" id="audio"></audio>
</body>
</html>

Resources