changing button based on bootstrap collapse state - javascript

I am using bootstrap.
I have the HTML code below:
<div class="row">
<button id="dog-btn" data-toggle="collapse" data-target="#dog-section" onclick="petToggle()">Show Pet</button>
</div>
<div class="col-12 collapse" id="dog-section">
I have the JS below:
function petToggle() {
var dogDiv = document.getElementById("dog-section");
var dogBtn = document.getElementById("dog-btn");
}
In my website the starting state of dog-section is variable. Sometimes it could be visible sometimes it can be closed. I tried using :hidden and :visible with jquery to get the initial state of the div but it didn't work as it always returned true or always returned false. My desired outcome: if dog-section is hidden because of Bootstrap dropdown I want the button to read Show Pet. If the dog-section is visible, I want it to read Hide Pet.
Can anyone help?

Use a conditional to check if the css is set to visible if it is then set it to hidden.
With jQuery:
To check:
if(dogSection.css('visibility') === 'hidden'){
// make it visible
}else{
// hide it
}
To set visible:
dogSection.css('visibility', 'visible')
To set hidden:
dogSection.css('visibility', 'hidden')
const $btn = $('#dog-btn')
const $dogSection = $('#dog-section')
function petToggle(){
$btn.click(function(){
if($dogSection.css('visibility') === 'hidden'){
$dogSection.css('visibility', 'visible')
$btn.text("Hide Pet Section")
}else{
$dogSection.css('visibility', 'hidden')
$btn.text("Show Pet Section")
}
})
}
petToggle()
#dog-section {
visibility: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="row">
<button id="dog-btn" data-toggle="collapse" data-target="#dog-section">Show Pet Section</button>
</div>
<div class="col-12 collapse" id="dog-section">
<img src="https://www.petmd.com/sites/default/files/sleeping-dogs-curled-up.jpg" alt="Sleeping Dog" width="450" height="355">
<img href="">
</div>
Using vanilla Javascript...
Depending on how you are displaying your #dog-section in the DOM you can use one of the following.
if(getComputedStyle(dogSection).getPropertyValue('visibility') === 'hidden')
if(getComputedStyle(dogSection).getPropertyValue('display') === 'none')
if(dogSection.style.visibility === 'hidden';
if(dogSection.style.display === 'none';
Then set it using one of the following:
dogSection.style.setProperty('visibility', 'visible')
dogSection.style.visibility = 'visible'
const btn = document.getElementById('dog-btn')
const dogSection = document.getElementById('dog-section')
function petToggle(){
btn.addEventListener('click', function(){
if(getComputedStyle(dogSection).getPropertyValue('visibility') === 'hidden'){
dogSection.style.setProperty('visibility', 'visible')
btn.textContent = "Hide Pet Section"
}else{
dogSection.style.setProperty('visibility', 'hidden')
btn.textContent = "Show Pet Section"
}
})
}
petToggle()
#dog-section {
visibility: hidden;
}
<div class="row">
<button id="dog-btn" data-toggle="collapse" data-target="#dog-section">Show Pet Section</button>
</div>
<div class="col-12 collapse" id="dog-section">
<img src="https://www.petmd.com/sites/default/files/sleeping-dogs-curled-up.jpg" alt="Sleeping Dog" width="450" height="355">
<img href="">
</div>

Remove the petToggle function. You need to use the collapse events to achieve what you want. Here's documentation.
Since dog-section might be hidden or shown initially, you can check the display style of the section and change button text accordingly.
// check the initial display state of the dog-section
// if it's hidden, set the button text to "Show Pet"
// if it's shown, set the button text to "Hide Pet"
if ($("#dog-section").css("display") === "none") {
$("#dog-btn").text("Show Pet");
} else {
$("#dog-btn").text("Hide Pet");
}
// set the button text to "Hide Pet" when dog-section is shown
$("#dog-section").on("show.bs.collapse", function () {
$("#dog-btn").text("Hide Pet");
});
// set the button text to "Show Pet" when dog-section is hidden
$("#dog-section").on("hide.bs.collapse", function () {
$("#dog-btn").text("Show Pet");
});
<link href="https://cdn.jsdelivr.net/npm/bootstrap#4.6.0/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#4.6.0/dist/js/bootstrap.bundle.min.js"></script>
<div class="container">
<div class="row">
<button id="dog-btn" data-toggle="collapse" data-target="#dog-section">Show Pet</button>
</div>
<div class="row">
<div class="col-12 collapse" id="dog-section">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsam quia suscipit amet ex aut. Odit error dolorem tempore, officiis sed, fugit in voluptate laboriosam quas illo ipsa alias magnam! Odit.
</div>
</div>
</div>

Related

Manipulate content # for all div elements (with role="tabpanel") - style="display: none;" to display: block;

How to manipulate a website to change all
div elements (with role="tabpanel") - style="display: none;" to style="display: block;"
via class="accordionItemContent" could be possible as well
I would like to see the whole page/div elements with total content (so it doesn't matter is the manipulation is via JS or CSS .. or jquery)
<div class="accordionItemContent accordion ui-reset widget uibottom" role="tabpanel" style="display: none;"></div>
Because the page is behind a login probably a change via site inspect/console would be one way to go.
Update
I have been to fast when writing about "display"
if "block" it only shows a frame without content
I saw that there is another main difference in the element shown vs all other hidden once:
<h1 class="uiaccordion" role="tab" a-exp="false" a-sel="false" tabindex="-1"><a href="#" id="manage_content_11_ac" tabindex="-1"></div>
<h1 class="uiaccordion" role="tab" a-exp="true" a-sel="true" tabindex="0"> <a href="#" id="manage_content_12_ac" tabindex="-1"></div>
-> How to see/activate the content as well?
jQuery...
$("div[role='tabpanel']").show();
or...
$('.accordionItemContent').show();
Run this in console
document.querySelectorAll('div.accordionItemContent.accordion.ui-reset.widget.uibottom[role="tabpanel"]').forEach(e => {
e.style.display = "block";
});
Edited for edited question, only using class accordionItemContent
document.querySelectorAll('div.accordionItemContent[role="tabpanel"]').forEach(e => {
e.style.display = "block";
});
To change the other attributes as mentioned in the update:
document.querySelectorAll('div.accordionItemContent[role="tabpanel"]').forEach(e => {
e.style.display = "block";
e.setAttribute(“tabindex”, 0) // Use this syntax to change all effected attributes
});
One approach could be creating a generic CSS class to hide elements and add/remove it to the element(s) you want to hide/show:
function showDivs() {
document.querySelectorAll('[role=tabpanel]').forEach(elem => elem.classList.remove('hide'));
}
.hide {
display: none;
}
<button onclick="showDivs()">show hidden DIVs</button>
<div class="accordionItemContent accordion ui-reset widget uibottom hide" role="tabpanel">DIV1: Lorem ipsum dolor sit consecutor amet</div>
<div class="accordionItemContent accordion ui-reset widget uibottom hide" role="tabpanel">DIV2: Lorem ipsum dolor sit consecutor amet</div>
<div class="accordionItemContent accordion ui-reset widget uibottom hide" role="tabpanel">DIV3: Lorem ipsum dolor sit consecutor amet</div>
If you prefer to stick with inline CSS, instead, you can modify the code above in this way:
function showDivs() {
document.querySelectorAll('[role=tabpanel]').forEach(elem => {
elem.style.display = 'block';
/*
* NOTE: if the inline style contains only the display property,
* you could even entirely remove it:
*
* elem.removeAttribute('style');
*/
});
}
<button onclick="showDivs()">show hidden DIVs</button>
<div class="accordionItemContent accordion ui-reset widget uibottom" role="tabpanel" style="display: none;">DIV1: Lorem ipsum dolor sit consecutor amet</div>
<div class="accordionItemContent accordion ui-reset widget uibottom" role="tabpanel" style="display: none;">DIV2: Lorem ipsum dolor sit consecutor amet</div>
<div class="accordionItemContent accordion ui-reset widget uibottom" role="tabpanel" style="display: none;">DIV3: Lorem ipsum dolor sit consecutor amet</div>

How to dynamically update a modal window's contents with HTML elements from sections using vanilla JS?

I'm working on a timeline type app / page and would like a modal window to open with each timeline block's contents when "Read More" is clicked. However, I seem to be lost in the iteration phase as whenever I click on "Read More" only the last section's title shows up in the modal title. Which means the loop finishes iterating and populates the modal title with the last element. Any insight would be greatly appreciated!
**Edited full program down to a more digestible format(hopefully) **
//select modal interaction
var readBtn = document.getElementsByClassName("cd-read-more");
var closeBtn = document.querySelector(".closeBtn");
var modal = document.querySelector(".modal");
var modalTitle = document.getElementById("modal-title");
var modalBody = document.querySelector(".modal-body");
var contentBlock = document.getElementsByClassName("cd-timeline-block")
var timeline = [];
//select cd-timeline-content
timeline.postTitles = document.getElementsByClassName("post-title");
timeline.postBody = document.getElementsByClassName("post-body");
timeline.postImg = document.getElementsByClassName("pic");
//modal event functions
function openModal(indexNumber) {
for (var i = 0; i < readBtn.length; i++) {
modalTitle.innerHTML = timeline.postTitles[i].innerHTML;
}
modal.style.display = "block";
};
//event listeners for selections
//loop thru collection of readBtn array and call openModal to each
for (var i = 0; i < readBtn.length; i++) {
readBtn[i].addEventListener("click", openModal);
};
<!doctype html>
<title>Example Timeline</title>
</head>
<body>
<header>
<h1>Example Timeline</h1>
</header>
<section id="cd-timeline" class="cd-container">
<div class="cd-timeline-block">
<div class="cd-timeline-img cd-location">
<img src="img/cd-icon-location.svg" alt="Picture">
</div>
<!-- cd-timeline-img -->
<div class="cd-timeline-content">
<div class="post-title">
<h2>First Title</h2>
</div>
<div class="post-body">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iusto, optio, dolorum provident rerum.</p>
</div>
Read more
<span class="cd-date">July 17 2017</span>
</div>
<!-- cd-timeline-content -->
</div>
<!-- cd-timeline-block -->
<div id="simpleModal" class="modal">
<div class="modal-content">
<div class="modal-header">
<h2 id="modal-title"><span class="closeBtn">×</span></h2>
</div>
<div class="modal-body">
<div id="map"></div>
</div>
<div class="modal-footer">
<h4>Test Footer</h4>
</div>
</div>
</div>
<!-- END MODAL -->
Thank you all for your input and clues. Out of frustration I wound up using jQuery instead of vanilla JS. I will transpile (am I using it correctly?) it into vanilla JS as a reinforcement exercise but I just wanted the functionality for now.
For reference this is the code I wound up with:
$(document).ready(function(){
//set click function on read more button
$(".cd-timeline-block").on("click", function(){
//selects modal title and empties of content
$(".modal-title").empty();
// //select modal body and empties it
$(".modal-body").empty();
//set variable title as click selector
var title = $(".post-title", this);
//set variable body content as click selections body
var body = $(".post-body", this);
$(title).clone().appendTo(".modal-title");
$(body).clone().appendTo(".modal-body");
})
});

jQuery - Append() is not working to add a button on Clicking an element

jsfiddle: https://jsfiddle.net/gkmuhfqt/1/
As you can see on jsfiddle, I made a Readmore text that can be clicked and it's for some functions.
Using jQuery, I tried to add a button through clicking the Readmore text that uses the append() function.
But it did not work.
Why does my Readmore text click not work at all in append()- to add some button?
I want to add hello button through clicking readmore text.
Where is my problem? How can I fix it?
-Edit-
html :
<div class="container-fluid">
<div class="row">
<div class="col-xs-12 col-sm-6 col-sm-offset-3 col-md-4 col-md-offset-4 col-lg-4 col-lg-offset-4" style="border:0.5px; border-style: solid;">
<div class="media">
<div class="media-left media-top" style="">
<img src="https://6dbaudio.files.wordpress.com/2013/08/imgp0746.jpg" class="media-object pull-left img-circle" style="width:70px; height:70px;">
</div>
<div class="media-body" style="">
<p><h4 class="media-heading">hello</h4></p>
<p class="readmore_as_p">Lorem ipsum dolor sit amet, consesit amet, consesit amet, consesit amet, consesit amet, consesit amet, consesit amet, consesit amet, consesit amet, consectetur.
</p>
</div>
</div>
</div>
javascript:
$(".readmore_as_p").each(function () {
var original_str = $(this).text();
console.log("hi");
if (original_str.length>20) {
var subtracted_str = original_str.substr(0, 20);
var p_plus_readmore_str = '<p class="readmore_before" data="' + original_str + '">' + subtracted_str + '...</p>';
var link_read_more = '<a class="read_more"><p>Read more</p></a>';
$(this).parent().children('p.readmore_as_p').html(p_plus_readmore_str+link_read_more);
$('.read_more').click(function () {
var originaltext = $(this).parent().children('p.readmore_before').attr('data');
$(this).parent().html(originaltext);
//Here is problem starting. What i ask is here.
var text = '<div class="media" style="">\n' +
' <div class="media-body text-center" style="">\n' +
' <button class="btn btn-warning" style="">hello</button>' +
' </div>\n' +
' </div>\n';
$(this).parent().parent().append(text);
//To here
});
}
else {
}
});
The issue is that
$(this).parent().html(originaltext);
removes the element that "this" refers to so $(this).parent().parent() doesn't have a context to get parent from.
You can fix this by moving that line to under the add button line, ie:
$(this).parent().parent().append(text);
$(this).parent().html(originaltext);
Updated fiddle: https://jsfiddle.net/gkmuhfqt/2/
As an extra: $('.read_more').click(function () { should be $('.read_more', this)... or move that outside the $(".readmore_as_p").each
$(this).parent().parent().append(text);
Parent element is not defined, because original $(this) (which is after debugging - a Read more link) is overwritten by your text, so there is no parent for not existing element in DOM.
Updated fiddle
It is better to create an anchor for original container:
var _t = $(this);
and use it later for appending of elements:
_t.append(text)
Nesting of parent().parent() is not very good practice.

Dynamic Facebook share button via jQuery

HTML:
<div class="views-row views-row-2 views-row-even">
<div class="sonuc">
<span>lorem ipsum dolor sit amet</span>
</div>
<div class="views-field views-field-nothing">
<span class="field-content">Share</span>
</div> <div class="sonucbg"></div>
</div>
<div class="views-row views-row-2 views-row-even">
<div class="sonuc">
<span>lorem ipsum dolor sit amet 2222</span>
</div>
<div class="views-field views-field-nothing">
<span class="field-content">Share</span>
</div> <div class="sonucbg"></div>
</div>
JS:
$('#share').click(function() {
var product_name = jQuery(".sonuc span").html();
FB.ui({
method: 'feed',
name: product_name,
}, function(response) {
if(response && response.post_id){}
else{}
});
});
When I click my .share button, get popup, its OK. But I want, e.g. click first share button, get that text.
How can I do it?
You need to isolate the instance of .sonuc span within the views-row instance based on which button was clicked
Try this:
$('.share').click(function() {
var product_name = $(this).closest('.views-row').find(".sonuc span").html();
/* FB code */
});
What you currently have will always get the html from the first .sonic contained in the page

jQuery append current div

I have an outter div .listingContainer, I have about 10 of these on the page all with different content in them. When I click the inner div .saveCompare I want to get the html off all the .listingContainer using jQuery var htmlStr = $(this).html();
I am finding it difficult getting the html of the clicked div, I tried .parent and such and it does not seem to work.
Would be grateful if someone point me to the correct dom call, thanks.
<div class="listingContainer grid_9 alpha omega">
<a class="listContent" href="adContent.html">
<div class="listingWrapper">
<div class="grid_8 alpha omega">
<div class="listingContent">
<div class="imgHolder">
<img src="imgs/cars/SearchThumb-10053319.jpg" width="100" height="75">
</div>
<div class="descHolder">
<div id="doneDeal"></div>
<h3>Fancy Car</h3><div class="saveCompare"><strong>+</strong> Compare</div>
<p>Lorem ipsum dolor sit amet, pri ex duis maiorum commune, illud viderer suscipiantur eam an. Dolorum recteque qui in. Pro inani nulla tacimates ex, qu</p>
<span class="listingPrice"><strong>€4,000</strong></span>
<span class="listingDate">Listed: <strong>Today</strong></span>
<span class="listingLocation">Co. Waterford</span>
<span class="listingViews">Viewed: 20 Times</span>
</div>
</div>
</div>
<div class="goTo goTo_unfocus grid_1 alpha omega">
<div class="gotoWrapper">
Click to View
<div class="imgVeiw"></div>
</div>
</div>
</div><!--End listingWrapper-->
</a>
</div>
To get the first parent that matches a specific selector, starting from an element going up, you can use .closest:
$(this).closest(".listingContainer");
This should accomplish what you are asking:
$(".saveCompare​​​").click(function() {
alert($(this).closest(".listingContainer").html());
});​​
$(".saveCompare").click(function(ev){
var listEl = $(this).parents(".listingContainer").first();
//Do what ever you want with listEl. For example listEl.html() ..etc;
});
$(".saveCompare").parents(".listingContainer"​​)​.get(0)
$('.saveCompare').click(function() {
$(this).parents('.listingContainer:first');
});
.listContent is an anchor tag and all the elements inside that. I'm not sure you will get "$('.saveCompare').click". Check this link
http://jsfiddle.net/Zh7HN/1/

Categories