Keep Added Image Behind Image while Moving - fabricjs

I'm using fabricjs 1.7.22 with a toggle-able background and the ability to add images behind said background images. I have it nearly working as I'd like but my problem is that when I move an image uploaded from my computer behind a frame image, it isn't staying behind the frame in the first canvas. However, it is working as it should in the static canvases. What am I doing wrong?
I have canvas.preserveObjectStacking = true; set, so am confused.
Please see my code snippet below, choose an image, and upload an image from your computer to see replicate my problem.
var canvas = [],
image;
canvas.push(new fabric.Canvas('c0'));
for (i = 1; i <= 7; i++) {
canvas.push(new fabric.StaticCanvas('sc' + i));
}
canvas.preserveObjectStacking = true;
function dropText() {
var text = new fabric.IText('Type here...', {
fontSize: 27,
top: 10,
left: 10,
});
canvas[0].add(text);
}
canvas[0].on('object:added', onModified);
canvas[0].on('object:modified', onModified);
canvas[0].on('object:scaling', onModified);
canvas[0].on('object:moving', onModified);
function onModified(option) {
var ob = option.target;
var index = canvas[0].getObjects().indexOf(ob);
ob.clone(function(obj) {
for (i = 1; i <= 7; i++) {
canvas[i].insertAt(obj, index, true);
}
});
};
// New Photo to Canvas
document.getElementById('addimg').onchange = function handleImage(e) {
var reader = new FileReader();
reader.onload = function (event) {
var imgObj = new Image();
imgObj.src = event.target.result;
imgObj.onload = function () {
var image = new fabric.Image(imgObj);
image.set({
left: 10,
top: 10,
}).scaleToHeight(100);
canvas[0].add(image);
canvas[0].sendToBack(image);
updateCanvas();
};
};
reader.readAsDataURL(e.target.files[0]);
};
$('#update').click(function() {
updateCanvas();
});
function updateCanvas() {
var json = JSON.stringify(canvas[0]);
for (i = 1; i <= 7; i++) {
canvas[i].loadFromJSON(json);
}
}
// Toggling Images
function replaceImage(imgUrl) {
if (!isImageLoaded) return; //return if initial image not loaded
image.setSrc(imgUrl, function() {
canvas[0].renderAll();
updateCanvas();
});
}
// Default (Blank)
fabric.Image.fromURL('https://i.imgur.com/SamdNdX.png', function(img) {
isImageLoaded = true;
image = img.set({
selectable: false,
evented: false,
}).scale(0.5);
canvas[0].add(image);
canvas[0].sendToBack(image);
updateCanvas();
});
$('#save').click(function() {
html2canvas($('#imagesave'), {
onrendered: function(canvas) {
var a = document.createElement('a');
// toDataURL defaults to png, so we need to request a jpeg, then convert for file download.
a.href = canvas.toDataURL("image/jpeg").replace("image/jpeg", "image/octet-stream");
a.download = 'myfile.jpg';
a.click();
}
});
});
body {
margin: 0px;
padding: 0px;
}
canvas {
border: 1px solid #f00;
margin: 0px;
display: block;
}
td {
margin: 0;
padding: 0;
border: 0;
outline: 0;
vertical-align: baseline;
}
#addimg {
position: relative;
overflow: hidden;
cursor: pointer;
}
input {
position: absolute;
font-size: 50px;
opacity: 0;
right: 0;
top: 0;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.22/fabric.js"></script>
<button onclick="dropText();" class="dropdown-item">Add Text</button>
<a id="addimg" class="dropdown-item">
<input type="file" name="file" />Add Image</a>
<button id="save">Save</button>
<button onclick="replaceImage('https://i.imgur.com/SamdNdX.png')">Blank</button>
<button onclick="replaceImage('https://i.imgur.com/RuZ5HTH.png')">Image A Pic</button>
<button onclick="replaceImage('https://i.imgur.com/u3Knj4R.png')">Image B Pic</button>
<div id="imagesave">
<table>
<tr>
<td>
<canvas id="c0" width="187.5" height="318.75"></canvas>
</td>
<td>
<canvas id="sc1" width="187.5" height="318.75"></canvas>
</td>
<td>
<canvas id="sc2" width="187.5" height="318.75"></canvas>
</td>
<td>
<canvas id="sc3" width="187.5" height="318.75"></canvas>
</td>
</tr>
<tr>
<td>
<canvas id="sc4" width="187.5" height="318.75"></canvas>
</td>
<td>
<canvas id="sc5" width="187.5" height="318.75"></canvas>
</td>
<td>
<canvas id="sc6" width="187.5" height="318.75"></canvas>
</td>
<td>
<canvas id="sc7" width="187.5" height="318.75"></canvas>
</td>
</tr>
</table>
</div>

You need to add preserveObjectStacking:true to each canvas, as you are implementing the preserveObjectStacking:true to the array and not to the canvas.
var canvas = [],
image;
canvas.push(new fabric.Canvas('c0',{preserveObjectStacking:true}));
for (i = 1; i <= 7; i++) {
canvas.push(new fabric.StaticCanvas('sc' + i,{preserveObjectStacking:true}));
}
canvas.preserveObjectStacking = true;
function dropText() {
var text = new fabric.IText('Type here...', {
fontSize: 27,
top: 10,
left: 10,
});
canvas[0].add(text);
}
canvas[0].on('object:added', onModified);
canvas[0].on('object:modified', onModified);
canvas[0].on('object:scaling', onModified);
canvas[0].on('object:moving', onModified);
function onModified(option) {
var ob = option.target;
var index = canvas[0].getObjects().indexOf(ob);
ob.clone(function(obj) {
for (i = 1; i <= 7; i++) {
canvas[i].insertAt(obj, index, true);
}
});
};
// New Photo to Canvas
document.getElementById('addimg').onchange = function handleImage(e) {
var reader = new FileReader();
reader.onload = function (event) {
var imgObj = new Image();
imgObj.src = event.target.result;
imgObj.onload = function () {
var image = new fabric.Image(imgObj);
image.set({
left: 10,
top: 10,
}).scaleToHeight(100);
canvas[0].add(image);
canvas[0].sendToBack(image);
updateCanvas();
};
};
reader.readAsDataURL(e.target.files[0]);
};
$('#update').click(function() {
updateCanvas();
});
function updateCanvas() {
var json = JSON.stringify(canvas[0]);
for (i = 1; i <= 7; i++) {
canvas[i].loadFromJSON(json);
}
}
// Toggling Images
function replaceImage(imgUrl) {
if (!isImageLoaded) return; //return if initial image not loaded
image.setSrc(imgUrl, function() {
canvas[0].renderAll();
updateCanvas();
});
}
// Default (Blank)
fabric.Image.fromURL('https://i.imgur.com/SamdNdX.png', function(img) {
isImageLoaded = true;
image = img.set({
selectable: false,
evented: false,
}).scale(0.5);
canvas[0].add(image);
canvas[0].sendToBack(image);
updateCanvas();
});
$('#save').click(function() {
html2canvas($('#imagesave'), {
onrendered: function(canvas) {
var a = document.createElement('a');
// toDataURL defaults to png, so we need to request a jpeg, then convert for file download.
a.href = canvas.toDataURL("image/jpeg").replace("image/jpeg", "image/octet-stream");
a.download = 'myfile.jpg';
a.click();
}
});
});
body {
margin: 0px;
padding: 0px;
}
canvas {
border: 1px solid #f00;
margin: 0px;
display: block;
}
td {
margin: 0;
padding: 0;
border: 0;
outline: 0;
vertical-align: baseline;
}
#addimg {
position: relative;
overflow: hidden;
cursor: pointer;
}
input {
position: absolute;
font-size: 50px;
opacity: 0;
right: 0;
top: 0;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.22/fabric.js"></script>
<button onclick="dropText();" class="dropdown-item">Add Text</button>
<a id="addimg" class="dropdown-item">
<input type="file" name="file" />Add Image</a>
<button id="save">Save</button>
<button onclick="replaceImage('https://i.imgur.com/SamdNdX.png')">Blank</button>
<button onclick="replaceImage('https://i.imgur.com/RuZ5HTH.png')">Image A Pic</button>
<button onclick="replaceImage('https://i.imgur.com/u3Knj4R.png')">Image B Pic</button>
<div id="imagesave">
<table>
<tr>
<td>
<canvas id="c0" width="187.5" height="318.75"></canvas>
</td>
<td>
<canvas id="sc1" width="187.5" height="318.75"></canvas>
</td>
<td>
<canvas id="sc2" width="187.5" height="318.75"></canvas>
</td>
<td>
<canvas id="sc3" width="187.5" height="318.75"></canvas>
</td>
</tr>
<tr>
<td>
<canvas id="sc4" width="187.5" height="318.75"></canvas>
</td>
<td>
<canvas id="sc5" width="187.5" height="318.75"></canvas>
</td>
<td>
<canvas id="sc6" width="187.5" height="318.75"></canvas>
</td>
<td>
<canvas id="sc7" width="187.5" height="318.75"></canvas>
</td>
</tr>
</table>
</div>

Related

AWS lambda cannot read dynamodb table and send mail using sendgrid

I want to send the mail using sendgrid in lambda function cannot send mail and read the dynamodb database but when I test in lambda console it shows null but when I test using locally it works
const moment = require("moment")();
const AWS = require("aws-sdk");
const sgMail = require("#sendgrid/mail");
AWS.config.getCredentials((err) => {
if (err) return err;
});
sgMail.setApiKey(
MYKEY
);
AWS.config.update({ region: "us-east-1" });
const dynamodb = new AWS.DynamoDB({ apiVersion: "2012-08-10" });
const ddb = new AWS.DynamoDB.DocumentClient();
exports.handler = async (event) => {
var currentDate = `${moment.date()}/${moment.month() + 1}`;
console.log(`EXECUTION DATE: ${currentDate}`);
// 1) Match with Dynamodb birthday table
var params = {
FilterExpression: "#cg = :data",
ExpressionAttributeNames: {
"#cg": "birthDate",
},
ExpressionAttributeValues: {
":data": currentDate,
},
TableName: "Users",
};
try {
// 2) Result
var result = ddb.scan(params).promise();
result
.then((items) => {
console.log("items");
if (items["Count"] > 0) {
items["Items"].map((user) => {
// Send mail
const msg = {
to: user.mail,
from: {
email: "test#example.com",
name: "Bhautik",
},
reply_to: {
email: "test#example.com",
name: "Bhautik",
},
subject: `Happy Birthday, ${user.name} 😊`,
text: "I hope you have a great day today...",
html:
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html data-editor-version="2" class="sg-campaigns" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1"> <meta http-equiv="X-UA-Compatible" content="IE=Edge"><!--[if (gte mso 9)|(IE)]> <xml> <o:OfficeDocumentSettings> <o:AllowPNG/> <o:PixelsPerInch>96</o:PixelsPerInch> </o:OfficeDocumentSettings> </xml><![endif]--><!--[if (gte mso 9)|(IE)]> <style type="text/css"> body{width: 600px;margin: 0 auto;}table{border-collapse: collapse;}table, td{mso-table-lspace: 0pt;mso-table-rspace: 0pt;}img{-ms-interpolation-mode: bicubic;}</style><![endif]--> <style type="text/css"> body, p, div{font-family: arial,helvetica,sans-serif; font-size: 14px;}body{color: #000000;}body a{color: #1188E6; text-decoration: none;}p{margin: 0; padding: 0;}table.wrapper{width:100% !important; table-layout: fixed; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: 100%; -moz-text-size-adjust: 100%; -ms-text-size-adjust: 100%;}img.max-width{max-width: 100% !important;}.column.of-2{width: 50%;}.column.of-3{width: 33.333%;}.column.of-4{width: 25%;}#media screen and (max-width:480px){.preheader .rightColumnContent, .footer .rightColumnContent{text-align: left !important;}.preheader .rightColumnContent div, .preheader .rightColumnContent span, .footer .rightColumnContent div, .footer .rightColumnContent span{text-align: left !important;}.preheader .rightColumnContent, .preheader .leftColumnContent{font-size: 80% !important; padding: 5px 0;}table.wrapper-mobile{width: 100% !important; table-layout: fixed;}img.max-width{height: auto !important; max-width: 100% !important;}a.bulletproof-button{display: block !important; width: auto !important; font-size: 80%; padding-left: 0 !important; padding-right: 0 !important;}.columns{width: 100% !important;}.column{display: block !important; width: 100% !important; padding-left: 0 !important; padding-right: 0 !important; margin-left: 0 !important; margin-right: 0 !important;}.social-icon-column{display: inline-block !important;}}</style> </head> <body> <center class="wrapper" data-link-color="#1188E6" data-body-style="font-size:14px; font-family:arial,helvetica,sans-serif; color:#000000; background-color:#FFFFFF;"> <div class="webkit"> <table cellpadding="0" cellspacing="0" border="0" width="100%" class="wrapper" bgcolor="#FFFFFF"> <tr> <td valign="top" bgcolor="#FFFFFF" width="100%"> <table width="100%" role="content-container" class="outer" align="center" cellpadding="0" cellspacing="0" border="0"> <tr> <td width="100%"> <table width="100%" cellpadding="0" cellspacing="0" border="0"> <tr> <td><!--[if mso]> <center> <table><tr><td width="600"><![endif]--> <table width="100%" cellpadding="0" cellspacing="0" border="0" style="width:100%; max-width:600px;" align="center"> <tr> <td role="modules-container" style="padding:0px 0px 0px 0px; color:#000000; text-align:left;" bgcolor="#FFFFFF" width="100%" align="left"><table class="module preheader preheader-hide" role="module" data-type="preheader" border="0" cellpadding="0" cellspacing="0" width="100%" style="display: none !important; mso-hide: all; visibility: hidden; opacity: 0; color: transparent; height: 0; width: 0;"> <tr> <td role="module-content"> <p>I hope you have a great day today...</p></td></tr></table><table class="wrapper" role="module" data-type="image" border="0" cellpadding="0" cellspacing="0" width="100%" style="table-layout: fixed;" data-muid="64efa4d4-043b-4982-a412-9d010d10b043"> <tbody> <tr> <td style="font-size:6px; line-height:10px; padding:0px 0px 0px 0px;" valign="top" align="center"> <img class="max-width" border="0" style="display:block; color:#000000; text-decoration:none; font-family:Helvetica, arial, sans-serif; font-size:16px;" width="512" alt="" data-proportionally-constrained="true" data-responsive="false" src="http://cdn.mcauto-images-production.sendgrid.net/82cf15c98221d9d9/1cf0943b-5037-4305-bd81-551fb7d3e346/512x496.png" height="496"> </td></tr></tbody> </table></td></tr></table><!--[if mso]> </td></tr></table> </center><![endif]--> </td></tr></table> </td></tr></table> </td></tr></table> </div></center> </body> </html>',
};
sgMail
.send(msg)
.then((res) => {
console.log("mail sent!!");
})
.catch((err) => {
console.log(err);
return `Error: ${err}`;
});
});
}
})
.catch((err) => {
console.log(err);
return `Error: ${err}`;
});
} catch (e) {
console.log(e);
return `Error: ${e}`;
}
};
Here is my steps in index.js
1) Fetch today date using momentjs
2) Scan the items whose birthDate is equal to today date
3) Send mail using sendgrid mail API.
Solved using fetched items put into Promise.all()
const moment = require("moment")();
const AWS = require("aws-sdk");
const sgMail = require("#sendgrid/mail");
AWS.config.getCredentials((err) => {
if (err) return err;
});
sgMail.setApiKey(
MyKey
);
AWS.config.update({ region: "us-east-1" });
const dynamodb = new AWS.DynamoDB({ apiVersion: "2012-08-10" });
const ddb = new AWS.DynamoDB.DocumentClient();
exports.handler = async (event) => {
var currentDate = `${moment.date()}/${moment.month() + 1}`;
console.log(`EXECUTION DATE: ${currentDate}`);
// 1) Match with Dynamodb birthday table
var params = {
FilterExpression: "#cg = :data",
ExpressionAttributeNames: {
"#cg": "birthDate",
},
ExpressionAttributeValues: {
":data": currentDate,
},
TableName: "Users",
};
try {
// 2) Result
var result = await ddb.scan(params).promise();
if(result.Count > 0) {
console.log(`Today Birthdays: ${result.Count}`);
let final = await Promise.all(
result.Items.map(async (user) => {
console.log(`Sending mail to ${user.mail}`);
const msg = {
to: user.mail,
from: {
email: "someone#example.com",
name: "Bhautik",
},
reply_to: {
email: "someone#example.com",
name: "Bhautik",
},
subject: `Happy Birthday, ${user.name} 😊`,
text: "I hope you have a great day today...",
html:
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html data-editor-version="2" class="sg-campaigns" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1"> <meta http-equiv="X-UA-Compatible" content="IE=Edge"><!--[if (gte mso 9)|(IE)]> <xml> <o:OfficeDocumentSettings> <o:AllowPNG/> <o:PixelsPerInch>96</o:PixelsPerInch> </o:OfficeDocumentSettings> </xml><![endif]--><!--[if (gte mso 9)|(IE)]> <style type="text/css"> body{width: 600px;margin: 0 auto;}table{border-collapse: collapse;}table, td{mso-table-lspace: 0pt;mso-table-rspace: 0pt;}img{-ms-interpolation-mode: bicubic;}</style><![endif]--> <style type="text/css"> body, p, div{font-family: arial,helvetica,sans-serif; font-size: 14px;}body{color: #000000;}body a{color: #1188E6; text-decoration: none;}p{margin: 0; padding: 0;}table.wrapper{width:100% !important; table-layout: fixed; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: 100%; -moz-text-size-adjust: 100%; -ms-text-size-adjust: 100%;}img.max-width{max-width: 100% !important;}.column.of-2{width: 50%;}.column.of-3{width: 33.333%;}.column.of-4{width: 25%;}#media screen and (max-width:480px){.preheader .rightColumnContent, .footer .rightColumnContent{text-align: left !important;}.preheader .rightColumnContent div, .preheader .rightColumnContent span, .footer .rightColumnContent div, .footer .rightColumnContent span{text-align: left !important;}.preheader .rightColumnContent, .preheader .leftColumnContent{font-size: 80% !important; padding: 5px 0;}table.wrapper-mobile{width: 100% !important; table-layout: fixed;}img.max-width{height: auto !important; max-width: 100% !important;}a.bulletproof-button{display: block !important; width: auto !important; font-size: 80%; padding-left: 0 !important; padding-right: 0 !important;}.columns{width: 100% !important;}.column{display: block !important; width: 100% !important; padding-left: 0 !important; padding-right: 0 !important; margin-left: 0 !important; margin-right: 0 !important;}.social-icon-column{display: inline-block !important;}}</style> </head> <body> <center class="wrapper" data-link-color="#1188E6" data-body-style="font-size:14px; font-family:arial,helvetica,sans-serif; color:#000000; background-color:#FFFFFF;"> <div class="webkit"> <table cellpadding="0" cellspacing="0" border="0" width="100%" class="wrapper" bgcolor="#FFFFFF"> <tr> <td valign="top" bgcolor="#FFFFFF" width="100%"> <table width="100%" role="content-container" class="outer" align="center" cellpadding="0" cellspacing="0" border="0"> <tr> <td width="100%"> <table width="100%" cellpadding="0" cellspacing="0" border="0"> <tr> <td><!--[if mso]> <center> <table><tr><td width="600"><![endif]--> <table width="100%" cellpadding="0" cellspacing="0" border="0" style="width:100%; max-width:600px;" align="center"> <tr> <td role="modules-container" style="padding:0px 0px 0px 0px; color:#000000; text-align:left;" bgcolor="#FFFFFF" width="100%" align="left"><table class="module preheader preheader-hide" role="module" data-type="preheader" border="0" cellpadding="0" cellspacing="0" width="100%" style="display: none !important; mso-hide: all; visibility: hidden; opacity: 0; color: transparent; height: 0; width: 0;"> <tr> <td role="module-content"> <p>I hope you have a great day today...</p></td></tr></table><table class="wrapper" role="module" data-type="image" border="0" cellpadding="0" cellspacing="0" width="100%" style="table-layout: fixed;" data-muid="64efa4d4-043b-4982-a412-9d010d10b043"> <tbody> <tr> <td style="font-size:6px; line-height:10px; padding:0px 0px 0px 0px;" valign="top" align="center"> <img class="max-width" border="0" style="display:block; color:#000000; text-decoration:none; font-family:Helvetica, arial, sans-serif; font-size:16px;" width="512" alt="" data-proportionally-constrained="true" data-responsive="false" src="http://cdn.mcauto-images-production.sendgrid.net/82cf15c98221d9d9/1cf0943b-5037-4305-bd81-551fb7d3e346/512x496.png" height="496"> </td></tr></tbody> </table></td></tr></table><!--[if mso]> </td></tr></table> </center><![endif]--> </td></tr></table> </td></tr></table> </td></tr></table> </div></center> </body> </html>',
};
await sgMail.send(msg);
})
);
}
} catch (e) {
console.log(e);
return `Error: ${e}`;
}
};

