jQuery animation from multiple sources - affecting multiple objects - javascript

I'm looking to simulate pumps, growing and shrinking as expected.
The process is:
pump 1 dumps into pump 2
pump 2 dumps into pump 3
pump 3 dumps into pump 1
Currently I have on/off buttons working pretty much as expected. Unfortunately, for the demo - I'd like to have multiple buttons on at the same time.
Therefore if pump 1 and pump 3 are on at the same time I would expect pump 2 to remain constant. Unfortunately, the way I have the jQuery animations working right now isn't mimicking this in real time.
Here's a demo: http://jsfiddle.net/tJugd/3939/
Ideally, what I'd want is something that grows/shrinks X pixels per second and is bound to a particular div - or something similar. I'm open to ideas.
Example jQuery:
const secs = 30000;
const maxH = '250';
const minH = '0';
$('#btn-on-one').click(function(){
$('#air-pump-one').animate({height:maxH}, secs);
$('#water-pump-one').animate({height:minH}, secs);
$('#air-pump-two').animate({height:minH}, secs);
$('#water-pump-two').animate({height:maxH}, secs);
});
$('#btn-off-one').click(function(){
$('#air-pump-one').stop().animate();
$('#water-pump-one').stop().animate();
$('#air-pump-two').stop().animate();
$('#water-pump-two').stop().animate();
});

I am not sure what you asked, but I rewrote it a little according to my understanding. You can see if this will work for you or not.
http://jsfiddle.net/d21oq86d/6/
If you change the capacity just make sure the .pump-animation-box height css has the correct height to reflect the new capacity.
CSS:
.pump-animation-parent {
display: inline-flex;
}
.pump-animation-box {
border: 2px solid #333;
height: 150px;
width: 40px;
margin-left: 30px;
margin-right: 30px;
margin-bottom: 40px;
background-color: white;
border-radius: 10px;
overflow: hidden;
position: relative;
}
.pump_contents {
background-color: #04ACFF;
position: absolute;
bottom: 0px;
left: 0px;
width: 40px;
}
HTML:
<div id="pump-animation" class="pump-animation-parent">
<div id="pump-one-animation" class="pump-animation-box">
<div class="pump_contents" data-id="1"></div>
</div>
<div id="pump-two-animation" class="pump-animation-box">
<div class="pump_contents" data-id="2"></div>
</div>
<div id="pump-three-animation" class="pump-animation-box">
<div class="pump_contents" data-id="3"></div>
</div>
</div>
<div id="button-parent">
<div>
<button class="btn-default pump_button" data-id="1">Toggle Pump 1</button>
</div>
<div>
<button class="btn-default pump_button" data-id="2">Toggle Pump 2</button>
</div>
<div>
<button class="btn-default pump_button" data-id="3">Toggle Pump 3</button>
</div>
</div>
JS:
var pumps = {
'status': {
1: false,
2: false,
3: false
},
'contents': {
1: 50,
2: 50,
3: 50
},
'capacity': {
1: 150,
2: 150,
3: 150
}
};
$(function(){
init();
});
function init() {
setInterval(function(){
pumpCycle();
updatePumps();
}, 200);
}
function pumpCycle() {
for(var i = 1; i <= 3; i++) {
var target = i == 3 ? 1 : i + 1;
if(pumps.status[i]) {
if(pumps.contents[target] < pumps.capacity[i] && pumps.contents[i] > 0) {
pumps.contents[target]++;
pumps.contents[i]--;
}
}
}
}
function updatePumps() {
for(var i = 1; i <= 3; i++) {
$('.pump_contents[data-id='+i+']').css('height', pumps.contents[i]+'px');
}
}
function printPumps() {
console.log(pumps);
}
$('.pump_button').click(function(){
var pump_id = $(this).attr('data-id');
pumps.status[pump_id] = !pumps.status[pump_id];
});

Related

Javascript shopping cart - need assistance with javascript portion, why isnt my code working?

