你可以使用jQuery通过点击卡片内的按钮来切换内部 div 的隐藏类。

huangapple go评论68阅读模式
英文:

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(&#39;click&#39;), so you're basically adding a new on(&#39;click&#39;) 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&#39;t need an onclick on the button
$(&#39;.coin-card .btn-info&#39;).on(&#39;click&#39;, async function() {
// find the parent .coin-card of the button that was clicked
const $card = $(this).closest(&#39;.coin-card&#39;);
const $infoPanel = $card.find(&#39;.more-info-panel&#39;);
// const coinName = $card.find(&#39;.coin-name&#39;).text().toLowerCase();
// const data = await fetchMoreInfo(coinID);
// set data...
// version 1 allow multiple panels open
//$infoPanel.toggleClass(&#39;hidden&#39;);
// or version 2 behave like accordion. close all other panels
const isOpen = $infoPanel.hasClass(&#39;hidden&#39;);
$(&#39;.coin-card .more-info-panel&#39;).addClass(&#39;hidden&#39;);
if (isOpen) {
$card.find(&#39;.more-info-panel&#39;).removeClass(&#39;hidden&#39;);
}
});

<!-- 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 -->

&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;coin-card&quot;&gt;
&lt;div class=&quot;headInfo&quot;&gt;
&lt;p class=&quot;coin-symbol&quot;&gt;btc&lt;/p&gt;
&lt;div class=&quot;form-check form-switch&quot;&gt;&lt;input class=&quot;form-check-input&quot; num1=&quot;0&quot; type=&quot;checkbox&quot;             role=&quot;switch&quot;
onclick=&quot;addCoinsToArray()&quot;&gt;&lt;label class=&quot;form-check-label&quot; for=&quot;flexSwitchCheckChecked&quot;&gt;&lt;/label&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p class=&quot;coin-name&quot;&gt;Bitcoin&lt;/p&gt;&lt;button class=&quot;btn btn-info mybtn&quot; data-toggle=&quot;collapse&quot;
data-target=&quot;info&quot; num=&quot;0&quot;&gt;More Info&lt;/button&gt;
&lt;div class=&quot;more-info-panel hidden&quot; symbol=&quot;bitcoin&quot;&gt;&lt;img class=&quot;more-info-image&quot;
src=&quot;./src/img/bitcoin-g80ff29158_640.jpg&quot;&gt;
&lt;p class=&quot;info-title&quot;&gt;Coin Prices:&lt;/p&gt;
&lt;p class=&quot;usd&quot;&gt;USD: $30&lt;/p&gt;
&lt;p class=&quot;eur&quot;&gt;EUR: €30&lt;/p&gt;
&lt;p class=&quot;ils&quot;&gt;ILS: ₪30&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;coin-card&quot;&gt;
&lt;div class=&quot;headInfo&quot;&gt;
&lt;p class=&quot;coin-symbol&quot;&gt;btc&lt;/p&gt;
&lt;div class=&quot;form-check form-switch&quot;&gt;&lt;input class=&quot;form-check-input&quot; num1=&quot;0&quot; type=&quot;checkbox&quot;             role=&quot;switch&quot;
onclick=&quot;addCoinsToArray()&quot;&gt;&lt;label class=&quot;form-check-label&quot; for=&quot;flexSwitchCheckChecked&quot;&gt;&lt;/label&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p class=&quot;coin-name&quot;&gt;Bitcoin&lt;/p&gt;&lt;button class=&quot;btn btn-info mybtn&quot; data-toggle=&quot;collapse&quot;
data-target=&quot;info&quot; num=&quot;0&quot;&gt;More Info&lt;/button&gt;
&lt;div class=&quot;more-info-panel hidden&quot; symbol=&quot;bitcoin&quot;&gt;&lt;img class=&quot;more-info-image&quot;
src=&quot;./src/img/bitcoin-g80ff29158_640.jpg&quot;&gt;
&lt;p class=&quot;info-title&quot;&gt;Coin Prices:&lt;/p&gt;
&lt;p class=&quot;usd&quot;&gt;USD: $30&lt;/p&gt;
&lt;p class=&quot;eur&quot;&gt;EUR: €30&lt;/p&gt;
&lt;p class=&quot;ils&quot;&gt;ILS: ₪30&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;coin-card&quot;&gt;
&lt;div class=&quot;headInfo&quot;&gt;
&lt;p class=&quot;coin-symbol&quot;&gt;btc&lt;/p&gt;
&lt;div class=&quot;form-check form-switch&quot;&gt;&lt;input class=&quot;form-check-input&quot; num1=&quot;0&quot; type=&quot;checkbox&quot;             role=&quot;switch&quot;
onclick=&quot;addCoinsToArray()&quot;&gt;&lt;label class=&quot;form-check-label&quot; for=&quot;flexSwitchCheckChecked&quot;&gt;&lt;/label&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p class=&quot;coin-name&quot;&gt;Bitcoin&lt;/p&gt;&lt;button class=&quot;btn btn-info mybtn&quot; data-toggle=&quot;collapse&quot;
data-target=&quot;info&quot; num=&quot;0&quot;&gt;More Info&lt;/button&gt;
&lt;div class=&quot;more-info-panel hidden&quot; symbol=&quot;bitcoin&quot;&gt;&lt;img class=&quot;more-info-image&quot;
src=&quot;./src/img/bitcoin-g80ff29158_640.jpg&quot;&gt;
&lt;p class=&quot;info-title&quot;&gt;Coin Prices:&lt;/p&gt;
&lt;p class=&quot;usd&quot;&gt;USD: $30&lt;/p&gt;
&lt;p class=&quot;eur&quot;&gt;EUR: €30&lt;/p&gt;
&lt;p class=&quot;ils&quot;&gt;ILS: ₪30&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年6月5日 04:36:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76402321.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定