2

I have a HTML page where I have two IFrames, and there are two buttons controlling which of them is visible.

Here is the index.html:

<!DOCTYPE html>
<html>
<head>
  <title>MyPage</title>
  <link rel="stylesheet" href="style.css" type="text/css">
</head>

<body onload="init()">
  <div class="main">
    <div class="leftbar">
        <button id="btn_1" class="leftbar-button" onclick="openTab(event, 'sec1')">Section1</button>
        <button id="btn_2" class="leftbar-button" onclick="openTab(event, 'sec2')">Section2</button>
    </div>

    <div id="sec1" class="tabcontent">
      <iframe src="section1.html"></iframe>
    </div>

    <div id="sec2" class="tabcontent">
      <iframe src="section2.html"></iframe>
    </div>    
  </div>

  <div id="clear" class="clear" style="clear: both; height: 0;"></div>

  <script src="main.js"></script>
</body>
</html>

Here is the main.js:

function onSwInit()
{
    // Set the home page to be displayed
    document.getElementById("sec1").style.display = "block";
    document.getElementById("btn_1").className += " active";
}

function openTab(evt, tabName)
{
  // Hide all content
  var i, tabcontent, tablinks;
  tabcontent = document.getElementsByClassName("tabcontent");
  for (i = 0; i < tabcontent.length; i++)
  {
    tabcontent[i].style.display = "none";
  }

  // Display the clicked section
  tablinks = document.getElementsByClassName("leftbar-button");
  for (i = 0; i < tablinks.length; i++)
  {
    tablinks[i].className = tablinks[i].className.replace(" active", "");
  }
  document.getElementById(tabName).style.display = "block";
  evt.currentTarget.className += " active";
}

Now, as one can see, by default, the page begins with btn_1 active and the corresponding IFrame section1.html visible. Now the problem is, suppose I want to share the URL of the page with the IFrame section2.html visible, how do I do it?

I am fine with a HTML, Javascript or PHP solution.

AndrewL64
  • 15,794
  • 8
  • 47
  • 79
mahesh
  • 1,028
  • 10
  • 24
  • 1
    You can add parameters at the end of a url that can be accessed in the code. Here is documentation on how to get these parameters in php: http://php.net/manual/en/reserved.variables.get.php – lfitzgibbons Jan 08 '19 at 22:38
  • 1
    As an aside, don't concatenate classnames like you're doing with `getElementById("btn_1").className += " active";` use the `element.classList` instead. If you have `var btn1 = document.getElementById("btn_1")` you can add and remove classes with `btn1.classList.add('active')` and `btn1.classList.remove('active')` – Stephen P Jan 08 '19 at 22:55
  • @Logiwan992 Thanks! That would be a good solution. Perhaps you could write it as an answer? – mahesh Jan 09 '19 at 10:07
  • @StephenP That is a good hint. Looks much more elegant! – mahesh Jan 09 '19 at 10:08

2 Answers2

3

JavaScript:

  1. Avoid using inline on* handlers (onclick, oninput, etc) and use event listeners within your JavaScript itself. Remove the onclick handlers and use querySelectorAll to retrieve all the buttons and assign them to a variable, say btns.

  2. Use forEach() to add a click event listener to each button in your btns variable that will load a function called say, toggleFrames().

  3. Inside that function, retrieve all the elements with class name tabcontent using querySelectorAll again and assign them to a variable, say frames.

  4. Use subtr() to retrieve the number from your button id e.g. the 2 in btn_2 which you will use to compare with the ids of each tab content in the variable frames.

  5. Use forEach() on the variable frames and check if the number in the id of the clicked button matches the number in the id of each tabcontent e.g. the 2 in sec2 and if they do, add the active class name and change the css display property of that element to block.

  6. Use window.location.href to retrieve the current page url and then use the search() method to check if the url string contains the id of one of your iframes. If there is a match, display that iframe and hide the other iframe.


Check and run the Code Snippet below for a practical example of the above:

//Check URL

function checkUrl() {
  var url = window.location.href;
  var frames = document.querySelectorAll('.tabcontent');
  frames.forEach(frame => {
    if( url.search( frame.id ) > 0 ) {
      frame.style.display = "block";
      frame.classList.add("active");
    } else {
      frame.style.display = "none";
      frame.classList.remove("active");
    }
  })
}