How add, delete, edit and save functions will work on multiple tables in HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Bootstrap Table with Add and Delete Row Feature</title>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Roboto|Varela+Round|Open+Sans"
/>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/icon?family=Material+Icons"
/>
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<style type="text/css">
body {
color: #404e67;
background: #f5f7fa;
font-family: "Open Sans", sans-serif;
}
.table-wrapper {
width: 700px;
margin: 30px auto;
background: #fff;
padding: 20px;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
}
.table-title {
padding-bottom: 10px;
margin: 0 0 10px;
}
.table-title h2 {
margin: 6px 0 0;
font-size: 22px;
}
.table-title .add-new {
float: right;
height: 30px;
font-weight: bold;
font-size: 12px;
text-shadow: none;
min-width: 100px;
border-radius: 50px;
line-height: 13px;
}
.table-title .add-new i {
margin-right: 4px;
}
table.table {
table-layout: fixed;
}
table.table tr th,
table.table tr td {
border-color: #e9e9e9;
}
table.table th i {
font-size: 13px;
margin: 0 5px;
cursor: pointer;
}
table.table th:last-child {
width: 100px;
}
table.table td a {
cursor: pointer;
display: inline-block;
margin: 0 5px;
min-width: 24px;
}
table.table td a.add {
color: #27c46b;
}
table.table td a.edit {
color: #ffc107;
}
table.table td a.delete {
color: #e34724;
}
table.table td i {
font-size: 19px;
}
table.table td a.add i {
font-size: 24px;
margin-right: -1px;
position: relative;
top: 3px;
}
table.table .form-control {
height: 32px;
line-height: 32px;
box-shadow: none;
border-radius: 2px;
}
table.table .form-control.error {
border-color: #f50000;
}
table.table td .add {
display: none;
}
</style>
<script type="text/javascript">
$(document).ready(function () {
$('[data-toggle="tooltip"]').tooltip();
var actions = $("table td:last-child").html();
// Append table with add row form on add new button click
$(".add-new").click(function () {
$(this).attr("disabled", "disabled");
var index = $("table tbody tr:last-child").index();
var row =
"<tr>" +
'<td><input type="text" class="form-control" name="current shift" id="cur_shft"></td>' +
'<td><input type="text" class="form-control" name="name current" id="n_curr"></td>' +
'<td><input type="text" class="form-control" name="shift handedover" id="shft_hndover"></td>' +
'<td><input type="text" class="form-control" name="name next" id="n_next"></td>' +
'<td><input type="text" class="form-control" name="time" id="shft_time"></td>' +
"<td>" +
actions +
"</td>" +
"</tr>";
$("table").append(row);
$("table tbody tr")
.eq(index + 1)
.find(".add, .edit")
.toggle();
$('[data-toggle="tooltip"]').tooltip();
});
// Add row on add button click
$(document).on("click", ".add", function () {
var empty = false;
var input = $(this).parents("tr").find('input[type="text"]');
input.each(function () {
if (!$(this).val()) {
$(this).addClass("error");
empty = true;
} else {
$(this).removeClass("error");
}
});
$(this).parents("tr").find(".error").first().focus();
if (!empty) {
input.each(function () {
$(this).parent("td").html($(this).val());
});
$(this).parents("tr").find(".add, .edit").toggle();
$(".add-new").removeAttr("disabled");
}
});
// Edit row on edit button click
$(document).on("click", ".edit", function () {
$(this)
.parents("tr")
.find("td:not(:last-child)")
.each(function () {
$(this).html(
'<input type="text" class="form-control" value="' +
$(this).text() +
'">'
);
});
$(this).parents("tr").find(".add, .edit").toggle();
$(".add-new").attr("disabled", "disabled");
});
// Delete row on delete button click
$(document).on("click", ".delete", function () {
$(this).parents("tr").remove();
$(".add-new").removeAttr("disabled");
});
});
</script>
</head>
<body>
<div class="container">
<div class="table-wrapper">
<div class="table-title">
<div class="row">
<div class="col-sm-8">
<h2><b>Shift Information</b></h2>
</div>
<div class="col-sm-4">
<button type="button" class="btn btn-info add-new">
<i class="fa fa-plus"></i> Add New
</button>
</div>
</div>
</div>
<table class="table table-bordered">
<thead>
<tr>
<th>Current Shift</th>
<th>Associates in Current Shift</th>
<th>Shift Handedover to</th>
<th>Associates in Next shift</th>
<th>Shift Handover time</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td>First</td>
<td>Chandu</td>
<td>Second</td>
<td>Venkata</td>
<td>15:30</td>
<td>
<a class="add" title="Add" data-toggle="tooltip"
><i class="material-icons"></i></a
>
<a class="edit" title="Edit" data-toggle="tooltip"
><i class="material-icons"></i></a
>
<a class="delete" title="Delete" data-toggle="tooltip"
><i class="material-icons"></i></a
>
</td>
</tr>
<tr>
<td>Second</td>
<td>Venkata</td>
<td>Third</td>
<td>Mallikharjuna</td>
<td>23:00</td>
<td>
<a class="add" title="Add" data-toggle="tooltip"
><i class="material-icons"></i></a
>
<a class="edit" title="Edit" data-toggle="tooltip"
><i class="material-icons"></i></a
>
<a class="delete" title="Delete" data-toggle="tooltip"
><i class="material-icons"></i></a
>
</td>
</tr>
<tr>
<td>Third</td>
<td>Mallikharjuna</td>
<td>First</td>
<td>Saikiran</td>
<td>06:30</td>
<td>
<a class="add" title="Add" data-toggle="tooltip"
><i class="material-icons"></i></a
>
<a class="edit" title="Edit" data-toggle="tooltip"
><i class="material-icons"></i></a
>
<a class="delete" title="Delete" data-toggle="tooltip"
><i class="material-icons"></i></a
>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>
I have created 6 html tables. I have written JS script for add, delete, edit and save functions. Now if i click on the add button for one table, the row is getting added 6 times to all tables. Please help on how to resolve this. Above example code is one such table and I just cloned the table to 5 other html files. I just changed the row column names

