Javascript or OLD JQuery accordion animations on one page without switching to each other

I'm trying to make reusable Javascript pieces and keep hitting the wall. This is currently annoying, but I have a slideshow with the same basic problem. I've searched for it several times but I don't think I am using the correct words ...

Purpose: Make a div using a class. Inside there are multiple divs (not always the same number) with the accordion class. Let the first of the accordion items in each div convention be visible while the rest are toggled closed (the div inside the accordionItem changes visibility and the h4 acts like a cue.) When you click on the invisible section, it switches to visible and the old one toggles. I want more than one of them on the page and their visibility and toggle does not affect each other. I don't need animations or any complex behavior.

Largest Limitation: I'm currently stuck using a site that can't get past jQuery 1.4.2 (moving to the top breaks the homepage menu and the IT department doesn't want to deal with fixing it and I don't have access). So I can't name a higher version without breaking the menu, but finding an accordion script (or whatever) that works on the site is a pain.

Other restrictions, I prefer the accordion if it breaks, breaks with all visible parts, so all information is still available. They are used to make the page shorter, but we need the information available.

How I worked on the problem. I copy javascript and make another one with changed class names every time I need a new acccordion, which is funny, but I don't know, Understand javascript well enough to do anything else. I am playing with html and css more so didn't create this javascript. I have the same basic slideshow problem, it works with jquery which I am stuck with, but I cannot figure out how to keep two instances of the slideshow from sucking into one.

I know I want this to be basically for every div convention to hide all accordion elements, show the first one, and when I click on another, only change the specific consent I'm in. Alternatively, if it inserted ids dynamically (so I don't need to inject them into the page code) and run it that way, that would be fine. I'm trying to make it so that someone who doesn't know how the code works can use it easily.

CSS and Javascript;

    <script type="text/javascript" src="https://code.jquery.com/jquery-1.4.2.min.js"></script>

