英文:
How can I toggle the hidden class on an inner div by clicking a button inside a card using jQuery?
问题
Here's the translated part of your code:
function handleMoreInfo() {
// 1) 找到coin-card元素
$(".coin-card").on("click", async function(e) {
// a) 停止事件传播
e.stopImmediatePropagation();
// b) 找到coin的ID
const coinID = ($(this).find('.coin-name').text()).toLowerCase();
// c) 获取有关coin的更多信息
const data = await fetchMoreInfo(coinID);
// d) 可选:隐藏所有面板
// if(nodeList) hideAllPanels();
// e) 显示所选的更多信息面板
if (data) showMoreInfo(data, $(this));
});
}
const showMoreInfo = (data, thatCoin) => {
// 1) 找到所有more-info-panel的类,然后查看hidden类是否存在
// 2) 在显示和隐藏之间切换more-info-panel
nodeList[0].forEach(div => {
const coinNameFromArr = $(div).find('.coin-name').text();
if (coinNameFromArr.toLowerCase() === data.id ) {
console.log('Match');
const panel = $(div).find('.more-info-panel').attr("class");
const panelClassesArr = panel.split(' ');
if(panelClassesArr.length === 1) $(div).find('.more-info-panel').addClass("hidden");
if(panelClassesArr.length === 2) $(div).find('.more-info-panel').removeClass("hidden");
}
})
// 3) 在面板内设置新数据
thatCoin.find('.more-info-image').prop("src", data?.image?.large);
thatCoin.find('.usd').text(`USD: $${data?.market_data?.current_price?.usd}`);
thatCoin.find('.eur').text(`EUR: €${data?.market_data?.current_price?.eur}`);
thatCoin.find('.ils').text(`ILS: ₪${data?.market_data?.current_price?.ils}`);
}
const hideAllPanels = () => {
// 1) 循环遍历body-container的节点列表,看看是否有面板是打开的
console.log(nodeList);
nodeList[0].forEach(div => {
const panel = $(div).find('.more-info-panel').attr("class");
const panelClassesArr = panel.split(' ');
// 2) 如果元素只有一个类,那么面板是显示的,我们需要隐藏它
if(panelClassesArr.length === 1) $(div).find('.more-info-panel').addClass("hidden");
});
}
I've translated the JavaScript part of your code.
英文:
How to create functionality in jQuery that will toggle hidden class on inner div by clicking on a button inside a card?
I tried to create a container div that have some cards in it.the problem is when i click the button
it only opens the panel but doesn't close the panel if i click it again.
however it being closed if i open a new panel(that is somthing i want to happen)
another thing is that hideAllPanels and showMoreInfo works when only one is active.
function handleMoreInfo() {
// 1) Find the coin-card element
$(".coin-card").on("click",async function(e) {
// a) stop bubbling
e.stopImmediatePropagation();
// b) Find coin id
const coinID = ($(this).find('.coin-name').text()).toLowerCase();
// c) Get more info about the coin
const data = await fetchMoreInfo(coinID);
// d) Optional: hide all panels
// if(nodeList) hideAllPanels();
// e) display the chosen more info panel
if (data) showMoreInfo(data,$(this));
});
}
const showMoreInfo = (data,thatCoin) => {
// 1) Find all classes on more-info-panel and then find out if class hidden exists
// 2) Toggle more-info-panel between displayed and hidden
nodeList[0].forEach(div => {
const coinNameFromArr = $(div).find('.coin-name').text();
if (coinNameFromArr.toLowerCase() === data.id ) {
console.log('Match');
const panel = $(div).find('.more-info-panel').attr("class");
const panelClassesArr = panel.split(' ');
if(panelClassesArr.length === 1) $(div).find('.more-info-panel').addClass("hidden");
if(panelClassesArr.length === 2) $(div).find('.more-info-panel').removeClass("hidden");
}
})
// 3) Set new data inside panel
thatCoin.find('.more-info-image').prop("src",data?.image?.large);
thatCoin.find('.usd').text(`USD: $${data?.market_data?.current_price?.usd}`);
thatCoin.find('.eur').text(`EUR: €${data?.market_data?.current_price?.eur}`);
thatCoin.find('.ils').text(`ILS: ₪${data?.market_data?.current_price?.ils}`);
}
const hideAllPanels = () => {
// 1) Loop over node list of the body-container to see if some panels are open
console.log(nodeList);
nodeList[0].forEach(div => {
const panel = $(div).find('.more-info-panel').attr("class");
const panelClassesArr = panel.split(' ');
// 2) If element have only one class it means that panel is displayed add we need to hide it
if(panelClassesArr.length === 1) $(div).find('.more-info-panel').addClass("hidden");
});
}
this is the html of a card example
<div class="coin-card">
<div class="headInfo">
<p class="coin-symbol">btc</p>
<div class="form-check form-switch"><input class="form-check-input" num1="0" type="checkbox" role="switch"
onclick="addCoinsToArray()"><label class="form-check-label" for="flexSwitchCheckChecked"></label></div>
</div>
<p class="coin-name">Bitcoin</p><button class="btn btn-info mybtn" onclick="handleMoreInfo()" data-toggle="collapse"
data-target="info" num="0">More Info</button>
<div class="more-info-panel hidden" symbol="bitcoin"><img class="more-info-image"
src="./src/img/bitcoin-g80ff29158_640.jpg">
<p class="info-title">Coin Prices:</p>
<p class="usd">USD: $30</p>
<p class="eur">EUR: €30</p>
<p class="ils">ILS: ₪30</p>
</div>
</div>
答案1
得分: 1
I agree, your code is a bit overcomplicated. You are also mixing onclick
and jQuery .on('click')
, so you're basically adding a new .on('click')
handler to coin-card every time you click on the button.
I'd approach it like this:
// you don't need an onclick on the button
$('.coin-card .btn-info').on('click', async function() {
// find the parent .coin-card of the button that was clicked
const $card = $(this).closest('.coin-card');
const $infoPanel = $card.find('.more-info-panel');
// const coinName = $card.find('.coin-name').text().toLowerCase();
// const data = await fetchMoreInfo(coinID);
// set data...
// version 1 allow multiple panels open
//$infoPanel.toggleClass('hidden');
// or version 2 behave like accordion. close all other panels
const isOpen = $infoPanel.hasClass('hidden');
$('.coin-card .more-info-panel').addClass('hidden');
if (isOpen) {
$card.find('.more-info-panel').removeClass('hidden');
}
});
.coin-card {
border: 1px solid;
margin: .5rem;
padding: 1rem;
float: left;
width: 20%;
}
p {
margin: 0;
}
.coin-card .more-info-panel.hidden {
display:none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="coin-card">
<div class="headInfo">
<p class="coin-symbol">btc</p>
<div class="form-check form-switch"><input class="form-check-input" num1="0" type="checkbox" role="switch" onclick="addCoinsToArray()"><label class="form-check-label" for="flexSwitchCheckChecked"></label></div>
</div>
<p class="coin-name">Bitcoin</p><button class="btn btn-info mybtn" data-toggle="collapse" data-target="info" num="0">More Info</button>
<div class="more-info-panel hidden" symbol="bitcoin"><img class="more-info-image" src="./src/img/bitcoin-g80ff29158_640.jpg">
<p class="info-title">Coin Prices:</p>
<p class="usd">USD: $30</p>
<p class="eur">EUR: €30</p>
<p class="ils">ILS: ₪30</p>
</div>
</div>
<div class="coin-card">
<div class="headInfo">
<p class="coin-symbol">btc</p>
<div class="form-check form-switch"><input class="form-check-input" num1="0" type="checkbox" role="switch" onclick="addCoinsToArray()"><label class="form-check-label" for="flexSwitchCheckChecked"></label></div>
</div>
<p class="coin-name">Bitcoin</p><button class="btn btn-info mybtn" data-toggle="collapse" data-target="info" num="0">More Info</button>
<div class="more-info-panel hidden" symbol="bitcoin"><img class="more-info-image" src="./src/img/bitcoin-g80ff29158_640.jpg">
<p class="info-title">Coin Prices:</p>
<p class="usd">USD: $30</p>
<p class="eur">EUR: €30</p>
<p class="ils">ILS: ₪30</p>
</div>
</div>
<div class="coin-card">
<div class="headInfo">
<p class="coin-symbol">btc</p>
<div class="form-check form-switch"><input class="form-check-input" num1="0" type="checkbox" role="switch" onclick="addCoinsToArray()"><label class="form-check-label" for="flexSwitchCheckChecked"></label></div>
</div>
<p class="coin-name">Bitcoin</p><button class="btn btn-info mybtn" data-toggle="collapse" data-target="info" num="0">More Info</button>
<div class="more-info-panel hidden" symbol="bitcoin"><img class="more-info-image" src="./src/img/bitcoin-g80ff29158_640.jpg">
<p class="info-title">Coin Prices:</p>
<p class="usd">USD: $30</p>
<p class="eur">EUR: €30</p>
<p class="ils">ILS: ₪30</p>
</div>
</div>
英文:
I agree, your code is a bit overcomplicated. You are also mixing onclick
and jQuery .on('click')
, so you're basically adding a new on('click')
handler to coin-card everytime you click on the button.
I'd approach it like this:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
// you don't need an onclick on the button
$('.coin-card .btn-info').on('click', async function() {
// find the parent .coin-card of the button that was clicked
const $card = $(this).closest('.coin-card');
const $infoPanel = $card.find('.more-info-panel');
// const coinName = $card.find('.coin-name').text().toLowerCase();
// const data = await fetchMoreInfo(coinID);
// set data...
// version 1 allow multiple panels open
//$infoPanel.toggleClass('hidden');
// or version 2 behave like accordion. close all other panels
const isOpen = $infoPanel.hasClass('hidden');
$('.coin-card .more-info-panel').addClass('hidden');
if (isOpen) {
$card.find('.more-info-panel').removeClass('hidden');
}
});
<!-- language: lang-css -->
.coin-card {
border: 1px solid;
margin: .5rem;
padding: 1rem;
float: left;
width: 20%;
}
p {
margin: 0;
}
.coin-card .more-info-panel.hidden {
display:none;
}
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="coin-card">
<div class="headInfo">
<p class="coin-symbol">btc</p>
<div class="form-check form-switch"><input class="form-check-input" num1="0" type="checkbox" role="switch"
onclick="addCoinsToArray()"><label class="form-check-label" for="flexSwitchCheckChecked"></label></div>
</div>
<p class="coin-name">Bitcoin</p><button class="btn btn-info mybtn" data-toggle="collapse"
data-target="info" num="0">More Info</button>
<div class="more-info-panel hidden" symbol="bitcoin"><img class="more-info-image"
src="./src/img/bitcoin-g80ff29158_640.jpg">
<p class="info-title">Coin Prices:</p>
<p class="usd">USD: $30</p>
<p class="eur">EUR: €30</p>
<p class="ils">ILS: ₪30</p>
</div>
</div>
<div class="coin-card">
<div class="headInfo">
<p class="coin-symbol">btc</p>
<div class="form-check form-switch"><input class="form-check-input" num1="0" type="checkbox" role="switch"
onclick="addCoinsToArray()"><label class="form-check-label" for="flexSwitchCheckChecked"></label></div>
</div>
<p class="coin-name">Bitcoin</p><button class="btn btn-info mybtn" data-toggle="collapse"
data-target="info" num="0">More Info</button>
<div class="more-info-panel hidden" symbol="bitcoin"><img class="more-info-image"
src="./src/img/bitcoin-g80ff29158_640.jpg">
<p class="info-title">Coin Prices:</p>
<p class="usd">USD: $30</p>
<p class="eur">EUR: €30</p>
<p class="ils">ILS: ₪30</p>
</div>
</div>
<div class="coin-card">
<div class="headInfo">
<p class="coin-symbol">btc</p>
<div class="form-check form-switch"><input class="form-check-input" num1="0" type="checkbox" role="switch"
onclick="addCoinsToArray()"><label class="form-check-label" for="flexSwitchCheckChecked"></label></div>
</div>
<p class="coin-name">Bitcoin</p><button class="btn btn-info mybtn" data-toggle="collapse"
data-target="info" num="0">More Info</button>
<div class="more-info-panel hidden" symbol="bitcoin"><img class="more-info-image"
src="./src/img/bitcoin-g80ff29158_640.jpg">
<p class="info-title">Coin Prices:</p>
<p class="usd">USD: $30</p>
<p class="eur">EUR: €30</p>
<p class="ils">ILS: ₪30</p>
</div>
</div>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论