I am making a javascript shopping cart. When you click on an item, the contents of that item are appended on the DOM via javascript. Having some difficulty with my code, specifically the sections where I bolded with '** **'
For my 'dropDown-amount' class, I have a number as the value but i cant seem to access that value later on in the code (see dropDown-price).
Also I have a For statement on my if/else statement that tries to loop through each index in 'items' array and to essentially count how many times one specific item is inside the list (so I can update quantity of x item on DOM) but having trouble getting everything to work. I know what I have to do to solve this problem and I know all 3 of these issues are linked together, just don't know what is exactly causing this to fail.
//dropdown menu hidden
const cartDropdown = document.querySelector('.cart-dropDown-items');
//every single + symbol
const addToCartButtons = document.querySelectorAll('.addToCart');
//price of item
const foodPrices = document.querySelectorAll('.selection-row-title');
//name of item
const foodNames = document.querySelectorAll('.selection-row-foodName');
//weight of item
const foodWeights = document.querySelectorAll('.selection-row-weight');
const items = [];
let total = 0;
for (let i = 0; i < addToCartButtons.length; i++) {
addToCartButtons[i].addEventListener('click', function() {
const newItem = document.createElement('div');
newItem.className = 'dropDown-item';
let amountItems = document.querySelector('.amount-items');
newItem.innerHTML =
`<div class='dropDown-title dropDown-info'>
${foodNames[i].innerHTML}
</div>
<div class='dropDown-amount dropDown-info'>
**<p class='amount-items'>${1}</p>**
</div>
<div class='dropDown-price dropDown-info'>
**${Number(foodPrices[i].innerHTML.substring(1)) * Number(amountItems.textContent)}**
</div>`;
console.log(newItem)
// if item currently exists in array, just update amount in checkout and increase count++
if (items.includes(addToCartButtons[i].value)) {
items.push(addToCartButtons[i].value); **
for (let i = 0; i < items.length; i++) {
if (items[i].includes(addToCartButtons[i].value)) {
Number(amountItems.innerHTML) + 1;
}
} **
}
// if items does not exist in array, update dom with new item UI and count = 1 by default
else {
items.push(addToCartButtons[i].value);
cartDropdown.appendChild(newItem);
}
console.log(items)
})
}
.cart-dropDown-items {}
.dropDown-title {}
.dropDown-item {
display: flex;
align-items: center;
text-align: center;
background-color: orange;
margin: 3px;
padding: 4px;
}
.dropDown-info {}
.dropDown-title {
width: 40%;
}
.dropDown-amount {
width: 30%;
text-align: center;
}
.dropDown-amount p {
border: 1px solid black;
width: 35%;
padding: 8px;
margin: 0 auto;
background-color: white;
}
.dropDown-price {
width: 30%;
}
<!--cart dropDown-->
<div class='cart-dropDown'>
<div class='cart-dropDown-header'>
<p>My Carts</p>
<p>Personal Cart</p>
<p class='cart-dropDown-close'>Close</p>
</div>
<div class='cart-dropDown-items'>
<!--
<div class='dropDown-item'>
<div class='dropDown-title dropDown-info'>Mixed bell pepper, 6 ct</div>
<div class='dropDown-amount dropDown-info'>1</div>
<div class='dropDown-price dropDown-info'>$9.84</div>
</div>
next unique item...
-->
</div>
<div class='cart-dropDown-checkout'>
<div class='cart-dropDown-checkout1'>
<p>Go to Checkout</p>
</div>
<div class='cart-dropDown-checkout2'>
<p>$0</p>
</div>
</div>
</div>
</div>

Why does one calculation for my onClick get applied to all elements that I'm looping through

