jQuery get dynamic nested element to call animate method - javascript

I am dynamically adding data to a div by pressing a button called view.
That is working fine, however I decided to take it a step further and another nested dynamic element.
I can make the call just fine from the dynamic div. The issue I am running into now is when I call the dynamic div to expand the all-views it only expands one; it will not expand any others.
I have verified that my call is correct by adding a var d = Date() and calling the milliseconds as a data-value.
I did some searching and found the parents() and find() methods. I can find the div but it still calls only one.
I have dynamically added 100 divs and it still only calls the newest one. I have also tried another on() with the resize and other triggered events.
What am I missing here?
$("#view").click(function() {
var d = new Date();
$("#dynamic-div-post").prepend('<div class="dynamic-div" style="width: 100%; background-color: red"><div class="col-6"><button id="btn-view" type="button" data-value="test-view" class="btn btn-outline-dark w-100 border-0 d-none d-sm-block"><img class="" src="/img/like.png" style="height: 18px;">view</button></div></div><div class="row dynamic-div" style="width: 100%; background-color: blue;"><div class="col-6 p-0"><div class="all-views" style="background-color: blue; width: 100%; display: none"></div></div></div>');
});
$("#dynamic-div-post").on('click', "#btn-view", function() {
//alert($(this).parents('#dynamic-div-post').find('.all-views').css('display'));
switch ($(this).parents('#dynamic-div-post').find('.all-views').css('display')) {
case 'none':
$(this).parents('#dynamic-div-post').find('.all-views').css({
'border-top': "1px solid rgba(0, 0, 0, 0.2)",
'display': 'block'
}).animate({
"min-height": "150px"
}, 1000, function() {
// Animation complete.
});
break;
case 'block':
$(this).parents('#dynamic-div-post').find('.all-views').animate({
borderWidth: 0,
"min-height": "0",
display: "none"
}, 1000, function() {
$(this).parents('#dynamic-div-post').find('.all-views').css({
'border-top': "none",
'display': 'none'
})
});
break;
}
//$(this).blur();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='dynamic-div-post' class='static-div'>
</div>
<div id='div-view' class='static-div'>
<button id='view'>view</button>
</div>

Found it. The button parent div was not a parent of the allViews
Change all dynamic elements from having ID to a class
Give the parent container a class we can recognise. Too many dynamic-div classes
You needed the NEXT div to open and close.
I simplified the animation
$("#view").click(function() {
var d = new Date();
$("#dynamic-div-post").prepend('<div class="dynamic-div container" style="width: 100%; background-color: red"><div class="col-6"><button type="button" data-value="test-view" class="btn-view btn btn-outline-dark w-100 border-0 d-none d-sm-block"><img class="" src="https://img.icons8.com/pastel-glyph/2x/facebook-like.png" style="height: 18px;">view</button></div></div><div class="row dynamic-div" style="width: 100%; background-color: blue;"><div class="col-6 p-0"><div class="all-views" style="background-color: yellow; width: 100%;">Here is some text</div></div></div>');
});
$("#dynamic-div-post").on('click', ".btn-view", function() {
const $allViews = $(this).closest('.container').next().find('.all-views');
if (!$allViews.is(".open")) {
$allViews.css({
'border-top': "1px solid rgba(0, 0, 0, 0.2)",
'display': 'block'
}).animate({
"min-height": "150px"
}, 1000, function() {
$allViews.addClass("open")
});
} else {
$allViews.animate({
"borderWidth": 0,
"min-height": 0,
"display": "none"
},function() { $allViews.removeClass("open") });
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='dynamic-div-post' class='static-div'>
</div>
<div id='div-view' class='static-div'>
<button id='view'>view</button>
</div>

Related

Stopping all other animations using no selector in $.animate with step()?

I'm animating objects using arrays in my selector which I am stuck using for a specific reason in another SO post I made.
How am I able to stop other animations that have been started from arbitrary array values? E.g: $({ x: 0 }).animate({
For example:
$({ x: 0 }).animate({
x: 500
}, {
easing: 'linear',
duration: 15000,
step: function(now, fx) {
// $(this).stop();
var current_styles = $(selector).attr('style'),
current_styles = string = current_styles.split(" ");
var x = parseFloat(current_styles[1].replace('px', '').replace(';', ''));
if ('x' === fx.prop) {
x = now;
}
$(selector).attr({ style: 'margin-left: ' + x + 'px;' });
},
complete: function() {
//
}
});
HTML:
<div class="row row_1"><button data-id="1">GO</button><div class="box" style="margin-left: 0;"></div></div>
<div class="row row_2"><button data-id="2">GO</button><div class="box" style="margin-left: 0;"></div></div>
<div class="row row_3"><button data-id="3">GO</button><div class="box" style="margin-left: 0;"></div></div>
<div class="row row_4"><button data-id="4">GO</button><div class="box" style="margin-left: 0;"></div></div>
<div class="row row_5"><button data-id="5">GO</button><div class="box" style="margin-left: 0;"></div></div>
<div class="row row_6"><button data-id="6">GO</button><div class="box" style="margin-left: 0;"></div></div>
CSS:
.row {
background-color: green;
margin-bottom: 1px;
width: 600px;
}
.box {
background-color: red;
height: 20px;
width: 20px;
display: inline-block;
}
button {
float: left;
}
I want to stop all other animations when I start this one. However, I cannot use $(selector).stop(); as it does not work.
JSFiddle & gif of issue:
JSFiddle of desired results (Using incorrect formatting for my purpose):
You can stop an animation from within a step() using $(this).stop(); but that only stops the one animation you are inside.
Basically, I need to be able to stop all other animations and then continue with the animation that was just started. The JS itself works exactly as intended, I just need to stop the old animations in their tracks as the new one starts.
It's not clear to me of an elegant nor easy way to do this when using:
$({ x: 0 }).animate({
Thank you for taking the time to consider my question
Store the previous started animation in a variable so you can access it (to retrieve the current value and to stop it):
var prevAnimation;
function runAnimation(selector) {
var start = 0;
if (prevAnimation) {
start = prevAnimation.get(0).x;
prevAnimation.stop();
}
prevAnimation = $({ x: start }).animate({
x: 500
}, {
easing: 'linear',
// And so on
Updated fiddle: https://jsfiddle.net/7vk9d2te/9/
-- Update --
If your animation is just about the margin-left, you could really simplify your code by removing the step function and letting jQuery do the magic with
function runAnimation(selector) {
var start = 0;
if (prevAnimation) {
start = parseFloat(prevAnimation.css('margin-left'));
prevAnimation.stop();
}
prevAnimation = $(selector)
.css('margin-left', start + 'px')
.animate({ 'margin-left': 500 }, {
easing: 'linear',
duration: 15000,
});
}
Fiddle: https://jsfiddle.net/7vk9d2te/10/

creating loop in jquery

I'm trying to build a function that changes background(color a), box(color b) and text color(color a) when a user clicks on the refresh button. I've set the color array, but couldn't figure out how to loop the array properly. Could anyone please help?
var colors = [
["#808080", "#f08080"],
["#2f4f4f", "#cdcdc1"],
["#F3E4C3", "#191970"],
["#DD5C3D", "#495496"],
["#ffbdbd", "#bdffff"],
["#c9c9ff", "#282833"],
["#fff5ee", "#4682b4"]]
I think I can do something like this below:
$("#refresh").click(function(){
$("box").animate({
backgroundColor: colors[0][1],
}, 500);
$("box").css("color", colors[0][0]);
$("background").animate({
backgroundColor: colors[0][0],
}, 500);
//add something that triggers loop here
});
And my html below:
<body>
<section id="main" class="box" style="margin-bottom: 10px">
<div id="city"></div>
<div id="detail"></div>
<div id="icon"></div>
<div id="temperature"></div>
<div id="fcicon" class="inrow">
<div id="f">F</div><div style="opacity: 0.5">/</div><div id="c">C</div>
</div>
<div id="refresh"><i class="fa fa-refresh"></i></div>
</section>
I don't think you need a loop. Try the code below. However i would recommend you to make separate css classes and toggle between them.
var colors = [["#808080", "#f08080"],
["#2f4f4f", "#cdcdc1"],
["#F3E4C3", "#191970"],
["#DD5C3D", "#495496"],
["#ffbdbd", "#bdffff"],
["#c9c9ff", "#282833"],
["#fff5ee", "#4682b4"]];
$(document).on(function(){
var i=0;
$("#refresh").click(function(){
if(colors.length==i+1){
i=0;
}else{
i=i+1;
$("box").animate({
backgroundColor: colors[i][1],
}, 500);
$("section").animate({
backgroundColor: colors[i][0],
}, 500);
$("background").animate({
backgroundColor: colors[i][0],
}, 500);
});
}
});
Edited my example to use your HTML, works great. I changed the class from .container to .box, as that's what you're using.
Here it is as a fiddle, in case.
// Array of color pairs that we'll use for background
// colors, text colors and border colors.
var colors = [
["#808080", "#f08080"],
["#2f4f4f", "#cdcdc1"],
["#F3E4C3", "#191970"],
["#DD5C3D", "#495496"],
["#ffbdbd", "#bdffff"],
["#c9c9ff", "#282833"],
["#fff5ee", "#4682b4"]
];
// The counter refers to which pair in the array we're
// currently referencing.
var counter = 0;
// When the refresh div gets clicked,
$("#refresh").click(function() {
// check the counter and increment or reset it.
if (counter >= colors.length - 1) {
counter = 0;
} else {
counter++
}
// Now, we want to animate CSS attributes on the
// container object. We'll use the color pair
// we're currently pointing to for the background
// text and border colors.
$(".box").animate({
backgroundColor: colors[counter][1],
color: colors[counter][0],
borderColor: colors[counter][0]
}, 500);
});
.box {
position: relative;
border: 1px solid blue;
height: 200px;
width: 200px;
}
.box #city {
font-weight: bolder;
font-size: 14px;
}
#refresh {
position: absolute;
bottom: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<section id="main" class="box" style="margin-bottom: 10px">
<div id="city">Worcester, MA</div>
<div id="detail"></div>
<div id="icon"></div>
<div id="temperature"></div>
<div id="fcicon" class="inrow">
<div id="f">F</div><div style="opacity: 0.5">/</div><div id="c">C</div>
</div>
<div id="refresh"><i class="fa fa-refresh"></i></div>
</section>
Added comments to make it a bit easier to follow.
you can simply keep track of the index by creating a closure.
function looper(){
let i = 0;
return function(){
$("box").animate({
backgroundColor: colors[i][1],
}, 500);
$("section").animate({
backgroundColor: colors[i][0],
}, 500);
$("background").animate({
backgroundColor: colors[i][0],
}, 500);
i++;
if(i === colors.length){
i = 0;
}
}
}
let change = looper();
now you can listen for the event and call the function "change" accordingly.
So I would store the value in the element via data(). Makes it really easy and reusable. Take a moment and read Decoupling Your HTML, CSS, and JavaScript.
The following code is reusable and extensible. Reusable by allowing multiple buttons to have different targets to refresh. Extensible by allowing you to add as many items to the animate as you want. Honestly I'd just put the color in the js-refresh button so each refresh button can have it's own array.
$(document).ready(()=>{
var colors = [
["#808080", "#f08080"],
["#2f4f4f", "#cdcdc1"],
["#F3E4C3", "#191970"],
["#DD5C3D", "#495496"],
["#ffbdbd", "#bdffff"],
["#c9c9ff", "#282833"],
["#fff5ee", "#4682b4"]];
$(".js-refresh").on('click', (e) => {
var $this = $(e.currentTarget);
var selector = $this.data('refresh-target');
$(selector).each((i,e)=>{
var $this = $(e);
var idx = $this.data('js-refresh-index') || 1;
idx = idx >= colors.length ? 1 : idx + 1;
$this
.data('js-refresh-index', idx)
.stop()
.animate({
backgroundColor: colors[idx-1][0],
}, 1)
.animate({
backgroundColor: colors[idx-1][1],
}, 500);
})
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script
src="https://code.jquery.com/color/jquery.color-2.1.2.min.js"
integrity="sha256-H28SdxWrZ387Ldn0qogCzFiUDDxfPiNIyJX7BECQkDE="
crossorigin="anonymous"></script>
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<section id="main" class="box" style="margin-bottom: 10px">
<div id="city"></div>
<div id="detail"></div>
<div id="icon"></div>
<div id="temperature" class="refresh-1">Temp</div>
<div id="fcicon" class="inrow">
<div id="f">F</div><div style="opacity: 0.5">/</div><div id="c">C</div>
</div>
<div class="js-refresh" data-refresh-target=".refresh-1">
<i class="fa fa-refresh"></i>
</div>
</section>
JQuery Animate from their docs
Animation Properties and Values
All animated properties should be animated to a single numeric value, except as noted below; most properties that are non-numeric cannot be animated using basic jQuery functionality (For example, width, height, or left can be animated but background-color cannot be, unless the jQuery.Color plugin is used). Property values are treated as a number of pixels unless otherwise specified. The units em and % can be specified where applicable.
My Html and JavaScript
<!DOCTYPE html>
<html>
<head>
<title>Animate</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<div class="row">
<select id="colors">
<option value="BlueWhite">Background: Blue, Color: White</option>
<option value="YellowBlue">Background: Yellow, Color: Blue</option>
<option value="WhiteRed">Background: White, Color: Red</option>
<option value="BlackWhite">Background: Black, Color: White</option>
</select>
<div id="main" class="box" style="margin-bottom: 10px">
<div id="city"></div>
<div id="detail"></div>
<div id="icon"></div>
<div id="temperature"></div>
<div id="fcicon" class="inrow">
<div id="f">F</div><div style="opacity: 0.5">/</div><div id="c">C</div>
</div>
</div>
<button id="refresh" class="btn btn-primary"><i class="fa fa-refresh"></i></button>
</div>
<script>
$(document).ready(function () {
var colors = {
"BlueWhite": {
"Background": "#0000ff",
"Color": "#ffffff"
},
"YellowBlue": {
"Background": "#FFFF00",
"Color": "#0000ff"
},
"WhiteRed": {
"Background": "#ffffff",
"Color": "#ff0000"
},
"BlackWhite": {
"Background": "#000000",
"Color": "#ffffff"
}
};
$("#refresh").click(function () {
var selected = $("#colors").val();
var colorObj;
if(colors[selected] != undefined) {
colorObj = colors[selected];
} else {
colorObj = colors["BlackWhite"];
}
$("#main").animate({
backgroundColor: colorObj.Background,
color: colorObj.Color
}, function () {
$(this).css("backgroundColor", colorObj.Background).css("color", colorObj.Color);
});
});
});
</script>
</body>
</html>

Apply a class using :class

I already saw the docs, but i still didn't figure out how to put this at work, basicly at begin i just want to show a specific class with vue.js that i later wanna change dynamicly, i just wanna set the default behaviour of that class, so i did something like this:
html
<div class="row">
<h1 class="text-center title">YOU</h1>
<div class="col-md-offset-1 col-md-10">
<div :class="progressYou">asd</div>
</div>
</div>
<div class="row">
<div class="col-md-offset-1 col-md-10">
<div :class="progressMonster">asd</div>
</div>
</div>
css
.progressYou{
width: '100px';
background-color: 'green';
height: '50px';
}
.progressMonster{
width: '100px';
background-color: 'green';
height: '50px';
}
javascript
new Vue({
el: '#monsterGame',
data: {
incrementMonster: 0,
incrementYou: 0,
progressMonster: {
'width': '100px',
'background-color': 'green',
'height': '50px'
},
progressYou: {
'width': '100px',
'background-color': 'green',
'height': '50px'
}
}
})
do i need to attach that in the css?, i basicly want a class on my css and change that dynamcly via the objects that i created on the data in the javascript side, but i can't see anything :S, what am i doing wrong?
You are using the v-bind:class directive, but your arguments are not classnames, they are style specifications.
Also, your CSS has unnecessary quotes.
new Vue({
el: '#monsterGame',
data: {
incrementMonster: 0,
incrementYou: 0,
className: 'progressMonster'
},
methods: {
toggleClass: function () {
this.className = this.className === 'progressMonster' ? 'progressYou' : 'progressMonster';
}
}
})
.progressYou {
width: 100px;
color: white;
background-color: green;
height: 50px;
}
.progressMonster {
color: black;
width: 100px;
background-color: lightblue;
height: 50px;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
<div id="monsterGame">
<div class="row">
<h1 class="text-center title">YOU</h1>
<div class="col-md-offset-1 col-md-10">
<div :class="[className]">asd</div>
</div>
</div>
<div class="row">
<div class="col-md-offset-1 col-md-10">
<div :class="[className]">asd</div>
</div>
</div>
<button #click="toggleClass">Switch</button>
</div>

Do not run jQuery function when <a> tag clicked

I currently work with some jQuery, where i have got some problems.
I got this code
if ($(".accordion").length > 0) {
$(".accordion").each(function() {
var item = $(this).find(".accordion-text");
var height = item.outerHeight() + 20;
item.data("height", height + "px").css("height", "0px");
})
}
$(".accordion").on("click", function(e) {
foldOut($(this));
});
function foldOut(accordien) {
console.log(accordien);
var item = $(accordien).find(".accordion-text");
if ($(accordien).hasClass("accordion-open")) {
$(item).stop().transition({
height: '0px'
}, 500, 'in-out');
$(accordien).find(".accordionArrow").removeClass("accordionBgActive");
console.log($(accordien).find(".accordionArrow"));
} else {
$(accordien).find(".accordionArrow").addClass("accordionBgActive");
$(item).stop().transition({
height: item.data("height")
}, 500, 'in-out');
}
$(accordien).toggleClass("accordion-open");
}
But inside the div that is folding out, there may be an a tag, and when i click on the a tag it opens the link but also folds the div..
How can i get the div not to fold when the click is on an a tag?
HTML Where its "closed"
<div class="row">
<div class="overflow-hide rel">
<div class="accordion rel col-md-12 no-pad">
<div class="accordionHeaderDiv">
<h3>Test</h3>
<div class="accordion-header-teaser">
<p>TestTestTestTestTestTestTestTestTestTest</p>
</div>
</div>
<div class="accordion-text" style="height: 0px;">
<p>TestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTest</p>
<p>Test</p>
</div>
<div class="accordionArrow" style=" position: absolute; top: 0; cursor: pointer; right: 43px; height: 30px;"></div>
</div>
<div class="clearfix"></div>
</div>
</div>
Filter it out regarding event target:
$(".accordion").on("click", function(e) {
if(e.target.tagName.toLowerCase() === "a") return;
foldOut($(this));
});
As anchor can contains other contents, a more relevant way would be:
$(".accordion").on("click", function (e) {
if ($(e.target).closest('a').length) return;
foldOut($(this));
});

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