<style>

      .accordionItem h4 { margin: 0;  font-size: 15px;  padding: 10px 20px 10px 10px; color: #fff; background: url('/images/image.aspx?iid=10691') right center no-repeat #fff;color: #a50050;  font-weight:600; font-family: 'Lucida Sans', Verdana, Arial, Sans-Serif; line-height: normal;}
      .accordionItem h4:hover { cursor: pointer; }
      .accordionItem div { margin: 0; padding: 1em 0.4em; background-color: rgba(165, 0, 80,.05); border-bottom: 1px solid #ccc; }
      .accordionItem.hide h4 { color: #a50050; background-color: #fff; font-weight:400; background: url('/images/image.aspx?iid=10690') right center no-repeat; border-bottom: 1px solid #ccc;}
      .accordionItem.hide div { display: none; }  

</style>


<script type="text/javascript">
    //<![CDATA[

    var accordionContainers = new Array();// ADDED BY ME
    var accordionItems = new Array();


    function init() {

    //Find each accordion ADDED BY ME
    var accordDivs = document.getElementsByTagName( 'div' );
    for ( var i = 0; i < accordDivs.length; i++) {
        if (accordDivs[i].className == 'accord') accordionContainers.push( accordDivs[i] );
        }

      // Grab the accordion items from each div 
      var divs = document.getElementsByTagName( 'div' );
      for ( var i = 0; i < divs.length; i++ ) {
        if ( divs[i].className == 'accordionItem' ) accordionItems.push( divs[i] );
      }

      // Assign onclick events to the accordion item headings
      for ( var i = 0; i < accordionItems.length; i++ ) {
        var h4 = getFirstChildWithTagName( accordionItems[i], 'H4' );
        h4.onclick = toggleItem;
      }

      // Hide all accordion item bodies except the first
      for ( var i = 1; i < accordionItems.length; i++ ) {
        accordionItems[i].className = 'accordionItem hide';
      }
    }

    function toggleItem() {
      var itemClass = this.parentNode.className;

      // Hide all items
      for ( var i = 0; i < accordionItems.length; i++ ) {
        accordionItems[i].className = 'accordionItem hide';
      }

      // Show this item if it was previously hidden
      if ( itemClass == 'accordionItem hide' ) {
        this.parentNode.className = 'accordionItem';
      }
    }

    function getFirstChildWithTagName( element, tagName ) {
      for ( var i = 0; i < element.childNodes.length; i++ ) {
        if ( element.childNodes[i].nodeName == tagName ) return element.childNodes[i];
      }
    }

    //}

     //]]>
       window.onload = function()
      {
      init();
     };

    </script>

      

I figured out how to find all the consonant divs on the page, but couldn't figure out what to do with them.

Example Stripped down Accordions: (This code works, but all accordionItems are considered the same, so they all switch together. The surrounding div doesn't agree in the original javascript, I added it at the beginning trying to figure out how to toggle one section at a time.)

    <div style="width:50%">
    <div class="accord">
    <div class="accordionItem">
      <h4>Headline</h4>
      <div>
        <p>Copy to Initially Show</p>
      </div>
    </div>

    <div class="accordionItem">
      <h4>Headline</h4>
      <div>
        <p>Copy to hide</p>
      </div>
    </div>

    <div class="accordionItem">
      <h4>Headline</h4>
      <div>
        <p>Copy to Hide </p>
      </div>
    </div>
</div><!-- END accord-->

<p>Blah blah blah to break up the page<p>
<div class="accord">
    <div class="accordionItem">
      <h4>Headline</h4>
      <div>
        <p>Copy to Initially Show</p>
      </div>
    </div>

    <div class="accordionItem">
      <h4>Headline</h4>
      <div>
        <p>Copy to hide</p>
      </div>
    </div>

    <div class="accordionItem">
      <h4>Headline</h4>
      <div>
        <p>Copy to Hide </p>
      </div>
    </div>
</div><!-- END accord-->
</div>

      

Thanks for any answers, especially the ones with long, twisted explanations that the ridiculously obvious thing I am missing ... I also love the examples.

+3


source to share


2 answers


The problem is this:

for ( var i = 0; i < accordionItems.length; i++ ) {
        var h4 = getFirstChildWithTagName( accordionItems[i], 'H4' );
        h4.onclick = toggleItem;
 }

      

It accordionItems

contains the entire list of accordion elements.

In the function, toggleItem

you iterate over the entire list again and switch the class hide

. Instead, you need to define a target and find its parentNode. And inside that parentNode, you have to switch the class.



You need to change the function toggleItem

like this:

  function toggleItem() {

  var itemClass = this.parentNode.className;

  var accord =  this.parentNode.parentNode.querySelectorAll("div");

 // get that parent alone and it children div

  for ( var i = 0; i < accord.length; i++ ) {
    accord[i].className = 'accordionItem hide';
  }


  // Show this item if it was previously hidden
  if ( itemClass == 'accordionItem hide' ) {
     this.parentNode.className = 'accordionItem';
  }
}

      

DEMO

0


source


If you are comfortable using jQuery (as already pointed out on your page), then a fairly straight forward solution is available. I've included a demo page showing how this can be done simply in jQuery.

I have commented this out to explain each step. If you put it into production, you probably want to remove some of the less useful ones. You will notice that the main methods I chose were . Closest (selector) and .children (selector).

The method .closest()

is useful for finding the parent of the target according to the selector (I found the closest one in this case .accord

, since it is the sibling .accordianItem

s parent ). This is important because we don't want to switch other div .accordianItem

s' that are not related. The parent .accord

isolates siblings from other elements on the page that are of the same class.



The method .children()

is useful for finding only immediate children that match a given selector. This is useful for capturing only the immediate child div

. Something to keep in mind, sometimes people prefer to use a specific class for the part of the content that needs to be hidden to avoid accidentally hiding other elements. An example of this is that we would have to add a footer as such:

<div class="collapse-item">
  <h4>Header</h4>
  <div class="content">
  </div>
  <div class="footer">
  </div>
</div>

      

When hiding the content (in this case .content

) and we don't want to hide our footer, instead, we should use a selector div

instead when searching through . Just something to think about.div

.content

.children()

0


source







All Articles