-2

What specific changes need to be made in the Bootstrap 5 example below in order for the following two things to occur:

  1. the "afterAcceptingTerms" div should be hidden until the user has clicked on the Accept Terms modal button, so that only the "beforeAcceptingTerms" div should be visible until the user has clicked on the Accept Terms modal button.
  2. the "afterAcceptingTerms" should become visible once the user clicks on the Accept Terms modal button, and the "beforeAcceptingTerms" div should be hidden once the user clicks on the Accept Terms modal button.

Here is the Bootstrap 5 code we are currently starting with, but you can see that the code example below fails to toggle the div classes as stated in the requirements above.

<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
    <title>Modal Popup Page</title>
    <link href="/assets/css/bootstrap.min.css" rel="stylesheet"> 
    <script src="/assets/js/popper.min.js"></script>
    <script src="/assets/js/bootstrap.min.js" ></script>
  </head>
  <body>
    <div class="wrapper" id="beforeAcceptingTerms">
      <section class="content-section">
        <p>You must click on the "I agree to the terms button" in order to see the content on this page.</p>
      </section>
  </div>
  <div class="wrapper" id="afterAcceptingTerms">
    <section class="content-section">
      <p>The page content goes here.  But this is only visible because you clicked on the Accept button on the modal in order to get the modal to go away.</p>
    </section>
  </div>
<!-- Modal -->
    <div class="modal fade" id="myModal" tabindex="-1" aria-labelledby="exampleModalLabel"   data-bs-backdrop="static" aria-hidden="true">
      <div class="modal-dialog" style="position: fixed;bottom: 0;left: 0;right: 0;">
          <div class="modal-content">
        <div class="modal-body">
            By using this site, you certify that you agree to our <a href="/terms">Terms of Use</a>.
        </div>
        <div class="modal-footer">
              <button type="button" class="btn btn-secondary" data-bs-dismiss="modal" onclick="localStorage.setItem('acceptTerms',1)">I agree to the Terms.</button>
        </div>
      </div>
      </div>
    </div>
    <script>
      let acceptTerms = localStorage.getItem('acceptTerms');
      if(acceptTerms != 1){
        var myModal = new bootstrap.Modal(document.getElementById('myModal'), {})
        myModal.show()
      }
    </script>
  </body>
</html>
halfer
  • 19,824
  • 17
  • 99
  • 186
CodeMed
  • 9,527
  • 70
  • 212
  • 364
  • SO is not a code-writing service - what have you tried? Break your problem up into smaller parts, and work on each. 1) You need to save the user's click on the modal button in local storage. I searched for "*javascript save click localstorage*" and found many examples (https://stackoverflow.com/q/19527579/6089612). 2) Hide / show the relevant `div`s. I searched for "*javascript show div*" (to change the state dynamically), and "*css show div*" (to set initial states) and ... many examples (https://stackoverflow.com/q/21070101/6089612, https://stackoverflow.com/q/20598568/6089612 resp.). – Don't Panic Dec 23 '22 at 21:35
  • 2
    PS - 3 paras of bold text does nothing except harm readability. – Don't Panic Dec 23 '22 at 21:37

1 Answers1

1

You forgot to add CDNs instead your local files.

(I added a button to clear local storage data for testing purpose).

What did I change?

        // Window onload event to display your content if users has accepted terms
        // calling checkTerms() function
        window.onload = (event) => {
            checkTerms();
        };

        const afterAcceptingTerms = document.getElementById('afterAcceptingTerms');
        const acceptTermsButton = document.getElementById('acceptTermsButton');

        // Added a listener to your accept terms button
        // removing inline onclick element attribute
        acceptTermsButton.addEventListener('click', function() {
            termsAccepted();
        });
        // Here we manage what to do when user click in the accept terms button
        // in this case with try/catch to prevent critical errors its good to send
        // errors like that (in a catch block) to a server for you stay on what errors users can experience
        function termsAccepted() {
            try {
                localStorage.setItem('acceptTerms',1);
            } catch (error) {
                alert('CRITICAL ERROR !!!! USER WILL NOT SEE THE CONTENT');
            }
            afterAcceptingTerms.classList.remove('none');
        }
        // Function called when window load !! To check if user has accept the terms !
        // I'm using try/catch because this is critical, if the localStorage can't be accessed
        // your content won't be shown
        function checkTerms() {
            let val = '';
            try {
                val = localStorage.getItem('acceptTerms');
            } catch (error) {
                alert('CRITICAL ERROR !!!! USER WILL NOT SEE THE CONTENT');
            }
            if (val === '1') {
            afterAcceptingTerms.classList.remove('none');
            } else {
                var myModal = new bootstrap.Modal(document.getElementById('myModal'), {})
                myModal.show()
            }
        }