Currently doing some exercise for CSS/Javascript animation. I'm attempting to make a Carousel slider from scratch.. I have 4 divs with 550px in width nested in a wrapper of 2200px, which is then nested in a 550px wrapper with overflow hidden.
I then created 4 LI's that I want to make clickable so that it'll translate the wrapper -550*I degrees for every LI.
I performed a queryselectorall to get all the li's, looped through it with a for loop, and created a function that should apply onclick functionality for each LI button.
The issue that I'm running into is that the first calculation of this transform property is applied to all LI's (the 550 * i for [1] [2] and [3] aren't applied).
Here's the HTML that I'm currently using.
<div id="container">
<div id="wrapper">
<div id="itemOne" >
</div>
<div id="itemTwo">
</div>
<div id="itemThree">
</div>
<div id="itemFour">
</div>
</div>
</div>
<ul>
<li class="button"></li>
<li class="button"></li>
<li class="button"></li>
<li class="button"></li>
</ul>
The Javascript
var wrapper = document.querySelector("#wrapper");
var buttons = document.querySelectorAll(".button");
for(var i = 0; i < buttons.length; i++){
var curBut = buttons[i];
curBut.addEventListener("click", function(){
wrapper.style[transformProperty] = 'translate3d(-'+((0-i) * 550) +'px,0,0'
})
console.log(((0-i) * 550));
}
console.log(buttons);
var transforms = ["transform",
"msTransform",
"webkitTransform",
"mozTransform",
"oTransform"];
var transformProperty = getSupportedPropertyName(transforms);
function getSupportedPropertyName(properties) {
for (var i = 0; i < properties.length; i++){
if(typeof document.body.style[properties[i]] != "undefined") {
return properties[i];
}
}
return null;
}
If anyone could explain why the function isn't applying the different changes for the wrapper for each LI, that'd be great! Thanks!!
The global variable i is not copied into each listener, it's shared between the listeners. When you click a button, i is already set to its final value which is 4. As a possible workaround you could override the global variable with a local variable, and get the index on click using indexOf :
var wrapper = document.querySelector("#wrapper");
var buttons = document.querySelectorAll("button");
for (var i = 0; i < buttons.length; i++) {
var curBut = buttons[i];
curBut.addEventListener("click", function() {
var i = Array.prototype.indexOf.call(buttons, this);
wrapper.style[transformProperty] = 'translate3d(-' + (i * 260) + 'px,0,0)';
});
}
var transforms = ["transform",
"msTransform",
"webkitTransform",
"mozTransform",
"oTransform"];
var transformProperty = getSupportedPropertyName(transforms);
function getSupportedPropertyName(properties) {
for (var i = 0; i < properties.length; i++) {
if (typeof document.body.style[properties[i]] != "undefined") {
return properties[i];
}
}
return null;
}
#container {
overflow: hidden;
background: gray;
margin-bottom: 1em;
width: 260px;
height: 100px;
}
#wrapper {
width: calc(4 * 260px);
height: 100px;
}
#wrapper div {
padding: 0 1em;
width: calc(260px - 2em);
line-height: 100px;
height: 100px;
float: left;
color: white;
font-size: 3em;
font-weight: bold;
text-align: center;
}
<div id="container">
<div id="wrapper">
<div id="itemOne">1</div>
<div id="itemTwo">2</div>
<div id="itemThree">3</div>
<div id="itemFour">4</div>
</div>
</div>
<div>
<button type="button">button 1</button>
<button type="button">button 2</button>
<button type="button">button 3</button>
<button type="button">button 4</button>
</div>

For MM/DD/YYYY text, display only that text which is not entered by user