Slick Carousel with stays vertical and is not responsive/clicking?

So, I have a project that I've taken on that already has a slick carousel, not familiar with drupal or bootstrap, but from what I can see the current follows documentation. The carousel is triggered upon the breakpoint (as confirmed by the carousel arrows that appear at the breakpoint), However the carousel is not horizontal and the arrows do not work. Please advise.
app.js
explore: function explore() {
$('.explore-carousel').slick({
autoplay:true,
mobileFirst:true,
infinite: false,
dots: false,
slidesToShow: 2,
slidesToScroll: 1,
prevArrow: $('.explore-prev'),
nextArrow: $('.explore-next'),
responsive: [{
breakpoint: 500,
settings: {
slidesToShow: 1
}
}]
});
},
exploreResize: function exploreResize(carousel) {
// https://github.com/kenwheeler/slick/issues/3282
$(window).on('load resize orientationchange', function () {
$(carousel).each(function () {
var $carousel = $(this);
if ($(window).width() > 768) {
if ($carousel.hasClass('slick-initialized')) {
$carousel.slick('unslick');
}
} else {
if (!$carousel.hasClass('slick-initialized')) {
CB.carousel.explore(carousel);
}
}
});
});
},
explore.twig
<section class="explore">
<a class="explore-prev"><img src="../lib/img/icon-carousel-arrow-left.svg"></a>
<a class="explore-next"><img src="../lib/img/icon-carousel-arrow-right.svg"></a>
<div class="explore-carousel grid-x grid-container align-center">
{% for block in entry.exploreMatrix.all() %}
{% set image = block.icon.one() %}
{% set link = block.linkUrl.one() %}
{% set length = loop.length %}
{% set col = 12/length %}
<div class="cell small-12 large-{{ col ? col : 4 }}">
<a class="explore--link" href={{ link.url }}>
<div class="outline">
<img class="explore-image" src="{{ image ? image.url : '' }}">
<div class="hover--container">
<div class="hr"></div>
<h3 class="hover--text">{{ block.linkText }}<span class="button-icon"> {% include 'includes/svg/cta-arrow' %}</span></h3>
</div>
</div>
</a>
</div>
{% endfor %}
</section>
css
.explore {
margin-top: 80px;
#include mq($small) {
margin-top: 0;
}
position: relative;
.explore-prev {
#extend .PrevArrow;
}
.explore-next {
#extend .NextArrow;
}
.explore-carousel {
display: flex;
#include h-padding(rem-calc(50));
// padding-left: rem-calc(50);
// padding-right: rem-calc(50);
#include mq($medium) {
// padding-left: initial;
// padding-right: initial;
#include h-padding(initial);
}
.explore--link {
width: 100%;
}
.outline {
position: relative;
width: rem-calc(250);
border-radius:50%;
transition: all .3s;
margin: 0 auto;
#include spacer(50px, 50px);
&.hover {
background: $offWhite;
}
#include mq($medium) {
width: rem-calc(300);
}
.hover--container {
transition: all .3s;
position: absolute;
left: 0;
right: 0;
margin: 0 auto;
bottom: 5%;
text-align: center;
opacity: 0;
.hover--text {
margin-top:rem-calc(10);
font-size: rem-calc(22);
color: $clay;
letter-spacing: -1px;
}
}
.explore--image {
width: rem-calc(250);
margin: 0 auto;
#include mq($medium) {
width: rem-calc(300);
}
}
}
.hover {
.hover--container {
transition: all .3s;
opacity: 1;
}
}
}
}
Not sure about the 'not horizontal' issue, but i recommend you to remove all css and run slick carousel in a sandbox. When done, add your CSS code.
CSS overrides can be painfull with slick.
About the arrows, i guess you need to register as string HTML markup. Like this:
prevArrow:'<div> my custom prev arrow </div>'

