I have the following bit about shop info:
<h3 class="-center"><shop>Shop name</shop></h3>
<button type="button" id="banff" onclick="showShop(this.id)"><shop-title><b>Bakery Shop</b></shop-title></button>
<p class="move-right"><shop-info>Shop Address · Shop number</shop-info></p>
<div id="shop" class="hidden">
<p><shop-info>Opening soon</shop-info></p>
</div>
What I'm trying to do is that once the button is clicked, it will get the first div after the button and toggle the hidden class without referencing the id, there will be multiple shops so I am trying to create one function which will work for all of them rather than create an individual function for each.
I thought I could do something like:
function showShop(id) {
const elem = document.getElementById(id);
alert(id);
const div = elem.closest('div');
div.classList.toggle('hidden');
}
But it's referencing the first div on the page rather than the first one after the button, where have I gone wrong here? Or do I need to go about this a different way?
Thanks in advance for any advice
What about connecting the button id with the div id?
something like:
<h3 class="-center"><shop>Shop name</shop></h3>
<button type="button" id="button-1" onclick="showShop(this.id)">
<shop-title><b>Bakery Shop</b></shop-title>
</button>
<p class="move-right"><shop-info>Shop Address · Shop number</shop-info></p>
<div id="shop-button-1" class="hidden">
<p><shop-info>Opening soon</shop-info></p>
</div>
and in the javascript code would be possible to simplify to:
function showShop(id) {
const elem = document.getElementById(id);
const div = document.getElementById('shop-' + id);
div.classList.toggle('hidden');
}
You should try and avoid using ids as they are difficult to keep track of. Instead you should navigate relative to the clicked button. Below is a script that can easily take care of multiple shop sections without using any ids:
document.querySelectorAll("button").forEach(btn=>{
for(var div=btn;div=div.nextElementSibling;)
if(div.tagName==="DIV") break;
if(div) btn.onclick=()=>div.classList.toggle("hidden")
})
.hidden {display:none}
<h3 class="-center"><shop>Shop name</shop></h3>
<button><shop-title><b>Bakery Shop</b></shop-title></button>
<p class="move-right"><shop-info>Shop Address · Shop number</shop-info></p>
<div class="hidden">Info on bakery shop:
<p><shop-info>Opening soon</shop-info></p>
</div>
<button><shop-title><b>Iron Monger</b></shop-title></button>
<p class="move-right"><shop-info>Shop Address · Shop number</shop-info></p>
<div class="hidden">Info on iron monger's:
<p><shop-info>already open!</shop-info></p>
</div>
<button><shop-title><b>Fish Monger</b></shop-title></button>
<p class="move-right"><shop-info>Shop Address · Shop number</shop-info></p>
<div class="hidden">Info on fish monger's:
<p><shop-info>will never open!</shop-info></p>
</div>
In my latest update I tweaked the snippet again so that now I do the "relative navigation to the associated <div>" only once: at the time when I define and add the onclick eventlistener.
Related
In my project, I fetch html content from DB with ajax, and these content will appear in web in div with id of timeTagDiv.
If My name is John, it should appears:
17:05:31 John translatetomaintanceGroup
letMnGrpmakeit
17:05:53 snow acceptSheet
17:06:04 snow translatetoleadGrp
leadercheckit
If my name is snow, it should appears:
17:05:31 John translatetomaintanceGroup
letMnGrpmakeit
17:05:53 snow acceptSheet
17:06:04 snow translatetoleadGrp
leadercheckit
Here is my ajax code:
var stChr="John";
var stTrnStr="translateto";
$.ajax({
......
success:function(data)
{
var $myHtml = $(data.stPrc);
$myHtml.find("label").filter(function(){
return $(this).text()===stChr;
}).parent().attr("class", "rightd");
//$myHtml.find('div:contains('+stChr+' '+stTrnStr+')').next().attr('class','rightd');
$('#timeTagDiv').html($myHtml);
}
});
Here is the content of data.stPrc from DB:
<div class="leftd">
<label>17:05:31</label>
<label>John</label>
<label> translateto</label>
<label>maintanceGroup</label>
</div>
<div class="leftd">
<div class="speech left" >letMnGrpmakeit</div>
</div>
<div class="leftd"><label>17:05:53</label>
<label>snow</label>
<label> acceptSheet</label>
</div>
<div class="leftd">
<label>17:06:04</label>
<label>snow</label>
<label> translateto</label>
<label>leadGrp</label>
</div>
<div class="leftd">
<div class="speech left" >leadercheckit</div>
</div>
When the context of label is John, the attribute class of parent div changed to rightd. Here is the code working successfully:
$myHtml.find("label").filter(function(){
return $(this).text()===stChr;
}).parent().attr("class", "rightd");
And then, the content of letMnGrpmakeit belongs to John should at the right side. So the next two divs class should be set class="rightd" and class="speech right".
In my example, before:
<div class="leftd">
<div class="speech left" >letMnGrpmakeit</div>
</div>
after replace:
<div class="rightd">
<div class="speech right" >letMnGrpmakeit</div>
</div>
I use :
$myHtml.find('div:contains('+stChr+' '+stTrnStr+')').next().attr('class','rightd');
$myHtml.find('div:contains('+stChr+' '+stTrnStr+')').next().next().attr('class','speech right');
But unfortunately, they both worked fail.
I have tried one condition:
$myHtml.find('label:contains('+stTrnStr+')').parent().next().attr('class','rightd');
It works, but it appears like:
17:05:31 John translatetomaintanceGroup
letMnGrpmakeit
17:05:53 snow acceptSheet
17:06:04 snow translatetoleadGrp
leadercheckit
"leadercheckit" should under "17:06:04 snow translatetoleadGrp", because it belongs to snow.
I have no idea about this. The key to change two div class are two conditions.
Who can help me?
I'm not sure I understand everything correctly because of wording and grammar, but I would suggest using addClass('className') and removeClass('className') instead. This way if your element has more than one class, it will only remove the desired class. By using .attr('class', 'className'), you're replacing everything. If you wish to add multiple classes, just use .addClass('class-1 class-2')
Use these:
$myHtml.find('label:contains('+stChr+')').next('label:contains('+stTrnStr+')').parent().next().attr('class','rightd');
$myHtml.find('label:contains('+stChr+')').next('label:contains('+stTrnStr+')').parent().next().children("div").eq(0).attr('class','speech right');
I'm fairly new to Javascript/Jquery and I'm trying to hide multiple children/adjacent classes when a specific parent class is clicked.
Here's my HTML
<div class="container">
<div class="row">
<div class ="col-md-2 pov_icon">
<div class="pov_icon_small">
<i class="fa fa-clock-o"></i>
</div>
<div class="pov_title_small">
MEASURE
</div>
</div>
<div class ="col-md-2 pov_icon">
<div class="pov_icon_large">
<i class="fa fa-map-marker"></i>
</div>
<div class="pov_title_large">
MEASURE
</div>
</div>
<div class ="col-md-2 pov_icon">
<div class="pov_icon_small">
<i class="fa fa-commenting"></i>
</div>
<div class="pov_title_small">
MEASURE
</div>
</div>
</div>
</div>
What I'm aiming to do is: When a user clicks one of the two smaller icons shown (pov_icon_small), for that individual icon: the classes pov_icon_small and pov_title_small will change to pov_icon_large and pov_title_large respectively. In the same time, I want the other 'large' icon and 'title' to revert back to the 'small' state
I've started calling some Javascript but I don't think I'm headed the right way:
$('.pov_icon_small').on('click', function (e) {
$(this).toggleClass("pov_icon_large");
});
Would anyone be willing to point me to the right direction?
To use individual click
$('.pov_icon_small , .pov_icon_large').on('click', function (e) {
$('.pov_icon_large').not($(this)).removeClass('pov_icon_large').addClass('pov_icon_small');
$(this).toggleClass("pov_icon_small").toggleClass("pov_icon_large");
});
and for title the same way
$('.pov_title_small , .pov_title_large').on('click', function (e) {
$('.pov_title_large').not($(this)).removeClass('pov_title_large').addClass('pov_title_small');
$(this).toggleClass("pov_title_small").toggleClass("pov_title_large");
});
Working Demo
To run both action on icon click use this
$('.pov_icon_small , .pov_icon_large').on('click', function () {
$('.pov_icon_large').not($(this)).removeClass('pov_icon_large').addClass('pov_icon_small');
$('.pov_title_large').not($(this).next('div[class^="pov_title_"]')).removeClass('pov_title_large').addClass('pov_title_small');
$(this).toggleClass("pov_icon_small").toggleClass("pov_icon_large");
$(this).next('div[class^="pov_title_"]').toggleClass("pov_title_small").toggleClass("pov_title_large");
});
Working Demo
Note: be sure to include Jquery
You can add a common class icon for the icon div and title for the title div and following code will work,
$(".pov_icon_small").on('click',function(){
$(this).parent().siblings().children('div').each(function(value){
if($(this).hasClass('icon'))
$(this).addClass('pov_icon_small').removeClass('pov_icon_large');
else if($(this).hasClass('title'))
$(this).addClass('pov_title_small').removeClass('pov_title_large');
});
$(this).addClass('pov_icon_large').removeClass('pov_icon_small');
$(this).siblings('.title').addClass('pov_title_large').removeClass('pov_title_small');
});
Here as you can see, I am first getting parent of the icon clicked i.e. Your pav_icon div now I am changing for all the siblings now each div in the sibling. If it is Iicon changing icon classes as required if title changing title classes.
I have made a simple system which detects double taps. I want to show a heart icon when someone double taps on an image, just like on Instagram.
This is what my code looks right now:
var elements = document.getElementsByClassName('snap_img');
[].slice.call(elements).forEach(function(element) {
var hammertime = new Hammer(element),
img_src = element.getAttribute('src');
hammertime.on('doubletap', function(event) {
alert(img_src); // this is to test if doubletap works
// Some javascript to show the heart icon
});
});
This is what the HTML looks like:
<div class="snap_item">
<div class="snap_item_following_info">
<img class="snap_item_following_img" src="res/stat/img/user/profile/small/1.fw.png" alt="#JohnDoe" />
<a class="snap_item_following_name" href="#">#JohnDoe</a>
<div class="snap_too">
</div>
</div>
<img class="snap_img" src="res/stat/img/user/snap/43/2.fw.png" alt="#ErolSimsir" />
<div class="like_heart"></div>
<div class="snap_info">
<div class="snap_text">
LA is the shit...
<a class="snap_text_hashtah" href="#">#LA_city_trip</a>
</div>
<div class="snap_sub_info">
<span class="snap_time">56 minutes ago</span>
<div class="like inactive_like">
<div class="like_icon"></div>
<div class="like_no_active">5477</div>
</div>
</div>
</div>
</div>
So when the element 'snap_img' is double tapped, I need to get the element 'like_heart' which is one line below the snap_img element. How do I get that sibling element and fade it in with JQuery?
Like this
[].slice.call(elements).forEach(function(element) {
var hammertime = new Hammer(element),
img_src = element.getAttribute('src');
hammertime.on('doubletap', function(event) {
alert(img_src); // this is to test if doubletap works
$(element).next().text('♥').hide().fadeIn();
});
});
P.S. I've added that heart text, since the sibling was empty.
On the event handler, i would do $(element).parent().find('.like_heart').fadeIn(); So the code is not dependant on the element ordering.
(To clarify to selector: take the parent element which is the div.snap_item and find an element with class like-heart inside it)
Hello I have a site I am working on an for this site I am making three panels flip when they are clicked on, you can think of it as a flip card concept. I have everything working but I realized that since the div itself is wrapped in an anchor tag and has a display of "block". What I have is the content inside that are links to external pages but since the div is clickable it only reads that anchor. I tried using the z-index but that doesn't seem to help as all.
This is my markup:
What is ElectedFace?
<div class="flip_content" id="flip1">
<div class="content-info">
<h5 style="text-align:center; font-size:20px; margin:3px 0 0 0; font-family:Arial, Helvetica, sans-serif;"><span class="blue">Elected</span><span class="red">face</span></h5>
<p>electedface is America's free social network delivering more real time news, faster than any other website.</p>
<p>electedface connects subscribers to their elected officials with active electedface accounts</p>
<p>electedface empowers subscribers to share their voice and turn social networking into constructive civil action.</p>
</div>
</div>
<a href="#" class="flip_switch" data-content_container="#flip2" data-flip_container="#flip_box2">
<div class="flipbox" id="flip_box2">
<h4>Getting Started</h4>
</div>
</a>
<div class="flip_content" id="flip2">
<div class="content-info">
<p> There are three ways to connect:</p>
<p>Read top news stories and Read local news stories</p>
<p>Connect to your elected officials and start a group in your community</p>
<p>Register for free membership</p>
</div>
</div>
<a href="#" class="flip_switch" data-content_container="#flip3" data-flip_container="#flip_box3">
<div class="flipbox" id="flip_box3">
<h4>Next Steps</h4>
</div>
</a>
<div class="flip_content" id="flip3">
<div class="content-info">
<p>Elected officials: activate your electedface account, connect to your electorate, and enlist supporters.</p>
</div>
</div>
Heres my Javascript
<script type="text/javascript">
$(function(){
$('.flip_switch').bind("click",function(){
var element = $(this);
var content = element.data("content_container");
var flip_container = element.data("flip_container");
var active_flipbox = $('.activeFlip');
if(element.hasClass('activeFlip')){
//If the flipbox is already flipped
flip_container.revertFlip();
}
else{
if(active_flipbox){
//Revert active flipbox
active_flipbox.revertFlip();
//Remove active status
active_flipbox.removeClass('activeFlip');
}
$(flip_container).flip({
direction: 'rl',
color: '#c8cbce',
content: $(content).html(),
speed:100,
onBefore: function(){
$(flip_container).addClass('activeFlip');
}
});
}
return false;
});
});
</script>
It seems to me your problem is so called bubbling
What you need is (most likely :) :
http://api.jquery.com/event.stopPropagation/
I am 95% finished with this (I hope). I am working on an accordion function that changes the text in the head of the accordion depending if the accordion is opened or closed. (I've got a plus and minus image working).
At present if the client clicks on the accordion to open and close it the title changes correctly, but if the client opens a different accordion the original accordion will slide up, but the title is not updated. I've tried a couple of options I thought would work, but no success as yet.
I've made a jsfiddle here
jquery is:
$(document).ready(function() {
// accordion functionality
$('.accordion-head').click(function(e){
var content = $(this).parent().find('.accordion-content');
var head = $(this).parent().find('.accordion-head');
var $showMore = "Show me more";
var $hideContent = "Hide this offer";
content.addClass('actual');
$('.accordion-content').not('.actual').each(function(){
if ($(this).hasClass('accordion-opened')){
$(this).slideUp(200,function(){
$(this).toggleClass('accordion-opened');
$(this).parent().find('.accordion-head').toggleClass('accordion-open');
});
}
});
$(this).toggleClass('accordion-open');
content.removeClass('actual');
if($(this).hasClass('accordion-open')){
content.slideDown(200,function(){
content.toggleClass('accordion-opened');
head.html($hideContent);
});
}else{
content.slideUp(200,function(){
content.toggleClass('accordion-opened');
head.html($showMore);
});
}
e.preventDefault();
});
});
HTML looks like this:
<div class="accordion">
<div class="accordion-head">
<a href="#">
<span class="accordion-heading">Show me more</span>
</a>
</div>
<div class="accordion-content">
Including Thames Water, Severn Trent, Anglian Water, Yorkshire Water and many more, plus all council tax local authorities. Cashback on mortgage payments up to maximum monthly mortgage payment of £1,000.
</div>
</div>
<span class="spacer"></span>
<div class="accordion">
<div class="accordion-head">
<a href="#">
<span class="accordion-heading">Show me more</span>
</a>
</div>
<div class="accordion-content">
Including British Gas, SSE, EDF Energy, E.ON, npower and many more.
</div>
</div>
<span class="spacer"></span>
etc.
Hope someone can help.
You could rewrite the header during the collapse loop by removing head.html($showMore) & changing
$(this).parent().find('.accordion-head').toggleClass('accordion-open');
to
$(this).parent().find('.accordion-head').toggleClass('accordion-open').html($showMore);
You can also insert $('.accordion-head').html($showMore); inside click function , which will update all the headers intially to show more and then update the individual headers according to the conditions.
var $showMore = "Show me more";
var $hideContent = "Hide this offer";
$('.accordion-head').html($showMore);
content.addClass('actual');