Related
I need the image in the both divs below to be in the same position even if the other div changes height or width. I have tried calculating top and left to % from px but still it is not working. I have also tried calculating the % of how big or small other div is and adding or removing the top and left to the image in other div and still no luck.
To check the issue, drag the image around inside the first div and click on submit. Now the image inside the bottom div should be in the same position as the above div, same top and left distance.
Please help. Thanks.
Here is the fiddle : https://jsfiddle.net/kashyap_s/gLdt62nh
var zoomLevel = 1;
$("#myimage").draggable({
start: function() {
},
stop: function() {
}
});
$('#save').click(function() {
var topcss = $('#myimage').css('top');
var leftcss = $('#myimage').css('left');
var transformcss = zoomLevel;
topcss = topcss.replace('px', '');
leftcss = leftcss.replace('px', '');
topcss = parseInt(topcss);
leftcss = parseInt(leftcss);
var parentWidth = $('#dragDiv').outerWidth()
var parentHeight = $('#dragDiv').outerHeight()
console.log('leftcss', leftcss, 'width', parentWidth)
console.log('topcss', topcss, 'height', parentHeight)
var percentLeft = leftcss / parentWidth * 100;
var percentTop = topcss / parentHeight * 100;
console.log('percentLeft', percentLeft, 'percentTop', percentTop)
transformcss = parseFloat(transformcss).toFixed(2);
var result = {
"top": topcss,
"left": leftcss,
'percentTop': percentTop,
'percentLeft': percentLeft,
'parentWidth': parentWidth,
'parentHeight': parentHeight,
"transform": "scale(" + transformcss + ")"
};
var output = JSON.stringify(result);
console.log('output', output)
$("#newimg").css({
'left': leftcss
});
$("#newimg").css({
'top': topcss
});
});
.transperentimage {
width: 497px;
height: 329px;
border: 1px solid black;
margin: 0 auto;
}
#bigimg {
width: 651px;
height: 431px;
border: 1px solid black;
margin: 0 auto;
}
img {
border: 2px solid red;
padding: 3px;
width: auto;
height: auto;
cursor: move;
max-height: 180px;
}
#newimg {
position: absolute;
max-height: 180px;
width: auto!important;
height: auto!important;
max-width: 100%!important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="transperentimage" id="dragDiv">
<img id="myimage" src="agent.png">
</div>
<button id="save">Save</button>
<div id="bigimg">
<img id="newimg" src="agent.png" />
</div>
$(function() {
$("#logo1").draggable({
containment: "parent",
drag: function() {
}
});
});
function setpos() {
var image1_w = $("#logo1").width();
var div1_w = $(".div1").width();
var image2_w = $("#logo2").width();
var div2_w = $(".div2").width();
var image1_h = $("#logo1").height();
var div1_h = $(".div1").height();
var image2_h = $("#logo2").height();
var div2_h = $(".div2").height();
var div1_aw = div1_w - image1_w;
var div2_aw = div2_w - image2_w;
var div1_ah = div1_h - image1_h;
var div2_ah = div2_h - image2_h;
var div
var xPos = $('#logo1').css('left');
var yPos = $('#logo1').css('top');
var ratio_w = parseFloat(div1_aw) / parseFloat(div2_aw);
var ratio_h = parseFloat(div1_ah) / parseFloat(div2_ah);
//let act = 1.39;
var div2_nw = parseFloat(xPos) / ratio_w;
var div2_nh = parseFloat(yPos) / ratio_h;
$("#posX").text('Div left:' + div2_nw);
$("#posA").text('Div Top:' + div2_nh);
$("#logo2").css({
'left': div2_nw,
'top': div2_nh
});
}
.div1 {
width: 497px;
height: 329px;
border: 1px solid black;
}
.div2 {
width: 651px;
height: 431px;
border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script
src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"
integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU="
crossorigin="anonymous"></script>
<p>Drag my logo.</p>
<div class="div1">
<img src="https://smteg.sefion.com/perfectmetal/assets/ui/sefion.jpg" style=" position: relative; left: 0px; top: 0px;" width="100" id="logo1">
</div>
<br>
<div class="div2">
<img style="position: relative;left: 0px;top: 0px" src="https://smteg.sefion.com/perfectmetal/assets/ui/sefion.jpg" width="100" id="logo2">
</div>
<br>
<button onclick="setpos();">
Save
</button>
<div id="posX">
</div>
<div id="posA">
</div>
<div id="posz">
</div>
<div id="posZ1">
</div>
Solved! check this out
HTML
<p>Drag my logo.</p>
<div class="div1">
<img src="https://smteg.sefion.com/perfectmetal/assets/ui/sefion.jpg" style=" position: relative; left: 0px; top: 0px;" width="100" id="logo1">
</div>
<br>
<div class="div2">
<img style="position: relative;left: 0px;top: 0px" src="https://smteg.sefion.com/perfectmetal/assets/ui/sefion.jpg" width="100" id="logo2">
</div>
<br>
<button onclick="setpos();">
Save
</button>
<div id="posX"></div>
<div id="posA"></div>
JS CODE
$( function() {
$( "#logo1" ).draggable(
{
containment: "parent",
drag: function() {
}
}
);
} );
function setpos()
{
var image1_w = $("#logo1").width();
var div1_w = $(".div1").width();
var image2_w = $("#logo2").width();
var div2_w = $(".div2").width();
var image1_h = $("#logo1").height();
var div1_h = $(".div1").height();
var image2_h = $("#logo2").height();
var div2_h = $(".div2").height();
var div1_aw = div1_w-image1_w;
var div2_aw = div2_w-image2_w;
var div1_ah = div1_h-image1_h;
var div2_ah = div2_h-image2_h;
var div
var xPos = $('#logo1').css('left');
var yPos = $('#logo1').css('top');
var ratio_w = parseFloat(div1_aw)/parseFloat(div2_aw);
var ratio_h = parseFloat(div1_ah)/parseFloat(div2_ah);
//let act = 1.39;
var div2_nw = parseFloat(xPos)/ratio_w;
var div2_nh = parseFloat(yPos)/ratio_h;
$("#posX").text('Div left:' + div2_nw);
$("#posA").text('Div Top:' + div2_nh);
$("#logo2").css({ 'left' : div2_nw, 'top' : div2_nh});
}
CSS
.div1{
width: 497px;
height: 329px;
border: 1px solid black;
}
.div2{
width: 651px;
height: 431px;
border: 1px solid black;
}
For your newimg, the parent must have a position that is relative. This way, the absolute positioning will be relative to the parent and not the body.
An element with position: absolute; is positioned relative to the nearest positioned ancestor (instead of positioned relative to the viewport, like fixed).
Consider the following code.
$(function() {
var zoomLevel = parseFloat(1 - ($("#dragDiv").outerWidth() / $("#bigimg").outerWidth()).toFixed(2));
function log(str) {
if ($(".log").length) {
$(".log").html(str);
} else {
$("<div>", {
class: "log"
}).html(str).appendTo("body");
}
}
function getPos(el) {
var par = $(el).parent();
var pos = {
top: parseInt($(el).css("top")),
left: parseInt($(el).css("left")),
zoom: "scale(" + (1 + zoomLevel) + ")",
parWidth: par.outerWidth(),
parHeight: par.outerHeight()
};
pos['perLeft'] = parseFloat((pos.left / pos.parWidth).toFixed(2)) * 100;
pos['perTop'] = parseFloat((pos.top / pos.parHeight).toFixed(2)) * 100;
return pos;
}
$("#myimage").draggable({
containment: "parent",
drag: function(e, ui) {
log("Left: " + ui.position.left + ", Top: " + ui.position.top);
},
start: function() {
// coordinates('#myimage');
},
stop: function() {
// coordinates('#myimage');
var p = getPos(this);
$(this).attr("title", JSON.stringify(p));
}
});
$('#save').click(function() {
var result = getPos($("#myimage"));
var output = JSON.stringify(result);
var nLeft = Math.round(result.perLeft * (1 + zoomLevel)) + "%";
var nTop = Math.round(result.perTop * (1 + zoomLevel)) + "%"
console.log(output, nLeft, nTop);
$("#newimg").css({
left: nLeft,
top: nTop
});
var p = getPos($("#newimg"));
$("#newimg").attr("title", JSON.stringify(p));
});
});
.transperentimage {
width: 497px;
height: 329px;
border: 1px solid black;
margin: 0 auto;
}
#bigimg {
width: 651px;
height: 431px;
border: 1px solid black;
margin: 0 auto;
position: relative;
}
img {
border: 2px solid red;
padding: 3px;
width: auto;
height: auto;
cursor: move;
/* max-width: 100%; */
max-height: 180px;
}
#newimg {
position: absolute;
max-height: 180px;
width: auto!important;
height: auto!important;
max-width: 100%!important;
}
.log {
font-size: 11px;
font-family: "Arial";
position: absolute;
top: 3px;
left: 3px
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div class="transperentimage" id="dragDiv">
<img id="myimage" src="https://i.imgur.com/4ILisqH.jpg">
</div>
<button id="save">Save</button>
<div id="bigimg">
<img id="newimg" src="https://i.imgur.com/4ILisqH.jpg" />
</div>
See More: https://www.w3schools.com/css/css_positioning.asp
Updated
Looking at it further, I am guessing that you might be trying to reposition the bigimg in relationship to myimage position. This requires scaling the percentage.
For example, if we move myimage to the far left, it will be at left: 247, and this is roughly 49% of 499px. 49% of 653 is around 319, and this would not place the image where we want it. We want it at 401.
bigimg is about 24% larger than dragDiv, so we need to scale our percentage. 49 * 1.24 = 60.74, round up to 61. 653 * .61 = 398.33 so better yet not perfect.
I am trying to solve problem with correct working of 2 buttons (I have called them btnleft and btnright). I will use them to change opacity/alpha channel for random color (for example hsl(x, y%, z%, 1) -> hsl(x, y%, z%, 0.8)).
a variable is for opacity value, btnleft is for changing opacity down and btnright for changing up. Main function alphaValue is not working when I click left/right button (and I do not see any error on WWW console).
HSLinStringAlpha is hsl(hue, saturation%, lumination%, opacity) notation.
Below I put my code (maybe too long, but working without opacity changing).
Thanks for any advice.
/* Nested functions with errors */
function colorChange() {
function randomColor() {
let Cmax = []; let Cmin = []; let Lum = []; let Delta = [];
let Hue = []; let Sat = [];
let HueAngle = Math.round(60 * Hue);
let SatInt = Math.round(100 * Sat);
let LumInt = Math.round(100 * Lum);
/* Here is probably some mistake (wrong method of made function?) */
function FullHSLCode() {
for (let i = 0; i < indexValue.length / 3; i++) {
HSLinString[i] = `hsl(${HueAngle[i]}, ${SatInt[i]}%, ${LumInt[i]}%)`;
}
return HSLinString;
}
FullHSLCode();
}
/* End of randomColor(), here I was tried to made closure */
randomColor();
var a = 1;
var HSLinStringAlpha = [`hsla(${HueAngle[0]}, ${SatInt[0]}%, ${LumInt[0]}%, ${a})`];
/* alphaValue() doesn't work after move it outside randomColor() function - WWW console shows that HueAngle, SatInt, LumInt variables aren't accessible */
function alphaValue(HSLinStringAlpha, HueAngle, SatInt, LumInt, a) {
if (this.id !== "btn1") {
//if(button1.onclick === true) {
if (this.id === "btnleft") {
a -= 0.05;
} else if (this.id === "btnright") {
a += 0.05;
}
HSLinStringAlpha.push(`hsla(${HueAngle[0]}, ${SatInt[0]}%, ${LumInt[0]}%, ${a})`);
HSLinStringAlpha.shift();
}
return HSLinStringAlpha;
}
alphaValue();
/*
let button1 = document.getElementById("btnleft");
let button2 = document.getElementById("btnright");
button1.disabled = false;
button2.disabled = false;
button1.addEventListener("click", alphaValue, false);
button2.addEventListener("click", alphaValue, false);
*/
}
to check which button is clicked you should not using
if (button1.onclick === true)
but use like
if (this.id === 'btnleft')
window.addEventListener("DOMContentLoaded", colorChange);
function colorChange() {
document.getElementById("btn1").addEventListener("click", randomColor, false);
function randomColor() {
let HEXColor = [];
let HSLColor = [];
let RGBinString = []; // defines color in rgb(num,num,num) style
let HEXinString = []; // defines color in hexadecimal style
let HSLinString = []; // defines color in hsl() style
/* Randomize r,g,b numbers of colors in rgb(num,num,num) style */
let indexValue = [];
let colorArray = [];
function RGBrandom() {
for(let j = 0; j <= 8; j++) {
indexValue[j] = Math.floor(Math.random() * 256);
colorArray.push(indexValue[j]);
}
for(i = 0; i < 3; i++) {
RGBinString[i] = `rgb(${indexValue[3*i]},${indexValue[3*i+1]},${indexValue[3*i+2]})`;
}
return RGBinString;
}
RGBrandom();
// Calculate hex code string from rgb code
function RGBtoHex(indexValue) {
const HEXcolorValue = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f"];
for(let i = 0; i < indexValue.length; i++) {
if(indexValue[i] <= 15) {
HEXColor.push(0, HEXcolorValue[indexValue[i]]);
}
else {
HEXColor.push(HEXcolorValue[Math.floor(indexValue[i] / 16)], HEXcolorValue[(indexValue[i]) % 16]);
}
}
return HEXColor;
}
let HEXFullColor = RGBtoHex(indexValue);
function FullHEXCode() {
for(let j = 0; j < HEXFullColor.length / 6; j++) {
HEXFullColor[j] = HEXFullColor.slice(6 * j, 6 * j + 6);
HEXinString[j] = HEXFullColor[j].join("");
HEXinString[j] = `#${HEXinString[j]}`;
}
return HEXinString;
}
FullHEXCode();
let RGBArray = [];
function RGBvalueChange() {
for(let j = 0; j <= 8; j++) {
/* for Red indexes (j = 0, 3, 6, etc.) */
if(j % 3 === 0) {
RGBArray.push(indexValue[j] / 255);
}
/* for Green indexes (j = 1, 4, 7, etc.) */
else if((j + 2) % 3 === 0) {
RGBArray.push(indexValue[j] / 255);
}
/* for Blue indexes (j = 2, 5, 8, etc.) */
else {
RGBArray.push(indexValue[j] / 255);
}
}
return RGBArray;
}
RGBvalueChange();
let Cmax = [];
let Cmin = [];
let Lum = [];
let Delta = [];
let Hue = [];
let Sat = [];
let HuePercent = [];
let SatInt = [];
let LumInt = [];
for(let i = 0; i < indexValue.length / 3; i++) {
Cmin.push(Math.min(RGBArray[3 * i], RGBArray[3 * i + 1], RGBArray[3 * i + 2])); // 3 values
Cmax.push(Math.max(RGBArray[3 * i], RGBArray[3 * i + 1], RGBArray[3 * i + 2])); // 3 values
Lum.push((Cmax[i] + Cmin[i]) / 2); // 3 values
Delta[i] = Cmax[i] - Cmin[i]; // 3 values
if(Delta[i] === 0) {
Hue.push(0); //Hue[i] === 0;
Sat.push(0); //Sat[i] === 0;
}
else {
// Hue dependance from other parameters
if(Cmax[i] === RGBArray[3 * i]) {
Hue.push(((RGBArray[3 * i + 1] - RGBArray[3 * i + 2]) / Delta[i] + (RGBArray[3 * i + 1] < RGBArray[3 * i + 2] ? 6 : 0)));
}
else if(Cmax[i] === RGBArray[3 * i + 1]) {
Hue.push((RGBArray[3 * i + 2] - RGBArray[3 * i]) / Delta[i] + 2);
}
else if(Cmax[i] === RGBArray[3 * i + 2]) {
Hue.push((RGBArray[3 * i] - RGBArray[3 * i + 1]) / Delta[i] + 4);
}
else {
Hue.push(0);
}
Sat[i] = Lum[i] > 0.5 ? (0.5 * Delta[i]) / (1 - Lum[i]) : Delta[i] / (2 * Lum[i]);
Sat.push(Sat[i]);
}
HuePercent[i] = Math.round(60 * Hue[i]);
SatInt[i] = Math.round(100 * Sat[i]);
LumInt[i] = Math.round(100 * Lum[i]);
}
function FullHSLCode() {
for(let j = 0; j < indexValue.length / 3; j++) {
HSLinString[j] = `hsl(${HuePercent[j]}, ${SatInt[j]}%, ${LumInt[j]}%)`;
}
return HSLinString;
}
FullHSLCode();
var a = 1;
let HSLinStringAlpha = [`hsl(${HuePercent[0]}, ${SatInt[0]}%, ${LumInt[0]}%, ${a})`];
let button1 = document.getElementById("btnleft");
let button2 = document.getElementById("btnright");
button1.disabled = false;
button2.disabled = false;
function alphaValue() {
if(this.id !== 'btn1') {
//if(button1.onclick === true) {
if(this.id === 'btnleft') {
a -= 0.05;
}
else {
a += 0.05;
}
//console.log(a)
HSLinStringAlpha[0] = [`hsl(${HuePercent[0]}, ${SatInt[0]}%, ${LumInt[0]}%, ${a})`];
//HSLinStringAlpha.shift();
}
console.log(HSLinStringAlpha[0][0])
return HSLinStringAlpha;
}
button1.addEventListener("click", alphaValue, false);
button2.addEventListener("click", alphaValue, false);
document.querySelector("p").innerHTML = [`${a} `, HSLinStringAlpha];
// 3 random colors in every element (circle)
document.getElementById("color1").value = HEXinString[0];
document.getElementById("color2").value = HEXinString[1];
document.getElementById("color3").value = HEXinString[2];
document.getElementById("color4").value = RGBinString[0];
document.getElementById("color5").value = RGBinString[1];
document.getElementById("color6").value = RGBinString[2];
document.getElementById("color7").value = HSLinStringAlpha[0];
document.getElementById("color8").value = HSLinString[1];
document.getElementById("color9").value = HSLinString[2];
box1.style.backgroundColor = HSLinStringAlpha[0];
box2.style.backgroundColor = HSLinStringAlpha[0];
box3.style.backgroundColor = HSLinStringAlpha[0];
}
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
height: 100vh;
width: 100vw;
background-color: lightgray;
position: absolute;
}
.bigbox {
min-height: 320px;
width: 630px;
position: absolute;
}
.box {
height: auto;
width: 33%;
margin: 0 0 10px;
background-color: lightgray;
display: block;
position: relative;
float: left;
}
.colorbox {
height: 150px;
width: 150px;
margin: 5px auto;
border-radius: 50%;
background-color: #234523;
display: block;
}
.text {
height: auto;
width: 100%;
display: block;
float: left;
}
.shape {
height: 1.75em;
width: calc(100% - 3px);
margin: 0 auto 5px;
font-size: 18px;
text-align: left;
border: gray solid 1px;
display: block;
}
p {
display: inline-block;
margin: 10px 5px;
float:right;
}
.arrowbox {
height: 100%;
width: 100%;
margin: 0 auto;
font-size: 20px;
display: block;
float: left;
}
.buttons {
height: 100%;
width: 40%;
margin: 10px auto;
display: block;
float: left;
}
.testbutton {
height: 100%;
width: 40%;
font-size: 20px;
display: block;
float: left;
}
.arrowbutton {
height: 100%;
width: 30%;
font-size: 20px;
display: block;
float: left;
}
.buttonbox {
height: 3.5em;
width: 100%;
font-size: 20px;
display: block;
clear: both;
}
#btn1 {
height: 100%;
width: 8.5em;
margin: 0 auto;
font-size: 20px;
display: block;
}
<div class="container">
<div class="bigbox">
<div id="box4" class="box">
<div id="box1" class="colorbox"></div>
<div class="text">
<input type="text" id="color1" class="shape" value="" size="12" maxlength="7" readonly="readonly" />
<input type="text" id="color4" class="shape" value="" size="12" maxlength="7" readonly="readonly" />
<input type="text" id="color7" class="shape" value="" size="12" maxlength="7" readonly="readonly" />
</div>
</div>
<div id="box5" class="box">
<div id="box2" class="colorbox"></div>
<div class="text">
<input type="text" id="color2" class="shape" value="" size="12" maxlength="15" readonly="readonly" />
<input type="text" id="color5" class="shape" value="" size="12" maxlength="15" readonly="readonly" />
<input type="text" id="color8" class="shape" value="" size="12" maxlength="15" readonly="readonly" />
</div>
</div>
<div id="box6" class="box">
<div id="box3" class="colorbox"></div>
<div class="text">
<input type="text" id="color3" class="shape" value="" size="12" maxlength="15" readonly="readonly" />
<input type="text" id="color6" class="shape" value="" size="12" maxlength="15" readonly="readonly" />
<input type="text" id="color9" class="shape" value="" size="12" maxlength="15" readonly="readonly" />
</div>
</div>
<div class="buttonbox">
<div class="arrowbox">
<p>Yes, it's almost something what I'm looking for, but...Yeah you need some extra options - click "TEST" button below.</p>
<div class="buttons">
<button id="btnleft" class="arrowbutton">◄</button>
<button id="btncenter" class="testbutton">RESET</button>
<button id="btnright" class="arrowbutton">►</button>
</div>
</div>
<button id="btn1" onclick="colorChange();">Click for color !!!</button>
</div>
</div>
</div>
I have a function which counts the number of line breaks in a div, depending on the width of the window. While the functions works fine when placed in the $(window).on('resize') function, it does not work when put in $(document).ready() function. I want it to work right on page load, and also window resize, how do I support both?
JSFiddle
Javascript/jQuery:
// functions called in both document.ready() and window.resize
$(document).ready(function(){
var lineCount = getLineCount();
postItems(lineCount);
$('.answer').text("Ready");
});
$(window).on('resize', function(){
var lineCount = getLineCount();
postItems(lineCount);
$('.answer').text("Number of lines: " + lineCount);
});
// calculates the amount of lines required to hold the items
function getLineCount() {
var lineWidth = $('.line').width();
var itemWidthSum = 0;
var lineCount=1;
$('.item').each(function(index, element) {
if((lineWidth - itemWidthSum) > ($(element).outerWidth())) {
itemWidthSum = itemWidthSum + $(element).outerWidth();
} else {
lineCount++;
itemWidthSum = $(element).outerWidth();
}
});
return lineCount;
}
// overlays rows for the amount of linebreaks
function postItems(lineCount){
var container = $('<div />');;
for(var i = 1; i <= lineCount; i++) {
container.append('<div class="line">' + i + '</div>');
}
$('.line-wrap').html(container);
}
You'll see at the start of the page, it incorrectly shows 17 lines, and then once you resize it will show the correct amount.
The issue lies in the first line of getLineCount(). Originally you had
var lineWidth = $('.line').width();
but no elements with the class "line" exist yet on your page (since they get added in your postItems() method. I changed it to
var lineWidth = $(".container").width();
instead, and now your code should be working. Snippet posted below:
$(document).ready(function(){
var lineCount = getLineCount();
postItems(lineCount);
$('.answer').text("Ready");
});
$(window).on('resize', function(){
var lineCount = getLineCount();
postItems(lineCount);
$('.answer').text("Number of lines: " + lineCount);
});
// calculates the amount of lines required to hold the items
function getLineCount() {
var lineWidth = $('.container').width();
var itemWidthSum = 0;
var lineCount=1;
$('.item').each(function(index, element) {
if((lineWidth - itemWidthSum) > ($(element).outerWidth())) {
itemWidthSum = itemWidthSum + $(element).outerWidth();
} else {
lineCount++;
itemWidthSum = $(element).outerWidth();
}
});
return lineCount;
}
// overlays rows for the amount of linebreaks
function postItems(lineCount){
var container = $('<div />');;
for(var i = 1; i <= lineCount; i++) {
container.append('<div class="line">' + i + '</div>');
}
$('.line-wrap').html(container);
}
body {
text-align:center;
}
.answer {
position: fixed;
left: 0;
bottom: 0;
}
.container {
position: relative;
width: 50%;
margin: 0 auto;
border: 1px solid #e8e8e8;
display: inline-block;
}
.item {
height: 50px;
padding:0 10px;
background-color: #aef2bd;
float: left;
opacity:0.2;
white-space: nowrap;
}
.line-wrap {
position: absolute;
border: 1px solid red;
width: 100%;
height: 100%;
top:0; left: 0;
}
.line {
height: 50px;
width: 100%;
background-color: blue;
opacity:0.5;
color: white;
transition: all 0.5s ease;
}
.line:hover {
background-color: yellow;
color: #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="item-wrap">
<div class="item">Computer Science</div>
<div class="item">Language</div>
<div class="item">Marketing</div>
<div class="item">Biology</div>
<div class="item">Computer Science</div>
<div class="item">Language</div>
<div class="item">Marketing</div>
<div class="item">Biology</div>
<div class="item">Computer Science</div>
<div class="item">Language</div>
<div class="item">Marketing</div>
<div class="item">Biology</div>
<div class="item">Computer Science</div>
<div class="item">Language</div>
<div class="item">Marketing</div>
<div class="item">Biology</div>
</div>
<div class="line-wrap">
</div>
</div>
<h1 class="answer"></h1>
I have created a calculator I use for counting carbs for my 7 y/o type 1 diabetic but as I add more values into my array the page is getting too long.
I'm looking for a way to start with a single select for the food name then select the weight and it calculates the carbs. Then have a button to dynamically add another row to the form in order to select a new food item and calculate the results of any further additions.
This is my functional code base:
<html><head>
<meta name = "viewport" content = "initial-scale = 1.0, user-scalable = no">
<title>Carb Calculator</title>
<style>
#container{width: 200px; margin: 0 auto;}
label { font-size:20px; display: inline-block; width: 45%; text-align: right;}
input[type="text"][disabled] {width: 12%; background-color: white; color: black; font-weight: bolder;}
input[type="button"] {}
select {width: 15%}
</style></head>
<body>
<script language="javascript" type="text/javascript">
var myArray = [['Banana',0.1428571429], ['Blackberry',0.1], ['Blueberry',0.1418918919], ['Carrots',0.09836065574], ['Cantaloupe',0.08], ['Cherry Tomato',0.05882352941], ['Cucumber',0.03653846154], ['Green apple',0.1373626374], ['Honeydew',0.09], ['Pear',0.15], ['Raspberry',0.12], ['Plum',0.11], ['Strawberry',0.075], ['Watermelon',0.075]];
function reset(){
var t=0;
for (var i=0; i<myArray.length; i++) {
var v = "val"+i;
document.calc.elements[v].value=0;
}
}
function calculate(){
var t=0;
var tt=0;
for (var i=0; i<myArray.length; i++) {
var v = "val"+i;
var a = "answer"+i;
if(isNaN(parseInt(document.calc.elements[v].value))) {
//document.calc.elements[a].value="";
} else {
tt=(parseInt(document.calc.elements[v].value))* myArray[i][1];
document.calc.elements[a].value=tt.toFixed(1);
t+=tt;
}
}
document.calc.answerTot.value=(t).toFixed(1)
}
document.write("<form name=\"calc\" action=\"post\">");
for (var i=0; i<myArray.length; i++) {
var vv = "val"+i;
var aa = "answer"+i;
document.write("<label>"+myArray[i][0]+":</label> <select name=\""+ vv +"\" onchange=\"calculate()\" >");
for (var j=0; j<301; j++) {
document.write("<option value=" +j+ ">" +j+ "</option>");
}
document.write("</select><input type=text name=" +aa+ " size=5 placeholder=\"Carbs\" disabled><br>");
}
document.write("<br><label for=\"answerTot\">Total carbs: </label> <input type=text name=answerTot size=5 disabled></br></br> <div style=\"text-align:center\"> <input type=button value=Calculate onClick=\"calculate()\"></br></br><input type=button value=Reset onClick=\"reset()\"></div>");
</script></body></html>
Hello there and welcome to StackOverflow!
Your code required a bit of rework and questions like that (more like a task than a question) aren't usually very successful around here.
Having said that, I wrote something that will hopefully help you, the nice thing about it being that if you want to add new types of food you'll only need to add them in the array and the js will take care of it.
Careful with the approximation to 1 digit though, you might lose some carbs in the calculation. Also, please check your carbs, see if I haven't modified anything by mistake.
var myArray = [
['Food', 0],
['Banana', 0.1428571429],
['Blackberry', 0.1],
['Blueberry', 0.1418918919],
['Carrots', 0.09836065574],
['Cantaloupe', 0.08],
['Cherry Tomato', 0.05882352941],
['Cucumber', 0.03653846154],
['Green apple', 0.1373626374],
['Honeydew', 0.09],
['Pear', 0.15],
['Raspberry', 0.12],
['Plum', 0.11],
['Strawberry', 0.075],
['Watermelon', 0.075]
];
function reset() {
var inputs = document.getElementById("calculatorForm").getElementsByTagName("input");
for (var i = 0; i < inputs.length; i++) {
inputs[i].value = "";
}
document.getElementById("answerTot").value = "";
}
function calculate() {
var t = 0;
var tt = 0;
var inputs = document.getElementById("calculatorForm").getElementsByTagName("input");
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].disabled == false) {
if (parseInt(inputs[i].value) > 0) {
tt = (parseInt(inputs[i].value) * getValue(inputs[i].previousSibling.value));
t = +t + +tt;
inputs[i].nextSibling.value = tt.toFixed(1);
}
}
}
console.log(t.toFixed(1));
document.getElementById("answerTot").value = (t).toFixed(1)
}
function add() {
document.getElementById("calculatorForm");
var o = document.createElement("option");
var sel = document.createElement("select");
var inp = document.createElement("input");
var close = document.createElement("span");
var entry = document.createElement("div");
var carbs = document.createElement("input");
carbs.disabled = true;
carbs.className = "result";
entry.className = "entry";
close.className = "remove";
close.innerHTML = "Remove";
for (i = 0; i < myArray.length; i++) {
o = document.createElement("option");
o.value = myArray[i][0];
o.innerHTML = myArray[i][0];
sel.appendChild(o);
}
close.addEventListener("click", function() {
this.parentElement.remove();
calculate();
})
entry.appendChild(sel);
entry.appendChild(inp);
entry.appendChild(carbs);
entry.appendChild(close);
document.getElementById("calculatorForm").appendChild(entry);
}
function getValue(food) {
for (var i = 0; i < myArray.length; i++) {
if (myArray[i][0] == food) return myArray[i][1];
}
}
function getIndex(food) {
for (var i = 0; i < myArray.length; i++) {
if (myArray[i][0] == food) return i;
}
}
window.onload = function() {
add();
}
* {
box-sizing: border-box;
}
#container {
width: 200px;
margin: 0 auto;
}
input[type="text"][disabled] {
outline: none;
border: 1px solid gray;
background-color: white;
color: black;
font-weight: bolder;
}
input[type="button"] {}
select {
width: 15%
}
#calculatorForm {
width: 300px;
margin: auto;
text-align: center;
}
#calculatorForm .entry > * {
width: 140px;
height: 20px;
margin: 5px;
}
#calculatorForm .entry > span {
font-size: 11px;
line-height: 20px;
cursor: pointer;
}
#calculatorForm .entry > .result {
width: 240px;
}
.control {
width: 300px;
margin: auto;
text-align: center;
}
.control>label {
font-size: 11px;
width: 290px;
display: block;
margin: auto;
text-align: left;
margin-bottom: -5px;
}
.control>input {
display: block;
width: 290px;
padding: 5px;
margin: 5px auto;
}
<form name="calc" action="post" id="calculatorForm">
</form>
<div style="text-align:center" class="control">
<label for="answerTot">Total carbs </label>
<input type=text id=answerTot size=5 disabled>
<input type=button value="Add Food" onClick="add()">
<input type=button value=Calculate onClick="calculate()">
<input type=button value=Reset onClick="reset()">
</div>
If anyone wants to see the result, this is what I ended up with. I added a couple event listeners and made the weight value a select rather than an input. Thanks again #Paul for the assistance this is exactly what I was trying to accomplish!
<html>
<head>
<meta name = "viewport" content = "initial-scale = 1.0, user-scalable = no">
<title>Carb Calculator</title>
<style>
{
box-sizing: border-box;
}
#container {
width: 200px;
margin: 0 auto;
}
input[type="text"][disabled] {
outline: none;
border: 1px solid gray;
background-color: white;
color: black;
font-weight: bolder;
}
input[type="button"] {}
select {
width: 15%
}
#calculatorForm {
width: 300px;
margin: auto;
text-align: center;
}
#calculatorForm .entry > * {
width: 145px;
height: 20px;
margin: 2px;
}
#calculatorForm .entry > span {
font-size: 11px;
line-height: 20px;
cursor: pointer;
}
#calculatorForm .entry > .result {
width: 50px;
}
.control {
width: 300px;
margin: auto;
text-align: center;
}
.control>label {
font-size: 11px;
width: 290px;
display: block;
margin: auto;
text-align: left;
margin-bottom: -5px;
}
.control>input {
display: block;
width: 290px;
padding: 5px;
margin: 5px auto;
}
</style>
</head>
<body>
<script language="javascript" type="text/javascript">
var myArray = [
['Food', 0],
['Banana', 0.1428571429],
['Blackberry', 0.1],
['Blueberry', 0.1418918919],
['Carrots', 0.09836065574],
['Cantaloupe', 0.08],
['Cherry Tomato', 0.05882352941],
['Cucumber', 0.03653846154],
['Green apple', 0.1373626374],
['Honeydew', 0.09],
['Pear', 0.15],
['Raspberry', 0.12],
['Plum', 0.11],
['Strawberry', 0.075],
['Watermelon', 0.075]
];
function reset() {
var inputs = document.getElementById("calculatorForm").getElementsByClassName("result");
for (var i = 0; i < inputs.length; i++) {
inputs[i].value = 0;
}
document.getElementById("answerTot").value = "";
}
function calculate() {
var t = 0;
var tt = 0;
var inputs = document.getElementById("calculatorForm").getElementsByClassName("result");
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].disabled == false) {
if (parseInt(inputs[i].value) >= 0) {
tt = (parseInt(inputs[i].value) * getValue(inputs[i].previousSibling.value));
t = +t + +tt;
inputs[i].nextSibling.value = tt.toFixed(1);
}
}
}
console.log(t.toFixed(1));
document.getElementById("answerTot").value = (t).toFixed(1)
}
function add() {
document.getElementById("calculatorForm");
var o = document.createElement("option");
var sel = document.createElement("select");
var inpu = document.createElement("select");
var close = document.createElement("span");
var entry = document.createElement("div");
var carbs = document.createElement("input");
carbs.disabled = true;
carbs.className = "result";
inpu.className = "result";
entry.className = "entry";
close.className = "remove";
close.innerHTML = "Remove";
for (i = 0; i < myArray.length; i++) {
o = document.createElement("option");
o.value = myArray[i][0];
o.innerHTML = myArray[i][0];
sel.appendChild(o);
}
for (var j=0; j<301; j++){
inpu.options[inpu.options.length]=new Option(j,j)
}
close.addEventListener("click", function() {
this.parentElement.remove();
calculate();
})
inpu.addEventListener("change", function() {
calculate();
})
sel.addEventListener("change", function() {
calculate();
})
entry.appendChild(sel);
entry.appendChild(inpu);
entry.appendChild(carbs);
entry.appendChild(close);
document.getElementById("calculatorForm").appendChild(entry);
}
function getValue(food) {
for (var i = 0; i < myArray.length; i++) {
if (myArray[i][0] == food) return myArray[i][1];
}
}
function getIndex(food) {
for (var i = 0; i < myArray.length; i++) {
if (myArray[i][0] == food) return i;
}
}
window.onload = function() {
add();
}
</script>
<form name="calc" action="post" id="calculatorForm"></form>
<div style="text-align:center" class="control"><br>
<label for="answerTot">Total carbs </label>
<input type=text id=answerTot size=5 disabled>
<input type=button value="Add Food" onClick="add()">
<input type=button value=Calculate onClick="calculate()">
<input type=button value=Reset onClick="reset()">
</div>
</body></html>
Here is a small application I came up with that could also suit your needs.
It consists of five files that should be located in the same directory.
Best of health for your child!
Features include:
adding and removing of new food types
adding and removing food to/from multiple lists
changing, increasing and decreasing count of fooditems in lists
manage (add,remove,rename) multiple lists
save and load data in your browser locally
export and import data through a text area to save your data externally.
layout support for both big screen and handheld devices
myCarbCalculator.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Carb Calculator</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link rel="stylesheet" href="myCarbCalculator.css"></link>
<link rel="stylesheet" media="screen" href="myCarbCalculator-Screen.css"></link>
<link rel="stylesheet" media="handheld" href="myCarbCalculator-Handheld.css"></link>
<script type="text/javascript" src="myCarbCalculator.js"></script>
</head>
<body onload="init();">
<div id="root">
<div id="header">
<button id="btnSaveSettings">save Settings</button>
<button id="btnLoadSettings">load Settings</button>
<button id="btnImportSettings">import Settings</button>
<button id="btnExportSettings">export Settings</button>
<button id="btnResetSettings">reset Settings</button>
</div>
<div id="center">
<div id="content-main">
<div id="c_foodSelector">
<label for="selFoodSelector">select a type of food</label>
<select id="selFoodSelector"></select>
<button id="btnAddSelectedFoodToList">Add Food to List</button>
</div>
<div id="c_foodTable">
<div id="c_foodTableOptions">
<input id="p_foodTableName" value="Your List of Food Items"/>
<button id="btnRenameFoodTable">rename List</button>
<button id="btnNewFoodTable">new List</button>
</div>
<table id="foodTable" class="fill-width"></table>
</div>
</div>
<div id="content-additional">
<div id="c_results">
<label for="inputResultCarbs">Carbs Total</label>
<input id="inputResultCarbs" readonly="readonly"/>
</div/>
<div id="c_foodTableSelection">
<table id="foodTableSelection" class="fill-width"></table>
</div>
<div id="c_output">
<h3>Import/Export</h3>
<textarea id="p_output" class="fill-width"></textarea>
</div/>
</div>
</div>
<div id="footer">
<label for="p_newFoodName">Food Name</label><input id="p_newFoodName"/>
<label for="p_newFoodCarbs">Carb Value</label><input id="p_newFoodCarbs"/>
<button id="btnNewFood">add a new type of food</button>
<button id="btnDeleteSelectedFood">delete Selected type of food</button>
</div>
</div>
</body>
</html>
myCarbCalculator.js
var SAVEID = 'carbCalculatorSettings';
function MyCarbCalculator(){
var self = this;
this.settings = null;
this.initSettings = function(){
self.settings = {
'activeFoodList' : 'default',
'foodData' : {},
'foodList' : {
'default' : {
'label' : 'Your List of Food Items',
'list' : {},
'dateCreated' : '',
'dateChanged' : '',
'notes' : 'This is the default Food List'
}
}
};
};
this.clearContents = function(element){
while (element.firstChild) {
element.removeChild(element.firstChild);
}
};
this.formatDate = function(timestamp){
if(timestamp != ""){
var date = new Date(timestamp);
var monthNames = [
"January", "February", "March",
"April", "May", "June", "July",
"August", "September", "October",
"November", "December"
];
var day = date.getDate();
var monthIndex = date.getMonth();
var year = date.getFullYear();
var hours = date.getHours();
var minutes = date.getMinutes();
var seconds = date.getSeconds();
return day + ' ' + monthNames[monthIndex] + ' ' + year + ' ' + hours + ':'+ minutes + ':'+ seconds;
}
return "---";
};
//////////////////////////////////////////////////////////////////
// Load and Save Data
//////////////////////////////////////////////////////////////////
this.resetSettings = function(){
self.initSettings();
self.updateView();
};
this.saveSettings = function(){
localStorage.setItem(SAVEID,JSON.stringify(self.settings));
};
this.loadSettings = function(){
var saveData = localStorage.getItem(SAVEID);
if(saveData != null && saveData.length > 0){
self.settings = JSON.parse(localStorage.getItem(SAVEID));
self.updateView();
}
else{
self.initSettings();
}
};
this.importSettings = function(){
localStorage.setItem(SAVEID,document.getElementById('p_output').value);
self.loadSettings();
};
this.exportSettings = function(){
document.getElementById('p_output').value = localStorage.getItem(SAVEID);
};
//////////////////////////////////////////////////////////////////
// Manage Food Data
//////////////////////////////////////////////////////////////////
this.updateView = function(){
self.updateFoodSelector();
self.updateFoodTable();
self.updateFoodTableSelection();
self.updateResult();
};
//////////////////////////////////////////////////////////////////
// Manage Food Data
//////////////////////////////////////////////////////////////////
this.newFood = function(){
var name = document.getElementById('p_newFoodName').value;
var carbs = document.getElementById('p_newFoodCarbs').value;
var id = Date.now();
self.settings.foodData[id] = {'name':name,'carbs':carbs};
self.updateFoodSelector();
};
this.removeSelectedFoodData = function(){
var foodSelector = document.getElementById('selFoodSelector');
var foodDataId = foodSelector.options[foodSelector.selectedIndex].value;
delete self.settings.foodData[foodDataId];
self.updateFoodSelector();
}
this.updateFoodSelector = function(){
var foodSelector = document.getElementById('selFoodSelector');
self.clearContents(foodSelector);
for(id in self.settings.foodData){
var food = self.settings.foodData[id];
var item = document.createElement("option");
item.value = id;
item.innerHTML = food.name + " (" + food.carbs + ")";
foodSelector.appendChild(item);
}
};
//////////////////////////////////////////////////////////////////
// Manage current Food Table
//////////////////////////////////////////////////////////////////
this.addSelectedFoodToTable = function(){
var activeFoodListId = self.settings.activeFoodList;
var foodList = self.settings.foodList[activeFoodListId];
var foodSelector = document.getElementById('selFoodSelector');
var selectedFoodId = foodSelector.options[foodSelector.selectedIndex].value;
var foodData = self.settings.foodData[selectedFoodId];
var foodItem = {'name':foodData.name,'carbs':foodData.carbs,'count':1};
foodList.list[Date.now()] = foodItem;
foodList.dateChanged = Date.now();
self.updateView();
};
this.updateFoodCount = function(id,value){
var activeFoodListId = self.settings.activeFoodList;
var foodList = self.settings.foodList[activeFoodListId];
foodList.list[id].count = value;
foodList.dateChanged = Date.now();
self.updateView();
};
this.removeFoodItem = function(id){
var activeFoodListId = self.settings.activeFoodList;
var foodList = self.settings.foodList[activeFoodListId];
delete foodList.list[id];
foodList.dateChanged = Date.now();
self.updateView();
};
this.updateFoodTable = function(){
var activeFoodListId = self.settings.activeFoodList;
var foodList = self.settings.foodList[activeFoodListId];
// update the List Name
var foodTableNameElement = document.getElementById('p_foodTableName');
foodTableNameElement.value = foodList.label;
// update the List itself
var foodTable = document.getElementById('foodTable');
self.clearContents(foodTable);
// create the Table Header
var row = document.createElement("tr");
foodTable.innerHTML =
"<tr><th>Name</th><th>Carbs/unit</th><th></th><th>Count</th><th></th></tr>";
for(id in foodList.list){
// create a table structure
var row = document.createElement("tr");
var elm1 = document.createElement("td");
var elm2 = document.createElement("td");
var elm3 = document.createElement("td");
var elm4 = document.createElement("td");
var elm5 = document.createElement("td");
var elm6 = document.createElement("td");
row.appendChild(elm1);
row.appendChild(elm2);
row.appendChild(elm3);
row.appendChild(elm4);
row.appendChild(elm5);
row.appendChild(elm6);
foodTable.appendChild(row);
// create input fields
var food = foodList.list[id];
var inputFoodId = document.createElement("input");
inputFoodId.id = "food-id-" + id;
inputFoodId.type = "hidden";
inputFoodId.value = id;
var inputFoodName = document.createElement("input");
inputFoodName.id = "food-name-" + id;
inputFoodName.setAttribute("readonly","readonly");
inputFoodName.value = food.name;
var inputFoodCarbs = document.createElement("input");
inputFoodCarbs.id = "food-carbs-" + id;
inputFoodCarbs.setAttribute("readonly","readonly");
inputFoodCarbs.style.width = "3em";
inputFoodCarbs.value = food.carbs;
var inputFoodCount = document.createElement("input");
inputFoodCount.id = "food-count-" + id;
inputFoodCount.setAttribute("data-id",id);
inputFoodCount.style.width = "3em";
inputFoodCount.value = food.count;
inputFoodCount.addEventListener("change",function(event){
var inputFoodCount = event.currentTarget;
var id = inputFoodCount.getAttribute("data-id");
var count = inputFoodCount.value;
self.updateFoodCount(id,count);
});
var btnDeleteFoodItem = document.createElement("button");
btnDeleteFoodItem.innerHTML = "remove";
btnDeleteFoodItem.setAttribute("data-id",id);
btnDeleteFoodItem.addEventListener("click",function(event){
var btnDeleteFoodItem = event.currentTarget;
var id = btnDeleteFoodItem.getAttribute("data-id");
self.removeFoodItem(id);
});
var btnCountUp = document.createElement("button");
btnCountUp.innerHTML = "+";
btnCountUp.setAttribute("data-id",id);
btnCountUp.addEventListener("click",function(event){
var id = event.currentTarget.getAttribute("data-id");
var inputFoodCount = document.getElementById("food-count-"+id);
inputFoodCount.value = ++ inputFoodCount.value;
self.updateFoodCount(id,inputFoodCount.value);
});
var btnCountDown = document.createElement("button");
btnCountDown.innerHTML = "-";
btnCountDown.setAttribute("data-id",id);
btnCountDown.addEventListener("click",function(event){
var id = event.currentTarget.getAttribute("data-id");
var inputFoodCount = document.getElementById("food-count-"+id);
inputFoodCount.value = -- inputFoodCount.value;
self.updateFoodCount(id,inputFoodCount.value);
});
// append input fields to the table row
elm1.appendChild(inputFoodId); // this one is invisible anyway
elm1.appendChild(inputFoodName);
elm2.appendChild(inputFoodCarbs);
elm3.appendChild(btnCountDown);
elm4.appendChild(inputFoodCount);
elm5.appendChild(btnCountUp);
elm6.appendChild(btnDeleteFoodItem);
}
};
//////////////////////////////////////////////////////////////////
// Calculate Results
//////////////////////////////////////////////////////////////////
this.calculateCarbsForList = function(listId){
var foodListData = self.settings.foodList[listId].list;
var total = 0;
for(id in foodListData){
var item = foodListData[id];
total = total + (item.carbs * item.count);
}
return total;
};
this.updateResult = function(){
var activeFoodListId = self.settings.activeFoodList;
var foodList = self.settings.foodList[activeFoodListId];
var inputResultCarbs = document.getElementById("inputResultCarbs");
inputResultCarbs.value = self.calculateCarbsForList(activeFoodListId);
};
//////////////////////////////////////////////////////////////////
// Food Table Handling
//////////////////////////////////////////////////////////////////
this.renameFoodTable = function(){
var activeTableId = self.settings.activeFoodList;
var foodList = self.settings.foodList[activeTableId];
var newName = document.getElementById('p_foodTableName').value;
foodList.label = newName;
foodList.dateChanged = Date.now();
self.updateView();
};
this.newFoodTable = function(){
var newTableName = document.getElementById('p_foodTableName').value;
var date = Date.now();
self.settings.foodList[date] = {
'label' : newTableName,
'list' : {},
'dateCreated' : date,
'dateChanged' : date,
'notes' : ''
}
self.settings.activeFoodList = date;
self.updateView();
};
this.updateFoodTableSelection = function(){
var foodTableSelection = document.getElementById('foodTableSelection');
self.clearContents(foodTableSelection);
var foodTableLists = self.settings.foodList;
foodTableSelection.innerHTML =
"<tr><th>Name</th><th>last Change</th><th>Carbs</th><th></th><th></th></tr>";
for(var tableId in foodTableLists){
var foodTable = foodTableLists[tableId];
var row = document.createElement("tr");
if(tableId == self.settings.activeFoodList){
row.classList.add("active");
}
var cell1 = document.createElement("td");
var cell2 = document.createElement("td");
var cell3 = document.createElement("td");
var cell4 = document.createElement("td");
var cell5 = document.createElement("td");
cell1.innerHTML = foodTable.label;
cell1.style.cursor = "help";
cell1.title = foodTable.notes;
cell2.innerHTML = self.formatDate(foodTable.dateChanged);
cell2.title = "created: " + self.formatDate(foodTable.dateCreated);
cell3.innerHTML = self.calculateCarbsForList(tableId);
var btnSelectFoodTable = document.createElement("button");
if(tableId == self.settings.activeFoodList)btnSelectFoodTable.disabled = 'disabled';
btnSelectFoodTable.innerHTML = "select";
btnSelectFoodTable.setAttribute("data-tableId",tableId);
btnSelectFoodTable.addEventListener("click",function(event){
var button = event.currentTarget;
self.settings.activeFoodList = button.getAttribute("data-tableId");
self.updateView();
});
cell4.appendChild(btnSelectFoodTable);
var btnDeleteFoodTable = document.createElement("button");
if(tableId == 'default')btnDeleteFoodTable.disabled = 'disabled';
btnDeleteFoodTable.innerHTML = "delete";
btnDeleteFoodTable.setAttribute("data-tableId",tableId);
btnDeleteFoodTable.addEventListener("click",function(event){
var button = event.currentTarget;
var tableId = button.getAttribute("data-tableId");
if(self.settings.activeFoodList = tableId){
self.settings.activeFoodList = "default";
};
delete self.settings.foodList[tableId];
self.updateView();
});
cell5.appendChild(btnDeleteFoodTable);
row.appendChild(cell1);
row.appendChild(cell2);
row.appendChild(cell3);
row.appendChild(cell4);
row.appendChild(cell5);
foodTableSelection.appendChild(row);
}
};
//////////////////////////////////////////////////////////////////
// Add global Events
//////////////////////////////////////////////////////////////////
document.getElementById("btnNewFood").addEventListener("click",this.newFood);
document.getElementById("btnSaveSettings").addEventListener("click",this.saveSettings);
document.getElementById("btnLoadSettings").addEventListener("click",this.loadSettings);
document.getElementById("btnResetSettings").addEventListener("click",this.resetSettings);
document.getElementById("btnImportSettings").addEventListener("click",this.importSettings);
document.getElementById("btnExportSettings").addEventListener("click",this.exportSettings);
document.getElementById("btnDeleteSelectedFood").addEventListener("click",this.removeSelectedFoodData);
document.getElementById("btnAddSelectedFoodToList").addEventListener("click",this.addSelectedFoodToTable);
document.getElementById("btnRenameFoodTable").addEventListener("click",this.renameFoodTable);
document.getElementById("btnNewFoodTable").addEventListener("click",this.newFoodTable);
//////////////////////////////////////////////////////////////////
// Initialize the Data on screen
//////////////////////////////////////////////////////////////////
self.loadSettings();
}
function init(){
var carCalculator = new MyCarbCalculator();
}
myCarbCalculator.css
body,html{
height:100%;
}
/* dont show borders on input fields if read only */
input:-moz-read-only {
border : none;
}
input:read-only {
border : none;
}
/* spacing elements out */
th{
text-align:left;
}
label,input,button,select{
white-space:nowrap;
margin-right: 1em;
}
button{
height:2.5em;
}
#c_results,#c_foodSelector,#c_output,#footer,#header{
padding:1em;
}
/* make result stand out */
#c_results #inputResultCarbs{
font-size: 2em;
color: #882222;
width:4em;
}
#c_results label[for="inputResultCarbs"]{
font-size: 1em;
padding-top:1em;
}
.fill-width{
width:100%;
}
table#foodTableSelection > tr.active{
background-color:yellow;
}
myCarbCalculator-Screen.css
#root{
display:flex;
flex-direction:column;
height:100%;
}
#header{
display:flex;
flex-direction:row;
border-bottom: 1px solid black;
}
#footer{
display:flex;
flex-direction.row;
border-top: 1px solid black;
}
#center{
flex: 1 0;
display:flex;
flex-direction:row;
}
#content-main{
flex: 1 0 auto;
display:flex;
flex-direction: column;
}
#c_foodSelector{
border-bottom: 1px solid black;
}
#c_foodTable{
}
#content-additional{
flex: 0 1 30%;
display:flex;
flex-direction: column;
border-left: 1px solid black;
}
#c_results{
flex: 1 0 auto;
border-bottom: 1px solid black;
}
#c_foodTableSelection{
flex: 1 0 auto;
border-bottom: 1px solid black;
}
#c_output{
flex: 0 1 50%;
}
myCarbCalculator-Handheld.css
#root{
display:flex;
flex-direction:column;
height:100%;
}
#header{
display:flex;
flex-direction:column;
border-top: 1px solid black;
order: 3;
}
#footer{
display:flex;
flex-direction:column;
border-top: 1px solid black;
order: 2;
}
#center{
flex: 1 0;
display:flex;
flex-direction:column;
order: 1;
}
#content-main{
display:flex;
flex-direction: column;
}
#c_foodSelector{
display:flex;
flex-direction:column;
border-bottom: 1px solid black;
}
#c_foodTable{
border-bottom: 1px solid black;
}
#content-additional{
display:flex;
flex-direction: column;
}
#c_results{
flex: 1 0 auto;
border-bottom: 1px solid black;
}
#c_foodTableSelection{
flex: 1 0 auto;
border-bottom: 1px solid black;
}
#c_output{
flex: 0 1 50%;
}
/*******************************************
ADDITONAL STYLES ONLY FOR HANDHELD LAYOUT
*******************************************/
/* spacing out vertically */
label,input,button,select{
margin-bottom: 0.5em;
}
input[id^="food-name"]{
width:4em;
}
#header:before,#footer:before{
text-align:center;
font-size:1em;
font-weight:bold;
margin-bottom:0.5em;
}
#header:before{
content:'Options';
}
#footer:before{
content:'Foodtypes';
}
Technical Notes:
I am using pure Javascript and css. Some styles might not be compatible with older browsers like Internet Explorer prior to Edge.
Saving of data is handled through the browsers local storage.
Import and Export is handled through plain text in "Javascript Object Notation" (JSON).
The Application itself is written as a Javascript Class e.g. Function named MyCarbCalculator which is created and initialized through the bodies onload event and an init() function.
With this example application I'm trying to show how to use Javascript in a structured (pseudo object oriented) way and the power and flexibility of event listeners and unnamed functions e.g. the use of functions as parameters.
Also I am using CSS media descriptors to create a flexible layout that can be customized for both handheld devices and big screens. This is mostly done through the "flexbox" style which allows for very fluid layouts and offers great control over the positioning of elements.
I'm creating a memory game for my web assignment at uni and I am stuck on how to get my animation playing on match on top of the cards that match.
At the moment, I have been able to get the animation to play on click of the memory_board div, but only works once.
So question 1 - How do you get the animation to work every time you click on the Memory_board div.(It only works once atm, and have to refresh the page to play it again)
My code for the animation to work is:
.sprite {
width:96px;
height:96px;
position: relative;
margin:15px;
}
.toon{
background: url(explode.png);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type='text/javascript' src='jquery.animateSprite.js'></script>
<script>//sparkle effect: http://www.rigzsoft.co.uk/how-to-implement-animated-sprite-sheets-on-a-web-page/
$(document).ready(function(){
$("#memory_board").click(function animation(){
$(".toon").animateSprite({
columns: 10,
totalFrames: 50,
duration: 1000,
});
});
});
</script>
<body>
<div class = "grid_10">
<div id="memory_board"></div>
<script>newBoard();</script>
<div style="position: relative; height: 110px;">
<div class="sprite toon"></div>
</div>
</div>
</body>
Question 2 - How will I place this animation over top of each card?
The layout of the board is by float in the memory_boarddiv, where the images are in an array and called up in the function tile.innerHTML = '<img src="' + val + '.png"/>';
Here is the full coding for the board:
div#memory_board{
background: -webkit-radial-gradient(#FFF, #CC99FF); /* For Safari 5.1 to 6.0 */
background: -o-radial-gradient(#FFF, #CC99FF); /* For Opera 11.1 to 12.0 */
background: -moz-radial-gradient(#FFF, #CC99FF); /* For Firefox 3.6 to 15 */
background: radial-gradient(#FFF, #CC99FF); /* Standard syntax (must be last) */
border:#FF0066 10px ridge;
width:510px;
height:405px;
padding:24px;
}
div#memory_board > div{
background:url(tile_background.png) no-repeat;
border:#000 1px solid;
width:45px;
height:45px;
float:left;
margin:7px;
padding:20px;
cursor:pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<title>Memory Card Game</title>
<meta http-equiv="Content-type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="reset.css" />
<link rel="stylesheet" type="text/css" href="text.css" />
<link rel="stylesheet" type="text/css" href="960.css" />
<link rel="stylesheet" type="text/css" href="mystyles.css" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type='text/javascript' src='jquery.animateSprite.js'></script>
<script> //developphp.com tutorial
var memory_array = ['A','A','B','B','C','C','D','D','E','E','F','F','G','G','H','H','I','I','J','J'];
var memory_values = [];
var memory_tile_ids = [];
var tiles_flipped = 0;
var turns = 0
var matches = 0
Array.prototype.memory_tile_shuffle = function(){
var i = this.length, j, temp;
while(--i > 0){
j = Math.floor(Math.random() * (i+1));
temp = this[j];
this[j] = this[i];
this[i] = temp;
}
}
function newBoard(){
tiles_flipped = 0;
var output = '';
memory_array.memory_tile_shuffle();
for(var i = 0; i < memory_array.length; i++){
output += '<div id="tile_'+i+'" onclick="memoryFlipTile(this,\''+memory_array[i]+'\')"></div>';
}
document.getElementById('memory_board').innerHTML = output;
//fade in
$(document).ready(function () {
$('#memory_board > div').hide().fadeIn(1500).delay(6000)
});
resetTime();
turns = 0;
document.getElementById('Count').innerHTML = 0;
matches = 0;
document.getElementById('matchNumber').innerHTML = 0;
}
function memoryFlipTile(tile,val){
startTimer();
playClick();
if(tile.innerHTML == "" && memory_values.length < 2){
tile.style.background = '#FFF';
tile.innerHTML = '<img src="' + val + '.png"/>';
if(memory_values.length == 0){
memory_values.push(val);
memory_tile_ids.push(tile.id);
} else if(memory_values.length == 1){
memory_values.push(val);
memory_tile_ids.push(tile.id);
if(memory_values[0] == memory_values[1]){
tiles_flipped += 2;
//sound
playMatch();
//animation
//number of clicks
turns = turns + 1;
document.getElementById("Count").innerHTML = turns;
//number of matches
matches = matches + 1;
document.getElementById("matchNumber").innerHTML = matches;
// Clear both arrays
memory_values = [];
memory_tile_ids = [];
// Check to see if the whole board is cleared
if(tiles_flipped == memory_array.length){
playEnd();
Alert.render("Congratulations! Board Cleared");
//resetTime()
//stopCount();
document.getElementById('memory_board').innerHTML = "";
newBoard();
}
} else {
function flipBack(){
// Flip the 2 tiles back over
var tile_1 = document.getElementById(memory_tile_ids[0]);
var tile_2 = document.getElementById(memory_tile_ids[1]);
tile_1.style.background = 'url(tile_background.png) no-repeat';
tile_1.innerHTML = "";
tile_2.style.background = 'url(tile_background.png) no-repeat';
tile_2.innerHTML = "";
//number of clicks
turns = turns + 1;
document.getElementById("Count").innerHTML = turns;
//clickNumber()
// Clear both arrays
memory_values = [];
memory_tile_ids = [];
}
setTimeout(flipBack, 700);
}
}
}
}
</script>
<body>
<div class = "grid_10">
<div id="memory_board"></div>
<script>newBoard();</script>
<div style="position: relative; height: 110px;">
<div class="sprite toon"></div>
</div>
</div>
</body>
Question 3 - How will I get to play this animation only on match, on top of the cards that have matched.
I'm guessing this is done by putting it into the memoryFlipTile function under the //animation where the sound and match number change upon a match found :
function memoryFlipTile(tile,val){
startTimer();
playClick();
if(tile.innerHTML == "" && memory_values.length < 2){
tile.style.background = '#FFF';
tile.innerHTML = '<img src="' + val + '.png"/>';
if(memory_values.length == 0){
memory_values.push(val);
memory_tile_ids.push(tile.id);
} else if(memory_values.length == 1){
memory_values.push(val);
memory_tile_ids.push(tile.id);
if(memory_values[0] == memory_values[1]){
tiles_flipped += 2;
//sound
playMatch();
//animation
//number of clicks
turns = turns + 1;
document.getElementById("Count").innerHTML = turns;
//number of matches
matches = matches + 1;
document.getElementById("matchNumber").innerHTML = matches;
// Clear both arrays
memory_values = [];
memory_tile_ids = [];
}
In case these snippets are confusing and you want the whole picture, here is the full script:
body{
background:#FFF;
font-family: Cooper Black;
}
h1{
font-family: Cooper Black;
text-align: center;
font-size: 64px;
color: #FF0066;
}
footer{
height: 150px;
background: -webkit-linear-gradient(#99CCFF, #FFF); /* For Safari 5.1 to 6.0 */
background: -o-linear-gradient(#99CCFF, #FFF); /* For Opera 11.1 to 12.0 */
background: -moz-linear-gradient(#99CCFF, #FFF); /* For Firefox 3.6 to 15 */
background: linear-gradient(#99CCFF, #FFF); /* Standard syntax (must be last) */
}
div#memory_board{
background: -webkit-radial-gradient(#FFF, #CC99FF); /* For Safari 5.1 to 6.0 */
background: -o-radial-gradient(#FFF, #CC99FF); /* For Opera 11.1 to 12.0 */
background: -moz-radial-gradient(#FFF, #CC99FF); /* For Firefox 3.6 to 15 */
background: radial-gradient(#FFF, #CC99FF); /* Standard syntax (must be last) */
border:#FF0066 10px ridge;
width:510px;
height:405px;
padding:24px;
}
div#memory_board > div{
background:url(tile_background.png) no-repeat;
border:#000 1px solid;
width:45px;
height:45px;
float:left;
margin:7px;
padding:20px;
cursor:pointer;
}
alert{
background: #FF0066;
}
button{
font-family: Cooper Black;
font-size: 20px;
color: #FF0066;
background: #5CE62E;
border: #C2E0FF 2px outset;
border-radius: 25px;
padding: 10px;
cursor: pointer;
}
input#txt{
background: yellow;
color: #FF0066;
font-family: Times New Roman;
font-size: 84px;
height: 150px;
width: 150px;
border-radius: 100%;
text-align: center;
border: none;
}
input#pause{
font-family: Cooper Black;
font-size: 18px;
color: #FF0066;
background: #C2E0FF;
border: #C2E0FF 2px outset;
border-radius: 25px;
padding: 10px;
cursor: pointer;
margin-top: 10px;
}
div.goes{
text-align: center;
border: #C2E0FF 5px double;
height: 160px;
width: 120px;
margin-top: 48px;
margin-left: 5px;
}
div.matches{
text-align: center;
border: #C2E0FF 5px double;
height: 160px;
width: 120px;
margin-top: 30px;
margin-left: 10px;
}
p{
font-size: 28px;
}
span{
font-family: Times New Roman;
font-size: 84px;
}
.sprite {
width:96px;
height:96px;
position: relative;
margin:15px;
}
.toon{
background: url(explode.png);
}
}
#dialogoverlay{
display: none;
opacity: 0.8;
position: fixed;
top: 0px;
left: 0px;
background: #FFF;
width: 100%;
z-index: 10;
}
#dialogbox{
display: none;
position: fixed;
background: #FF0066;
border-radius:7px;
width:400px;
z-index: 10;
}
#dialogbox > div{ background: #FFF; margin:8px; }
#dialogbox > div > #dialogboxhead{ background: linear-gradient(#99CCFF, #FFF); height: 40px; color: #CCC; }
#dialogbox > div > #dialogboxbody{ background: #FFF; color: #FF0066; font-size: 36px; text-align:center;}
#dialogbox > div > #dialogboxfoot{ background: linear-gradient(#FFF, #99CCFF); padding-bottom: 20px; text-align:center; }
<!DOCTYPE html>
<html>
<head>
<title>Memory Card Game</title>
<meta http-equiv="Content-type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="reset.css" />
<link rel="stylesheet" type="text/css" href="text.css" />
<link rel="stylesheet" type="text/css" href="960.css" />
<link rel="stylesheet" type="text/css" href="mystyles.css" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type='text/javascript' src='jquery.animateSprite.js'></script>
<script> //developphp.com tutorial
var memory_array = ['A','A','B','B','C','C','D','D','E','E','F','F','G','G','H','H','I','I','J','J'];
var memory_values = [];
var memory_tile_ids = [];
var tiles_flipped = 0;
var turns = 0
var matches = 0
Array.prototype.memory_tile_shuffle = function(){
var i = this.length, j, temp;
while(--i > 0){
j = Math.floor(Math.random() * (i+1));
temp = this[j];
this[j] = this[i];
this[i] = temp;
}
}
function newBoard(){
tiles_flipped = 0;
var output = '';
memory_array.memory_tile_shuffle();
for(var i = 0; i < memory_array.length; i++){
output += '<div id="tile_'+i+'" onclick="memoryFlipTile(this,\''+memory_array[i]+'\')"></div>';
}
document.getElementById('memory_board').innerHTML = output;
//fade in
$(document).ready(function () {
$('#memory_board > div').hide().fadeIn(1500).delay(6000)
});
resetTime();
turns = 0;
document.getElementById('Count').innerHTML = 0;
matches = 0;
document.getElementById('matchNumber').innerHTML = 0;
}
function memoryFlipTile(tile,val){
startTimer();
playClick();
if(tile.innerHTML == "" && memory_values.length < 2){
tile.style.background = '#FFF';
tile.innerHTML = '<img src="' + val + '.png"/>';
if(memory_values.length == 0){
memory_values.push(val);
memory_tile_ids.push(tile.id);
} else if(memory_values.length == 1){
memory_values.push(val);
memory_tile_ids.push(tile.id);
if(memory_values[0] == memory_values[1]){
tiles_flipped += 2;
//sound
playMatch();
//animation
//number of clicks
turns = turns + 1;
document.getElementById("Count").innerHTML = turns;
//number of matches
matches = matches + 1;
document.getElementById("matchNumber").innerHTML = matches;
// Clear both arrays
memory_values = [];
memory_tile_ids = [];
// Check to see if the whole board is cleared
if(tiles_flipped == memory_array.length){
playEnd();
Alert.render("Congratulations! Board Cleared");
//resetTime()
//stopCount();
document.getElementById('memory_board').innerHTML = "";
newBoard();
}
} else {
function flipBack(){
// Flip the 2 tiles back over
var tile_1 = document.getElementById(memory_tile_ids[0]);
var tile_2 = document.getElementById(memory_tile_ids[1]);
tile_1.style.background = 'url(tile_background.png) no-repeat';
tile_1.innerHTML = "";
tile_2.style.background = 'url(tile_background.png) no-repeat';
tile_2.innerHTML = "";
//number of clicks
turns = turns + 1;
document.getElementById("Count").innerHTML = turns;
//clickNumber()
// Clear both arrays
memory_values = [];
memory_tile_ids = [];
}
setTimeout(flipBack, 700);
}
}
}
}
//timer
var c = 0;
var t;
var timer_is_on = 0;
function timedCount() {
document.getElementById('txt').value = c;
c = c+1;
t = setTimeout(timedCount, 1000);
}
function startTimer() {
if (!timer_is_on) {
timer_is_on = 1;
timedCount();
}
}
function stopCount() {
clearTimeout(t);
timer_is_on = 0;
}
function resetTime(){
clearTimeout(t);
timer_is_on = 0;
c = 0
document.getElementById('txt').value = 0
}
//sound effects /*sounds from http://www.freesfx.co.uk*/
function playClick(){
var sound=document.getElementById("click");
sound.play();
}
function playMatch(){
var sound=document.getElementById("match_sound");
sound.play();
}
function playEnd(){
var sound=document.getElementById("finished");
sound.play();
}
//custom alert developphp.com tutorial
function CustomAlert(){
this.render = function(dialog){
var winW = window.innerWidth;
var winH = window.innerHeight;
var dialogoverlay = document.getElementById('dialogoverlay');
var dialogbox = document.getElementById('dialogbox');
dialogoverlay.style.display = "block";
dialogoverlay.style.height = winH+"px";
dialogbox.style.left = (winW/2) - (400 * .5)+"px";
dialogbox.style.top = "200px";
dialogbox.style.display = "block";
document.getElementById('dialogboxhead').innerHTML = "";
document.getElementById('dialogboxbody').innerHTML = dialog;
document.getElementById('dialogboxfoot').innerHTML = '<button onclick="Alert.ok()">New Game</button>';
}
this.ok = function(){
document.getElementById('dialogbox').style.display = "none";
document.getElementById('dialogoverlay').style.display = "none";
}
}
var Alert = new CustomAlert();
</script>
<script>//sparkle effect: http://www.rigzsoft.co.uk/how-to-implement-animated-sprite-sheets-on-a-web-page/
$(document).ready(function(){
$("#memory_board").click(function animation(){
$(".toon").animateSprite({
columns: 10,
totalFrames: 50,
duration: 1000,
});
});
});
</script>
</head>
<body>
<audio id = "click" src = "click.mp3" preload = "auto"></audio>
<audio id = "match_sound" src = "match.mp3" preload = "auto"></audio>
<audio id = "finished" src = "finished.wav" preload = "auto"></audio>
<div id = "dialogoverlay"></div>
<div id = "dialogbox">
<div>
<div id = "dialogboxhead"></div>
<div id = "dialogboxbody"></div>
<div id = "dialogboxfoot"></div>
</div>
</div>
<div class = "container_16">
<div id = "banner" class = "grid_16">
<p><br></p>
<h1>Memory</h1>
</div>
<div class = "grid_3">
<input type="text" id="txt" value="0"/>
<p><br></p>
<p><br></p>
<div class = "goes">
<p>Turns <br><span id = "Count">0</span></p>
</div>
</div>
<div class = "grid_10">
<div id="memory_board"></div>
<script>newBoard();</script>
<div style="position: relative; height: 110px;">
<div class="sprite toon"></div>
</div>
</div>
<div class = "grid_3">
<button id = "new_game" onclick="newBoard()">New Game</button>
<input type="button" id="pause" value="Pause Game" onclick="stopCount()">
<p><br></p>
<p><br></p>
<p><br></p>
<div class = "matches">
<p>Matches <br><span id = "matchNumber">0</span></p>
</div>
</div>
</div>
<footer> </footer>
</body>
</html>