I have a page like below image
According to my requirement, user is allowed to enter digits from the keypad that is provided on the page only. So input field is readonly.
Now I am trying to get is, when user start entering month then other text should remain in text field until user types that. e.g. 05/DD/YYYY like this. And accordingly that text will be hide.
If I placed placeholder then when user starts entering digits all text gone. I don't want that. So I have taken "MM/DD/YYYY" text in seperate span tag.
var Memory = "0", // initialise memory variable
Current = "", // and value of Display ("current" value)
Operation = 0, // Records code for eg * / etc.
MAXLENGTH = 8; // maximum number of digits before decimal!
function format(input, format, sep) {
var output = "";
var idx = 0;
for (var i = 0; i < format.length && idx < input.length; i++) {
output += input.substr(idx, format[i]);
if (idx + format[i] < input.length) output += sep;
idx += format[i];
}
output += input.substr(idx);
return output;
}
function AddDigit(dig) { //ADD A DIGIT TO DISPLAY (keep as 'Current')
if (Current.indexOf("!") == -1) { //if not already an error
if ((eval(Current) == undefined) &&
(Current.indexOf(".") == -1)) {
Current = dig;
document.calc.display.focus();
} else {
Current = Current + dig;
document.calc.display.focus();
}
Current = Current.toLowerCase(); //FORCE LOWER CASE
} else {
Current = "Hint! Press 'Clear'"; //Help out, if error present.
}
if (Current.length > 0) {
Current = Current.replace(/\D/g, "");
Current = format(Current, [2, 2, 4], "/");
}
document.calc.display.value = Current.substring(0, 10);
document.getElementById("cursor").style.visibility = "hidden";
}
function Clear() { //CLEAR ENTRY
Current = "";
document.calc.display.value = Current;
document.calc.display.focus();
document.getElementById("cursor").style.visibility = "visible";
//setInterval ("cursorAnimation()", 5000);
}
function backspace() {
Current = document.calc.display.value;
var num = Current;
Current = num.slice(0,num.length - 1);
document.calc.display.value = Current;
document.calc.display.focus();
document.getElementById("cursor").style.visibility = "hidden";
}
function cursorAnimation() {
$("#cursor").animate({
opacity: 0
}, "fast", "swing").animate({
opacity: 1
}, "fast", "swing");
}
//--------------------------------------------------------------->
$(document).ready(function() {
document.getElementById("cursor").style.visibility = "visible";
//setInterval ("cursorAnimation()", 1000);
});
.intxt1 {
padding: 16px;
border-radius: 3px;
/* border: 0; */
width: 1017px;
border: 1px solid #000;
font-family: Droid Sans Mono;
background: #fff;
}
.txtplaceholder {
font-family: "Droid Sans Mono";
color: #D7D7D7;
position: relative;
float: left;
left: 219px;
top: 17px;
z-index: 10 !important;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
display: inline-block;
}
#cursor {
position: relative;
z-index: 1;
left: 32px;
top: 2px;
visibility: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<form Name="calc" method="post">
<div style="position:relative">
<span id="cursor">_</span>
<span class="txtplaceholder">MM/DD/YYYY</span>
<span style="z-index:100">
<input class="intxt1" autocomplete="off" id="pt_dob" name="display" value="" type="text" readonly>
</span>
<button class="cancel-icon" type="reset" onClick="Clear()"></button>
</div>
<div class="num_keypad1" style=" margin-top:19px;">
<!-- Screen and clear key -->
<div class="num_keys">
<!-- operators and other keys -->
<span id="key1" onClick="AddDigit('1')">1</span>
<span id="key2" onClick="AddDigit('2')">2</span>
<span id="key3" onClick="AddDigit('3')">3</span>
<span id="key4" onClick="AddDigit('4')">4</span>
<span id="key5" onClick="AddDigit('5')">5</span>
<span id="key6" onClick="AddDigit('6')">6</span>
<span id="key7" onClick="AddDigit('7')">7</span>
<span id="key8" onClick="AddDigit('8')">8</span>
<span id="key9" onClick="AddDigit('9')">9</span>
<span id="key0" onClick="AddDigit('0')" style="width: 200px;">0</span>
<span id="keyback" class="clear" onClick="backspace()"> <div class="num_xBox">X</div></span>
</div>
</div>
</form>
With the above Html code I am getting below result:
Problems coming are below:
My digits are going below the text "MM/DD/YYYY". I am not getting how should I get my digits above that text
How should I hide the text which is entered by user and display other accordingly e.g. "MM" should hide if user enters 05 and display other text like this "05/DD/YYYY".
Can anyone please help me in this?
NOTE: With input type=date or by any other plugins I can achieve above functionality but my requirement is different. I have to achieve this with HTML, CSS, JS only.
I would use a ready built data picker for this kind of thing as it would have all the error checking in built to ensure you enter a date in the correct format.
The way you are doing it, you are not able to check if the day is valid until you have entered the month, by which time the user will have to backspace and it will be a very slow and clunky process which is not very user friendly.
Anyway, if you persist with a number pad, here is how I would do it.
put the date in a global array
have a global index counter
add and remove values based on the index counter
The following is a very quick example of the above
var dateBits = ["D", "D", "M", "M", "Y", "Y", "Y", "Y"],
letters = ["D", "D", "M", "M", "Y", "Y", "Y", "Y"],
input = document.getElementById('pt_dob'),
currentIndex = 0;
function makeDate() {
return dateBits[0] + dateBits[1] + "/" + dateBits[2] + dateBits[3] + "/" + dateBits[4] + dateBits[5] + dateBits[6] + dateBits[7];
}
function AddDigit(number) {
dateBits[currentIndex] = number;
if (currentIndex < 8) {
currentIndex++;
}
input.value = makeDate();
}
function RemoveDigit() {
if (currentIndex > 0) {
currentIndex--;
}
dateBits[currentIndex] = letters[currentIndex];
input.value = makeDate();
}
function Clear() {
for (i = 0; i < letters.length; i++) {
dateBits[i] = letters[i];
}
currentIndex = 0;
input.value = makeDate();
}
input.value = makeDate(); // run this line onload or include this whole script at the bottom of the page to get your input to start with your text
.intxt1 {
padding: 16px;
border-radius: 3px;
/* border: 0; */
width: 1017px;
border: 1px solid #000;
font-family: Droid Sans Mono;
background: #fff;
}
#cursor {
position: relative;
z-index: 1;
left: 32px;
top: 2px;
visibility: hidden;
}
.num_keys > span {
display: inline-flex;
width: 2em;
height: 2em;
align-items: center;
justify-content: center;
cursor: pointer;
border: 1px solid black;
}
<form Name="calc" method="post">
<div style="position:relative"><span id="cursor">_</span>
<span class="txtplaceholder">MM/DD/YYYY</span><span style="z-index:100"><input class="intxt1" autocomplete="off" id="pt_dob" name="display" value="" type="text" autocomplete="off" readonly></span>
<button class="cancel-icon" type="reset" onClick="Clear(); return false;">clear</button>
</div>
<div class="num_keypad1" style=" margin-top:19px;">
<!-- Screen and clear key -->
<div class="num_keys">
<!-- operators and other keys -->
<span id="key1" onClick="AddDigit('1')">1</span>
<span id="key2" onClick="AddDigit('2')">2</span>
<span id="key3" onClick="AddDigit('3')">3</span>
<span id="key4" onClick="AddDigit('4')">4</span>
<span id="key5" onClick="AddDigit('5')">5</span>
<span id="key6" onClick="AddDigit('6')">6</span>
<span id="key7" onClick="AddDigit('7')">7</span>
<span id="key8" onClick="AddDigit('8')">8</span>
<span id="key9" onClick="AddDigit('9')">9</span>
<span id="key0" onClick="AddDigit('0')" style="width: 200px;">0</span>
<span id="keyback" class="clear" onClick="RemoveDigit()"> <div class="num_xBox">X</div></span>
</div>
</div>
</form>
var text = "DD/MM/YYYY";
$(".textbox").on("focus blur", function(){
$(".wrapper").toggleClass("focused");
});
$(".wrapper").click(function (e) {
if (e.target == this) {
var b = $(".textbox", this).focus();
}
}).trigger("click");
$(".wrapper > .textbox").on("input", function(){
var ipt = $(this).text().replace(/\u00A0/g, " ");
$(".gray").text(text.substr(ipt.length, text.length));
}).trigger("input");
check this fiddle http://jsfiddle.net/7sD2r/22/
If ive understood all well. I think the one solution is to store user input in hidden field. Then get this input to split digits and return to visible input value that consists of splitted values etc.

