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>
I am replicating this webpage https://www.modsy.com/project/furniture and I wrote the code On every slide there will be changing of image and phrase like that there are three phrases and images now I want to store the image and phrase in the local storage what the user has finalized
My html code is:
<div class="image mt-3 mb-3" id="sliderImages">
<img src="../static/images/1.jpg" width="400" height="180">
<img src="../static/images/2.jpg" width="400" height="180">
<img src="../static/images/3.jpg" width="400" height="180">
</div><br>
<div class="rangeslider">
<input type="range" min="1" max="3" value="1" class="myslider" id="sliderRange">
<div id="sliderOutput">
<div class="container">
<div class="row mt-4">
<div class="col-4">
<h6 class="display-6">Starting From Scratch</h6>
<p> I'm designing the room </p>
</div>
<div class="col-4">
<h6 class="display-6">Somewhere in Between</h6>
<p>I'm designing around a few pieces I already own</p>
</div>
<div class="col-4">
<h6 class="display-6">Mostly Furnished</h6>
<p>I want to put the finishing touches on my room</p>
</div>
</div>
</div>
<div class="container">
<div class="row mt-4">
<div class="col-4">
<h6 class="display-6">Starting From Scratch</h6>
<p> I'm designing the room </p>
</div>
<div class="col-4">
<h6 class="display-6">Somewhere in Between</h6>
<p>I'm designing around a few pieces I already own</p>
</div>
<div class="col-4">
<h6 class="display-6">Mostly Furnished</h6>
<p>I want to put the finishing touches on my room</p>
</div>
</div>
</div>
<div class="container">
<div class="row mt-4">
<div class="col-4">
<h6 class="display-6">Starting From Scratch</h6>
<p> I'm designing the room </p>
</div>
<div class="col-4">
<h6 class="display-6">Somewhere in Between</h6>
<p>I'm designing around a few pieces I already own</p>
</div>
<div class="col-4">
<h6 class="display-6">Mostly Furnished</h6>
<p>I want to put the finishing touches on my room</p>
</div>
</div>
</div>
</div>
<div class="row mb-3 mt-3">
<div class="col-4 mr-5">
« Home
</div>
<div class="col-4 ml-5">
Next » </div>
</div>
</div>
My CSS code is:
<style>
.rangeslider {
width: 50%;
margin: 0 auto;
position: absolute;
}
.myslider {
-webkit-appearance: none;
background: white;
width: 100%;
height: 20px;
opacity: 0.8;
margin-top: 180px;
}
.myslider::-webkit-slider-thumb {
-webkit-appearance: none;
cursor: pointer;
background: #000080;
width: 33%;
height: 20px;
}
.col-4 {
text-align: center;
}
.myslider:hover {
opacity: 1;
}
.image {
position: relative;
width: 400px;
margin: 0 auto;
}
.image>img {
position: absolute;
display: none;
}
.image>img.visible,
.image>img:first-child {
display: block;
}
#sliderOutput>div {
display: none;
}
#sliderOutput>div.visible,
#sliderOutput>div:first-child {
display: block;
}
#p1{
height: 10px;
}
</style>
My JS code is:
<script>
window.addEventListener('load', function() {
var rangeslider = document.getElementById("sliderRange");
var output = document.getElementById("sliderOutput");
var images = document.getElementById("sliderImages");
rangeslider.addEventListener('input', function() {
for (var i = 0; i < output.children.length; i++) {
output.children[i].style.display = 'none';
images.children[i].style.display = 'none';
}
i = Number(this.value) - 1;
output.children[i].style.display = 'block';
images.children[i].style.display = 'block';
});
});
</script>
My main requirement if the slider is in the first that phrase and image should be stored in local storage like that if it is in second that details should store.
There is no enough details about what json you want to store in the localStorage so that's why i am giving you the basic idea of how you can store a json in localStorage.
Basically you can't store json in localStorage directly but you can store that json in form of a stringand then converting that string(json) into json. Here is the basic example :
// setting json to localStorage
var jsonToBeStoredInLocalStorae = {
sliderImages = [
{path : 'image-path-here'},
{path : 'image-path-here'}
],
phrase : 'your image phrase'
};
localStorage.setItem('slider_json',JSON.stringify(jsonToBeStoredInLocalStorae ));
When you want to get that json from localStorage so you will do like this
//Here you are getting that json in `string` form from `localStorage` and parsing it to `json`
var localStorageJson = JSON.parse(localStorage.getItem('slider_json'));
In localStorage you can only save text strings, so if you want to save it is only one value per record, you insert a name and value to localStorage, but if you want to save an object, you must transform it to a text string with the function JSON.stringify
All children and parents div are with the same class. I'd attached v-on:clickmethod to toggled only the child one of the clicked parent, not all children. If I add (this) the method doesn't work. Thank you.
<div class="expand-box" v-on:click="textToggle()">
<div class="expand-title">Lorem ipsum</div>
<div class="expand-text">Child</div>
</div>
<div class="expand-box" v-on:click="textToggle()">
<div class="expand-title">Lorem Ipsum</div>
<span class="expand-text">Child.</span>
</div>
mounted(){
this.hideText();
},
methods: {
hideText: function() {
$(".expand-text").hide();
},
textToggle: function() {
$(".expand-text").toggle(300);
}
}
First when you are using v-on:click you need set function name like v-on:click="textToggle" if you are not passing parameters.
It's not recommanded to use jQuery alond side Vuejs for animation and dom manipulation,
you need to use css or Vuejs animation :
CSS ANIMATION :
https://codepen.io/khofaai/pen/qJXbbr
http://optimizely.github.io/vuejs.org/guide/transitions.html
.msg {
transition: all .3s ease;
height: 30px;
padding: 10px;
background-color: #eee;
overflow: hidden;
}
.msg.v-enter, .msg.v-leave {
height: 0;
padding: 0 10px;
opacity: 0;
}
<p class="msg" v-if="show" v-transition>Hello!</p>
You can pass $event as a parameter of textToggle so that it becomes v-on:click="textToggle($event)" then your method will use this reference to toggle that element using,
textToggle: function(elem) {
$(elem.target).toggle(300);
}
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
},
mounted() {
this.hideText();
},
methods: {
hideText: function() {
$(".expand-text").hide();
},
textToggle: function(elem) {
$(elem.target).toggle(300);
}
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://unpkg.com/vue"></script>
<div id='app'>
<div class="expand-box" v-on:click="textToggle($event)">
<div class="expand-title">Lorem ipsum</div>
<div class="expand-text">Child</div>
</div>
<div class="expand-box" v-on:click="textToggle($event)">
<div class="expand-title">Lorem Ipsum</div>
<span class="expand-text">Child.</span>
</div>
</div>
You can also use ref in your HTML element to get the reference of that element like:
HTML
<div class="expand-box" v-on:click="textToggle('el1')" ref="el1">
<div class="expand-title">Lorem ipsum</div>
<div class="expand-text">Child</div>
</div>
<div class="expand-box" v-on:click="textToggle('el2')" ref="el2">
<div class="expand-title">Lorem Ipsum</div>
<span class="expand-text">Child.</span>
</div>
METHOD
textToggle: function(refId) {
this.$refs[refId].toggle(300);
}
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>
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));
});