window.onload = checkUrl();

//Check Button Click

var btns = document.querySelectorAll(".leftbar-button");

function toggleFrame(e){
  var frames = document.querySelectorAll('.tabcontent');
 var x = e.target.id.substr(-1);
  frames.forEach(frame => {
   if(frame.id.includes(x)){
     frame.style.display = "block";
        frame.classList.add("active");
    } else {
     frame.style.display = "none";
        frame.classList.remove("active");
    }
  });
  
}

btns.forEach(btn => {
 btn.addEventListener("click", toggleFrame);
})
.tabcontent {padding:20px 10px;text-align:center;background-color: #000;color:#FFF;}
 <div class="main">
    <div class="leftbar">
        <button id="btn_1" class="leftbar-button">Section1</button>
        <button id="btn_2" class="leftbar-button">Section2</button>
    </div>
    <hr />
    <div id="sec1" class="tabcontent">
      <h1>
      Iframe 1 here
      </h1>
    </div>

    <div id="sec2" class="tabcontent" style="display: none;">
      <h1>
      Iframe 2 here
      </h1>
    </div>    
  </div>
AndrewL64
  • 15,794
  • 8
  • 47
  • 79
  • This answer doesn't solve my problem per se, but is a very useful idea. Can you tell me why using event listeners is better than handlers (I mean generally)? – mahesh Jan 09 '19 at 10:11
  • @mahesh As mentioned by @Alnitak [here](https://stackoverflow.com/questions/5871640/why-is-using-onclick-in-html-a-bad-practice#5871775), one of the reasons why you should avoid using inline handlers is because it mixes your **code**(here, *JavaScript*) and your **markup**(here, *HTML*) which is generally something we should avoid. Another reason to not use handlers is that the handlers end up going through `eval()` and running in the global scope. – AndrewL64 Jan 09 '19 at 10:34
  • 1
    `Event listeners` however, not only avoid the above problems but they also allow us to bind multiple functions to a single event which is not possible with handlers regardless of whether they are inline or not. – AndrewL64 Jan 09 '19 at 10:34
  • Check out the other answers [here](https://stackoverflow.com/questions/5871640/why-is-using-onclick-in-html-a-bad-practice) for other reasons why using inline handlers and/or non-inline handlers in general is a bad practice. – AndrewL64 Jan 09 '19 at 10:36
  • 1
    @mahesh I have edited the code. Check **Point 6** as well as the first few lines of the code snippet to see how you can display the iframe based on your url. – AndrewL64 Jan 09 '19 at 11:56
  • Now whenever you try to access say `www.yourWebsite.com/somePage/#sec2` or `www.yourWebsite.coma/somePage?sec2`, the iframe `sec2` will be displayed by default. – AndrewL64 Jan 09 '19 at 11:58
1

PHP:

You can't; that's the whole point of a single page application (SPA). If you want to be able to share individual iframes, you'll need to navigate to section2.html directly. Naturally, that won't have any of the surrounding content.

If you want that surrounding content (to be visible on each page), you'd be better off making use of HTML Imports, jQuery.load(), or better yet, PHP includes:

Page 1:

<?php include('header.php'); ?>
<!-- iframe content -->
<?php include('footer.php'); ?>

Page 2:

<?php include('header.php'); ?>
<!-- iframe content -->
<?php include('footer.php'); ?>

header.php:

<!DOCTYPE html>
<html>
<head>
  <title>MyPage</title>
  <link rel="stylesheet" href="style.css" type="text/css">
</head>

<body onload="init()">
  <div class="main">
    <div class="leftbar">
        <button id="btn_1" class="leftbar-button" onclick="openTab(event, 'sec1')">Section1</button>
        <button id="btn_2" class="leftbar-button" onclick="openTab(event, 'sec2')">Section2</button>
    </div>

footer.php:

  <div id="clear" class="clear" style="clear: both; height: 0;"></div>

  <script src="main.js"></script>
</body>
</html>
AndrewL64
  • 15,794
  • 8
  • 47
  • 79
Obsidian Age
  • 41,205
  • 10
  • 48
  • 71
  • It is one way to solve it, but that would still mean I have then two pages, which is what I am trying to avoid. – mahesh Jan 09 '19 at 10:09