How to scroll from waypoint to waypoint in jQuery?

In my webpage I have 4 "waypoints" that have their respective links in a menu. What I need is to also bind the scroll of the page to these waypoints. So when the page loads, the pointer is at the top and based on the scrolling direction, the page moves to the next/previous waypoint. Until now I have come up with this simplistic approach, which goes into a scroll loop due to the scrollTo() function triggering the whole method again.
$(function () {
var top = $(window).scrollTop();
var currentWaypoint = 0;
var previousWaypoint = 0;
$(window).scroll(function () {
console.log("Scroll triggered");
console.log("Current Waypoint: " + currentWaypoint);
var curTop = $(window).scrollTop();
if (top < curTop) {
if (currentWaypoint < 4) {
previousWaypoint = currentWaypoint;
currentWaypoint=currentWaypoint+1;
}
}
else {
if (currentWaypoint > 0) {
previousWaypoint = currentWaypoint;
currentWaypoint=currentWaypoint-1;
}
}
top = curTop;
if (previousWaypoint != currentWaypoint) {
switch (currentWaypoint) {
case 1:
$.scrollTo(document.getElementById("waypoint-collection"));
case 2:
$.scrollTo(document.getElementById("waypoint-report"));
case 3:
$.scrollTo(document.getElementById("waypoint-video"));
case 4:
$.scrollTo(document.getElementById("waypoint-mail"));
default:
}
}
console.log("New Waypoint: " + currentWaypoint);
});
});
I've seen this sort of behaviour implemented in some websites but cannot seem to find anything relevant with google. Any ideas?
EDIT:
The relevant HTML code:
<html>
<head>
<style>
body {
background-color: #FFFFFF;
}
.features-container-wh {
min-height: 12.5rem;
text-align: center;
height: 100%;
}
.features-container-bl {
background-color: #43bfcb;
text-align: center;
color: #FFFFFF;
height: 100%;
}
.features-container-bottom {
height: 100%;
}
</style>
</head>
<body>
<div class="features-container-wh">
Collection
Report
Video
Mail
</div>
<div class="features-container-bl" id="waypoint-collection">
<p>Stuff...</p>
</div>
<div class="features-container-wh" id="waypoint-report">
<p>Stuff...</p>
</div>
<div class="features-container-bl" id="waypoint-video">
<p>Stuff...</p>
</div>
<div class="features-container-bottom" id="waypoint-mail">
<p>Stuff...</p>
</div>
</body>
$('html, body').animate({scrollTop: $("#.wayPoint1").offset().top}, 2000);