Also added a .none class with (display:none) to your #afterAcceptingTerms element, it was essential this element starts with display:none. We are going to remove that class programmatically:

<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
    <title>Modal Popup Page</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
    <style>
        .none {
            display: none;
        }
    </style>
  </head>
  <body>
    <div class="wrapper" id="beforeAcceptingTerms">
      <section class="content-section">
        <p>You must click on the "I agree to the terms button" in order to see the content on this page.</p>
      </section>
      <button id="clearData">Clear storage data</button>
  </div>
  <div class="wrapper none" id="afterAcceptingTerms">
    <section class="content-section">
      <p>The page content goes here.  But this is only visible because you clicked on the Accept button on the modal in order to get the modal to go away.</p>
    </section>
  </div>
<!-- Modal -->
    <div class="modal fade" id="myModal" tabindex="-1" aria-labelledby="exampleModalLabel"   data-bs-backdrop="static" aria-hidden="true">
      <div class="modal-dialog" style="position: fixed;bottom: 0;left: 0;right: 0;">
          <div class="modal-content">
        <div class="modal-body">
            By using this site, you certify that you agree to our <a href="/terms">Terms of Use</a>.
        </div>
        <div class="modal-footer">
              <button type="button" id="acceptTermsButton" class="btn btn-secondary" data-bs-dismiss="modal">I agree to the Terms.</button>
        </div>
      </div>
      </div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
    <script>
        var clearData = document.getElementById('clearData');
        clearData.addEventListener('click', function() {
            localStorage.clear();
        });

        window.onload = (event) => {
            checkTerms();
        };

        const afterAcceptingTerms = document.getElementById('afterAcceptingTerms');
        const acceptTermsButton = document.getElementById('acceptTermsButton');

        acceptTermsButton.addEventListener('click', function() {
            termsAccepted();
        });

        function termsAccepted() {
            try {
                localStorage.setItem('acceptTerms',1);
                afterAcceptingTerms.classList.remove('none');
            } catch (error) {
                alert('CRITICAL ERROR !!!! USER WILL NOT SEE THE CONTENT');
            }
        }

        function checkTerms() {
            let val = '';
            try {
                val = localStorage.getItem('acceptTerms');
                if (val === '1') {
                afterAcceptingTerms.classList.remove('none');
                } else {
                    var myModal = new bootstrap.Modal(document.getElementById('myModal'), {})
                    myModal.show()
                }
            } catch (error) {
                alert('CRITICAL ERROR !!!! USER WILL NOT SEE THE CONTENT');
            }
        }
    </script>
  </body>
</html>
halfer
  • 19,824
  • 17
  • 99
  • 186
  • Thank you and +1 for getting most of it. But what would you alter in the code you gave in order for `beforeAcceptingTerms` to disappear after the user clicks on the button, per the requirements stated in the OP? – CodeMed Dec 23 '22 at 22:34
  • Yes I forgot to mention what I changed in the code XD , i added a class .none with display:none in #beforeAcceptingTerms element ,now when users click in accept terms trigger a function that remove this class (.none) displaying the element #beforeAcceptingTerms and saves the option in local storage, also i added a event onload on page to check local storage and also removing .none class . Note: Now #beforeAcceptingTerms start with display:none ! (what makes sense) – Edvaldo Filho Dec 23 '22 at 23:07