node.js + socket.io + recursively adding replies

I've cobbled together a web page to control an Onkyo receiver via its serial port using parts of several diverse examples I found mostly on stackexchange. It works well, but I've run into the problem highlighted by #user568109 in the first link below where I think I have "initialized connection eventlisteners from within your routes" instead of globally. (Each time the web page is refreshed, the number of replies sent increments by one.) The problem is I can't see how to do initialize it globally. I tried removing the function:
io.sockets.on('connection', function (socket) {......}
but leaving the ....... part, as was done successfully in the second link below, but that didn't work for my case. Is there a simple fix? I'm a complete novice to node and javascript so I'm hoping it is obvious to someone.
Apart from the additional replies each time the web page is refreshed, it works well. (Apart from initializing the on off switch, the radio buttons and volume slider get initialed correctly, but I'll try to address that once I've sorted this sockets thing out).
Thanks!
Socket.io emits duplicate data after browser refresh
node.js + socket.io - duplicate websocket writes?
Here's the code snippet:
var express = require('express');
app = express();
server = require('http').createServer(app);
io = require('socket.io').listen(server);
var SerialPort = require("serialport")
var serialPort = new SerialPort("/dev/ttyUSB0", {
baudRate: 9600,
dataBits: 8,
parity: 'none',
stopBits: 1
}
);
server.listen(8080);
app.use(express.static('public'));
io.sockets.on('connection', function (socket) {
socket.on('toOnkyo', function (data) {
paramVal = data.value;
var buf = new Buffer(16);
buf.write(paramVal, "utf-8");
serialPort.write(buf);
io.sockets.emit('toOnkyo', {value: paramVal});
});
serialPort.on('data', function(data) {
io.sockets.emit('onkyoReply', {value: data.toString().substr(0,7)});
});
});
console.log("running");
body {
text-align: center;
margin-top: 50px;
background: #50D0A0;
}
input[type=range]{
-webkit-appearance: none;
width: 80%;
}
input[type=range]::-webkit-slider-runnable-track {
height: 10px;
background: #ddd;
border: none;
border-radius: 3px;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
border: none;
height: 32px;
width: 32px;
border-radius: 50%;
background: goldenrod;
margin-top: -12px;
}
input[type=range]:focus {
outline: none;
}
input[type=range]:focus::-webkit-slider-runnable-track {
background: #ccc;
}
.radioLeft
{
text-align:left;
}
.onoffswitch {
position: relative; width: 90px;
-webkit-user-select:none; -moz-user-select:none; -ms-user-select: none;
}
.onoffswitch-checkbox {
display: none;
}
.onoffswitch-label {
display: block; overflow: hidden; cursor: pointer;
border: 2px solid #999999; border-radius: 20px;
}
.onoffswitch-inner {
display: block; width: 200%; margin-left: -100%;
transition: margin 0.3s ease-in 0s;
}
.onoffswitch-inner:before, .onoffswitch-inner:after {
display: block; float: left; width: 50%; height: 30px; padding: 0; line-height: 30px;
font-size: 14px; color: white; font-family: Trebuchet, Arial, sans-serif; font-weight: bold;
box-sizing: border-box;
}
.onoffswitch-inner:before {
content: "ON";
padding-left: 10px;
background-color: #34A7C1; color: #FFFFFF;
}
.onoffswitch-inner:after {
content: "OFF";
padding-right: 10px;
background-color: #EEEEEE; color: #999999;
text-align: right;
}
.onoffswitch-switch {
display: block; width: 18px; margin: 6px;
background: #FFFFFF;
position: absolute; top: 0; bottom: 0;
right: 56px;
border: 2px solid #999999; border-radius: 20px;
transition: all 0.3s ease-in 0s;
}
.onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-inner {
margin-left: 0;
}
.onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-switch {
right: 0px;
}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Onkyo Controller</title>
<meta name="viewport" content="width=400px" />
<script src="socket.io/socket.io.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
Sent: <span id="sliderVolText"></span><br>
Reply: <span id="replyTextHex"></span>
(Decimal: <span id="replyText10"></span>)<br>
Mode: <span id="modeText"></span><br>
PowerText: <span id="powerText"></span><br>
Power: <span id="power"></span><br>
onoffText: <span id="onoffText"></span><br>
onoff: <span id="onoff"></span>
<script>
function setCheckedValue(radioObj, newValue) {
if(!radioObj)
return;
var radioLength = radioObj.length;
if(radioLength == undefined) {
radioObj.checked = (radioObj.value == newValue.toString());
return;
}
for(var i = 0; i < radioLength; i++) {
radioObj[i].checked = false;
if(radioObj[i].value == newValue.toString()) {
radioObj[i].checked = true;
}
}
}
</script>
<form class="onoffswitch" >
<input type="checkbox" name="onoffswitch" class="onoffswitch-checkbox" id="myonoffswitch" onclick="showOnoff(checked)">
<label class="onoffswitch-label" for="myonoffswitch">
<span class="onoffswitch-inner"></span>
<span class="onoffswitch-switch"></span>
</label>
</form>
<form name="modeForm" method="get" action="" onsubmit="return false;">
<p> <label for="mode0"><input type="radio" value="0x00" name="modeForm" id="mode0" onclick="showMode(this.value)"> Stereo</label>
<label for="mode1"><input type="radio" value="0x01" name="modeForm" id="mode1" onclick="showMode(this.value)"> Direct</label>
<label for="mode2"><input type="radio" value="0x0C" name="modeForm" id="mode2" onclick="showMode(this.value)"> All Ch stereo</label>
<label for="mode3"><input type="radio" value="0x42" name="modeForm" id="mode3" onclick="showMode(this.value)"> THX Cinema</label>
<label for="mode4"><input type="radio" value="0x84" name="modeForm" id="mode4" onclick="showMode(this.value)"> PLllx THX Cinema</label>
<label for="mode5"><input type="radio" value="0x11" name="modeForm" id="mode5" onclick="showMode(this.value)"> Pure</label>
</form>
<form name="slideForm" method="get" action="" onsubmit="return false;">
<input type="range" id= "inputSlider" min="0" max="100" value="vol" step="1" oninput="showVolume(this.value)" />
</form>
<br><br>
<div class="results"></div>
<script type="text/javascript">
var socket = io.connect();
var ctrlType = "";
socket.on('toOnkyo', function (data) {
ctrlType = data.value.toString().substr(2,3);
if (ctrlType == "MVL" && !(data.value.toString().substr(5,4)=="QSTN")){
document.getElementById("inputSlider").value = parseInt(data.value.toString().substr(5,2),16);
document.getElementById("sliderVolText").innerHTML = data.value;
}
if (ctrlType == "LMD" && !(data.value.toString().substr(5,4)=="QSTN")){
document.getElementById("mode").value = parseInt(data.value.toString().substr(5,2),16);
document.getElementById("modeText").innerHTML = data.value;
}
if (ctrlType == "PWR" && !(data.value.toString().substr(5,4)=="QSTN") ){
document.getElementById("power").value = parseInt(data.value.toString().substr(5,2),16);
document.getElementById("powerText").innerHTML = data.value;
}
if (ctrlType == "PWR" && !(data.value.toString().substr(5,4)=="QSTN") ){
document.getElementById("onoff").value = parseInt(data.value.toString().substr(5,2),16);
document.getElementById("onoffText").innerHTML = data.value;
}
});
socket.on('onkyoReply', function (data) {
var done = false;
ctrlType = data.value.toString().substr(2,3);
document.getElementById("replyTextHex").innerHTML = data.value;
document.getElementById("replyText10").innerHTML = parseInt(data.value.toString().substr(5,2),16);
if (ctrlType == "LMD"){
setCheckedValue(document.forms['modeForm'].elements['modeForm'],"0x"+data.value.toString().substr(5,2));
}
if (ctrlType == "PWR"){
var val = parseInt(data.value.toString().substr(5,2),16);
setCheckedValue(document.forms['powerForm'].elements['powerForm'],"0x"+data.value.toString().substr(5,2));
}
if (ctrlType == "MVL" && done == false){
document.getElementById("inputSlider").value = parseInt(data.value.toString().substr(5,2),16);
document.querySelector('.results').innerHTML = parseInt(data.value.toString().substr(5,2),16);
done = true;
}
});
function showVolume(newValue) {
document.getElementById("sliderVolText").innerHTML="\!1MVL"+("0" + Number(newValue).toString(16)).slice(-2)+"\r\n";
socket.emit('toOnkyo', { value: "\!1MVL"+("0" + Number(newValue).toString(16)).slice(-2)+"\r\n" });
}
function showMode(newValue) {
document.getElementById("modeText").innerHTML="\!1LMD"+("0" + Number(newValue).toString(16)).slice(-2)+"\r\n";
socket.emit('toOnkyo', { value: "\!1LMD"+("0" + Number(newValue).toString(16)).slice(-2)+"\r\n" });
}
function showOnoff(newValue) {
document.getElementById("onoffText").innerHTML="\!1PWR"+("0" + Number(newValue).toString(16)).slice(-2)+"\r\n";
socket.emit('toOnkyo', { value: "\!1PWR"+("0" + Number(newValue).toString(16)).slice(-2)+"\r\n" });
}
socket.emit('toOnkyo', { value: "\!1PWRQSTN"+"\r\n" });
socket.emit('toOnkyo', { value: "\!1LMDQSTN"+"\r\n" });
socket.emit('toOnkyo', { value: "\!1MVLQSTN"+"\r\n" });
</script>
</body>
</html>
Found a solution based on Ian Wooten's blog:
http://www.ianwootten.co.uk/2011/07/04/maintaining-references-to-sockets-with-express-and-socket-io/
Great!
server.listen(8080);
app.use(express.static('public'));
var paramVal = 0;
var countRep = 0;
var countSend = 0;
var buf = new Buffer(16);
var global_socket;
io.sockets.on('connection', function (socket) {
global_socket = socket;
global_socket.on('toOnkyo', function (data) {
paramVal = data.value;
buf.write(paramVal, "utf-8");
serialPort.write(buf);
console.log(paramVal.toString().substr(0,7) + " (" + parseInt(paramVal.toString().substr(5,2),16) + ")\r\n");
global_socket.emit('toOnkyo', {value: paramVal});
console.log('new'+paramVal);
countSend=countSend+1;
console.log('count send '+ countSend);
});
});
serialPort.on('data', function(data) {
console.log('data received: ' + data.toString().substr(0,7) + " (" + parseInt(data.toString().substr(5,2),16) + ")");
global_socket.emit('onkyoReply', {value: data.toString().substr(0,7)});
countRep=countRep+1;
console.log('count '+ countRep);
});
console.log("running");

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