Shrink div's then restore them on click

Ideally I want a windows 7 style minimize the div then restore. I want a method that literally takes the div, shrinks and move it to the bottom left of the screen, then can be clicked on to restore it to the center. Please help! Here is my jsfiddle for the basic operation of moving the divs using buttons:
http://jsfiddle.net/UqWC6/1/
var clicked = 0;
var restored = 0;
$("#go").click(function () {
if ($(".box" + clicked)) {
$(".box" + clicked).animate({
top: 400,
width: "20px;",
height: "20px;",
opacity: 0.4,
});
clicked++;
} else {
clicked = 0;
}
});
$('#go2').click(function () {
if ($(".box" + restored)) {
$(".box" + restored).animate({
top: -20,
width: "140px;",
height: "140px;",
opacity: 1,
});
restored++;
} else {
restored = 0;
}
});
http://jsfiddle.net/UqWC6/2/
I removed the incorrect semicolons. And linked to jqueryUI in the fiddle.
So changed these lines from
width: "20px;",
height: "20px;",
width: "140px;",
height: "140px;",
To this
width: "20px",
height: "20px",
width: "140px",
height: "140px",
Seems to work great now. Let me know if that's what you want.
EDIT: http://jsfiddle.net/UqWC6/3/ I fixed it so the third one only needs one click, instead of two.
I changed your html from this
<p>
<button id="go">Save »</button>
<button id="go2">Restore Next</button>
</p>
<div class="box0">box 1</div>
<div class="box1">box 2</div>
<div class="box3">box 2</div>
To this
<p>
<button id="go">Save »</button>
<button id="go1">Restore Next</button>
</p>
<div class="box0">box 1</div>
<div class="box1">box 2</div>
<div class="box2">box 3</div>
And changed this script line from
$('#go2').click(function () {
To this
$('#go1').on('click', function () {
EDIT http://jsfiddle.net/UqWC6/4/ I made it so that you can continue to loop through the clicks once they hit 3 clicks (reset them to 0)
added
if (clicked === 3) {
clicked = 0;
}
if (restored === 3) {
restored = 0;
}

Categories

Resources