1

I'm basically adding an iframe inside my "panel" class. I want the iframe to display when the button has been clicked on and if its clicked on again, hide it. How would i go abouts doing this?

This is the html code for my accordion:

<button class="accordion">Link1</button>
    <div class="panel">
        <iframe src="linkcodehere" class="iframestreet" style="border:0; display:none; visibility: hidden;"></iframe>
        //some other code to display information
    </div>
<button class="accordion">Link2</button>
    <div class="panel">
        <iframe src="linkcodehere2" class="iframestreet" style="border:0; display:none; visibility: hidden;"></iframe>
        //some other code to display information
    </div>

This is the code for the javascript to display elements inside class panel:

$(document).ready(function() {
    var acc = document.getElementsByClassName("accordion");
    var i;
    var id = document.getElementsByClassName("iframestreet");

    for (i = 0; i < acc.length; i++) {
        acc[i].onclick = function() {
            this.classList.toggle("active");
            var panel = this.nextElementSibling;
            if (panel.style.maxHeight) { 
                panel.style.maxHeight = null;
            } else {
                panel.style.maxHeight = panel.scrollHeight + "px";
            }
            if (id[i].style.display == 'block'){ 
                console.log("hide this");
                id[i].style.display = 'none';
                id[i].style.visibility = 'hidden'; 
            } else {
                console.log("display it");
                id[i].style.display = 'block';
                id[i].style.visibility = 'visible';
            }
        }
    }
});

I'm getting this error when I look into my console log: Uncaught TypeError: Cannot read property 'style' of undefined

TBA
  • 63
  • 2
  • 9
  • Naming things `id` is not a great practice because it's used so much for id's and naming the accordion `acc` is not very readable either. You aren't going to really shave time off your program that way, and you'll likely add time to the work because it's confusing. I would also recomend creating a jsFiddle for this. – sheriffderek Mar 21 '17 at 18:11
  • `getElementByClass` is not a function. – Sean Kwon Mar 21 '17 at 18:12
  • Your HTML has some extra divs. – sheriffderek Mar 21 '17 at 18:12
  • Sorry fixed those issues, was rewriting my code, didn't want to copy/paste everything since it was too big. – TBA Mar 21 '17 at 18:16

2 Answers2

1

HTML:

<button id='hideshow'>Link1</button>
<div class="panel">
  <iframe src="linkcodehere" class="content" style="border:0;display:none"></iframe>
  <br/>
  <p class="content" style="display:none;">some stuff</p>
  <p class="content" style="display:none;">more stuff</p>
</div>
<button id="hideshow2">Link2</button>
<div class="panel2">
  <iframe src="linkcodehere2" class="content2" style="border:0; display:none;"></iframe>
  <br/>
  <p class="content2" style="display:none;">some stuff</p>
  <p class="content2" style="display:none;">more stuff</p>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

JavaScript/JQuery:

$(document).ready(function(){
  $('#hideshow').on('click', function(event) {        
     $('.content').toggle('show');
  });
});
$(document).ready(function(){
  $('#hideshow2').on('click', function(event) {        
     $('.content2').toggle('show');
  });
});

Working example: http://codepen.io/anon/pen/vxRxPm

James Douglas
  • 3,328
  • 2
  • 22
  • 43
  • Works fine however I have other elements tag inside class panel. How would i get it to display them? e.g. – TBA Mar 21 '17 at 18:45
  • Test1

    Test2

    – TBA Mar 21 '17 at 18:45
  • What would I need to addd to also display test1 and test2 on click of the button, thanks. – TBA Mar 21 '17 at 18:46
  • To show/hide an object in the div "panel" add the CLASS "content" and style "display:none;". – James Douglas Mar 21 '17 at 19:01
  • Why no $? and those events aren't being used and will raise errors in linters. – sheriffderek Mar 21 '17 at 19:13
  • I was wondering that as well; turns out jquery works as well, but $ is probably better, as it is more well known. Answer edited. Also, see this: http://stackoverflow.com/questions/3291680/jquery-syntax-when-to-use-dollar-vs-jquery – James Douglas Mar 21 '17 at 19:20
1

In my experience, accordions are almost always an unpleasant UI pattern for both the user and the developer.

That being said, there are many many ways you could do this. This is how I would approach it.

Notes from the OP's code: keep the variables readable + if you're going to use jQuery, just go all the way instead of using half and half. Get to know the standard API or the jQuery one until you know both. : )

jsFiddle: https://jsfiddle.net/sheriffderek/tfy11sas/

markup

<ul class='accordian js-accordian'>

  <li class='item js-item' data-name='one'>
    <button>open me</button>
    <div class='content'>
      <p>This is some content. It could be an iFrame or whatever you want. - but you'll have to set the height for an iFrame.</p>
    </div>
  </li>

  <li class='item js-item' data-name='two'>
    <button>open me</button>
    <div class='content'>
      <p>This is some content. It could be an iFrame or whatever you want. - but you'll have to set the height for an iFrame.</p>
    </div>
  </li>

</ul>


script

$(document).ready(function() {
  var $accordian = $('.js-accordian');
  var $items = $('.js-item');

    // set even click on the whole accordian and then check for js-item
  // this way you pair down how much is being watched
  $accordian.on('click', '.js-item', function() {
    console.log( $(this).data('name') );
    // just to show data-attributes for fun

    $items.removeClass('open');
    $(this).addClass('open'); // the item you clicked...
  });
});


CSS

.accordian {
  list-style: none;
  margin: 0;
  padding: 0;
  background: black;
}

.accordian .item {
  background: lightgray;
}

.accordian .content {
  height: 0;
  overflow: hidden;
}

.accordian .content p {
  margin: 0;
  padding: .5rem;
  background: white;
}

.accordian .item.open .content {
  height: auto;
}
sheriffderek
  • 8,848
  • 6
  • 43
  • 70