jqueryjquery-mobilejquery-mobile-popupjquery-mobile-navbar

Jquery Mobile error dynamically changing Tab, doesn't make tab active


I have 3 tabs within a pop up. Depending on which hyperlink is clicked, I'd like it to go to make a specific tab active.

Having stripped out all non-essential code, it seems that it fails if the hyperlink has a 'ui-btn' class applied to it. If the link is left unstyled then it works fine. It selects the correct tab, but it doesn't make the navbar link active/highlighted.

Is anyone able to shed any light on this? Or a simple work around.

Please see JSFiddle Demo

HTML

<div data-role="popup" id="CC_dayformPopup" data-history="false" data-dismissible="false">

<main class="ui-content">
<form action="" method="post" id="CC_dayform" data-ajax="false">

<div data-role="tabs" id="tabs">
  <div data-role="navbar">Type:
    <ul>
      <li><a href="#CC_OO_tab" data-ajax="false" id="CC_OO_tab_link">OO</a></li>
      <li><a href="#CC_CLO_tab" data-ajax="false" id="CC_CLO_tab_link">CLO</a></li>
      <li><a href="#CC_DO_tab" data-ajax="false" id="CC_DO_tab_link">DO</a></li>
    </ul>
  </div>

  <div id="CC_OO_tab">
        <div class="ui-field-contain">
            <fieldset data-role="controlgroup">
                <input type="checkbox" name="OO_req" id="CC_OO_req" />
                <label for="CC_OO_req">OO</label>
            </fieldset>
        </div>
    </div>

  <div id="CC_CLO_tab">
        <div class="ui-field-contain">

            <fieldset data-role="controlgroup">
            <input type="checkbox" name="CLO_req" id="CC_CLO_req" />
            <label for="CC_CLO_req">CLO</label>
            </fieldset>
        </div>

    </div>
    <div id="CC_DO_tab">
        <div class="ui-field-contain">
            <fieldset data-role="controlgroup">
                <input type="checkbox" name="DO_req" id="CC_DO_req" />
                <label for="CC_DO_req">DO</label>
            </fieldset>
        </div>
</div>

<fieldset data-role="controlgroup" data-type="horizontal" class="ui-mini">
<button type="submit" form="CC_dayform">Save</button>
<a href="#" data-rel="back" onclick="document.getElementById('CC_dayform').reset();" class="ui-btn ui-corner-all ui-shadow ui-btn-a">Cancel</a>
</fieldset>

</form>
</main>
</div>



These don't work...
<a href="#CC_dayformPopup" data-rel="popup" data-transition="pop" onclick="editDayform('1','on','','');" class="ui-btn ui-btn-a ui-btn-inline">OO chosen</a> 
<a href="#CC_dayformPopup" data-rel="popup" data-transition="pop" onclick="editDayform('1','','on','');" class="ui-btn ui-btn-a ui-btn-inline">CLO chosen</a> 
<a href="#CC_dayformPopup" data-rel="popup" data-transition="pop" onclick="editDayform('1','','','on');" class="ui-btn ui-btn-a ui-btn-inline ">DO Chosen</a>
As they're 'ui-btn'
<br />
These work--><a href="#CC_dayformPopup" data-rel="popup" data-transition="pop" onclick="editDayform('1','on','','');" >OO chosen</a> 
<a href="#CC_dayformPopup" data-rel="popup" data-transition="pop" onclick="editDayform('1','','on','');">CLO chosen</a> 
<a href="#CC_dayformPopup" data-rel="popup" data-transition="pop" onclick="editDayform('1','','','on');">DO Chosen</a> as they have no 'ui-btn'

Jquery

function editDayform(day, OO, CLO, DO) {
  if (OO == 'on') {
    $('#CC_OO_tab_link').trigger('click');
  } else if (CLO == 'on') {
    $('#CC_CLO_tab_link').trigger('click');
  } else if (DO == 'on') {
    $('#CC_DO_tab_link').trigger('click');
  }
  if (OO == 'on') {
    $('#CC_OO_req').prop('checked', true).checkboxradio('refresh');
  }
  if (CLO == 'on') {
    $('#CC_CLO_req').prop('checked', true).checkboxradio('refresh');
  }
  if (DO == 'on') {
    $('#CC_DO_req').prop('checked', true).checkboxradio('refresh');
  }
  return true;
}

Solution

  • First the solution of your problem.
    I'm not sure, what's exactly happens behind the scene. But if you click a jquery-mobile button .ui-btn, jquery-mboile will remove .ui-btn-active from all other buttons on your page and highlight the one that is clicked. This will take some time. But you are triggering the 'clicked' event on your tab immediately and before jquery-mobile is done with removeing all .ui-btn-active.
    If you delay $('#CC_OO_tab_link').trigger('click'); and 1 millisecond is already enough, it will work. See the Code snippet

    	function editDayform(day, OO, CLO, DO) {
    	  if (OO == 'on') {
    
    	    setTimeout(function() {
    	      $('#CC_OO_tab_link').trigger('click');
    	    }, 1);
    
    	  } else if (CLO == 'on') {
    	    setTimeout(function() {
    	      $('#CC_CLO_tab_link').trigger('click');
    	    }, 1);
    
    
    	  } else if (DO == 'on') {
            setTimeout(function() {
    	      $('#CC_DO_tab_link').trigger('click');
    	    }, 1);
    	  }
    	  if (OO == 'on') {
    	    $('#CC_OO_req').prop('checked', true).checkboxradio('refresh');
    	  }
    	  if (CLO == 'on') {
    	    $('#CC_CLO_req').prop('checked', true).checkboxradio('refresh');
    	  }
    	  if (DO == 'on') {
    	    $('#CC_DO_req').prop('checked', true).checkboxradio('refresh');
    	  }
    	  return true;
    	}
    <!-- jQuery -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
    <!-- jQuery Mobile -->
    <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jquerymobile/1.4.5/jquery.mobile.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquerymobile/1.4.5/jquery.mobile.min.js"></script>
    
    <div data-role="popup" id="CC_dayformPopup" data-history="false" data-dismissible="false">
    
      <main class="ui-content">
        <form action="" method="post" id="CC_dayform" data-ajax="false">
    
          <div data-role="tabs" id="tabs">
            <div data-role="navbar">
              Type:
              <ul>
                <li>
                  <a href="#CC_OO_tab" data-ajax="false" id="CC_OO_tab_link">OO</a>
                </li>
                <li>
                  <a href="#CC_CLO_tab" data-ajax="false" id="CC_CLO_tab_link">CLO</a>
                </li>
                <li>
                  <a href="#CC_DO_tab" data-ajax="false" id="CC_DO_tab_link">DO</a>
                </li>
              </ul>
            </div>
    
            <div id="CC_OO_tab">
              <div class="ui-field-contain">
                <fieldset data-role="controlgroup">
                  <input type="checkbox" name="OO_req" id="CC_OO_req" />
                  <label for="CC_OO_req">OO</label>
                </fieldset>
              </div>
            </div>
    
            <div id="CC_CLO_tab">
              <div class="ui-field-contain">
    
                <fieldset data-role="controlgroup">
                  <input type="checkbox" name="CLO_req" id="CC_CLO_req" />
                  <label for="CC_CLO_req">CLO</label>
                </fieldset>
              </div>
    
            </div>
            <div id="CC_DO_tab">
              <div class="ui-field-contain">
                <fieldset data-role="controlgroup">
                  <input type="checkbox" name="DO_req" id="CC_DO_req" />
                  <label for="CC_DO_req">DO</label>
                </fieldset>
              </div>
            </div>
    
            <fieldset data-role="controlgroup" data-type="horizontal" class="ui-mini">
              <button type="submit" form="CC_dayform">
                Save
              </button>
              <a href="#" data-rel="back" onclick="document.getElementById('CC_dayform').reset();" class="ui-btn ui-corner-all ui-shadow ui-btn-a">Cancel</a>
            </fieldset>
    
        </form>
      </main>
      </div>
    
      These don't work...
      <a href="#CC_dayformPopup" data-rel="popup" data-transition="pop" onclick="editDayform('1','on','','');" class="ui-btn ui-btn-a ui-btn-inline">OO chosen</a>
      <a href="#CC_dayformPopup" data-rel="popup" data-transition="pop" onclick="editDayform('1','','on','');" class="ui-btn ui-btn-a ui-btn-inline">CLO chosen</a>
      <a href="#CC_dayformPopup" data-rel="popup" data-transition="pop" onclick="editDayform('1','','','on');" class="ui-btn ui-btn-a ui-btn-inline ">DO Chosen</a>
      As they're 'ui-btn'
      <br />These work--><a href="#CC_dayformPopup" data-rel="popup" data-transition="pop" onclick="editDayform('1','on','','');">OO chosen</a>
      <a href="#CC_dayformPopup" data-rel="popup" data-transition="pop" onclick="editDayform('1','','on','');">CLO chosen</a>
      <a href="#CC_dayformPopup" data-rel="popup" data-transition="pop" onclick="editDayform('1','','','on');">DO Chosen</a> as they have no 'ui-btn'


    But your code looks very weird and there are a lot code smells in there.

    First: all the onclick() on your links. You should remove them and instead you should bind an event to the buttons.
    I added the buttons a class called .dayformButton and a custom data attr data-dayorm="". Then we bind a click event on the class dayformButton, if this event occurs, we look which button is clicked (with the data-dayform attr.) and then we save this attr into a var to make it available for the popup event listener.

    JQuery-mobile gives you a lot of different events for all the widgets. In this case we can take the events from the popup. The first event that we bind is beforeposition.

    Triggered before a popup computes the coordinates where it will appear

    Before the popup is visible on the screen, we trigger the click event on the right tab and check the right checkbox. You can change beforeposition to afteropen and you will see that the checkbox and the tab is activated right after the popup is opened.

    And in a last step we bind an event when the popup is closed. The jquery-mobile event afterclose

    Triggered when a popup has completely closed

    We use this event to reset the form, after the popup is closed. This way we remove the last onclick from your html.

    Your editDayform function looks also very weird. You're repeating yourself. You're doing 3 times the same thing, only with different ids. The easier way is to just change the id to a passed value. This way you get rid of all these if's and else's.

    	 // Set a global var
    	var dayform = null;
    
    	 // Bind a Click Event
    	$(".dayformButton").on('click', function() {
    	  // Which Button is clicked and set the global Var to this value
    	  dayform = $(this).data('dayform');
    	  console.log("Clicked: " + dayform);
    	});
    
    	 // Bind Events to the popup
    	$("#CC_dayformPopup").popup({
    	  beforeposition: function(event, ui) {
    	    // Select the matching tab and check the checkbox
    	    $('#CC_' + dayform + '_req').prop('checked', true).checkboxradio('refresh');
    	    $('#CC_' + dayform + '_tab_link').trigger('click');
    	  },
    
    	  afterclose: function(event, ui) {
    	    console.log("Popup closed");
    
    	    // Reset the form when the popup is closed
    	    $('#CC_dayform').trigger("reset");
    	  }
    
    
    	});
    <!-- jQuery -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
    <!-- jQuery Mobile -->
    <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jquerymobile/1.4.5/jquery.mobile.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquerymobile/1.4.5/jquery.mobile.min.js"></script>
    
    <div data-role="popup" id="CC_dayformPopup" data-history="false" data-dismissible="false">
    
      <main class="ui-content">
        <form action="" method="post" id="CC_dayform" data-ajax="false">
    
          <div data-role="tabs" id="tabs">
            <div data-role="navbar">
              Type:
              <ul>
                <li>
                  <a href="#CC_OO_tab" data-ajax="false" id="CC_OO_tab_link">OO</a>
                </li>
                <li>
                  <a href="#CC_CLO_tab" data-ajax="false" id="CC_CLO_tab_link">CLO</a>
                </li>
                <li>
                  <a href="#CC_DO_tab" data-ajax="false" id="CC_DO_tab_link">DO</a>
                </li>
              </ul>
            </div>
    
            <div id="CC_OO_tab">
              <div class="ui-field-contain">
                <fieldset data-role="controlgroup">
                  <input type="checkbox" name="OO_req" id="CC_OO_req" />
                  <label for="CC_OO_req">OO</label>
                </fieldset>
              </div>
            </div>
    
            <div id="CC_CLO_tab">
              <div class="ui-field-contain">
    
                <fieldset data-role="controlgroup">
                  <input type="checkbox" name="CLO_req" id="CC_CLO_req" />
                  <label for="CC_CLO_req">CLO</label>
                </fieldset>
              </div>
    
            </div>
            <div id="CC_DO_tab">
              <div class="ui-field-contain">
                <fieldset data-role="controlgroup">
                  <input type="checkbox" name="DO_req" id="CC_DO_req" />
                  <label for="CC_DO_req">DO</label>
                </fieldset>
              </div>
            </div>
    
            <fieldset data-role="controlgroup" data-type="horizontal" class="ui-mini">
              <button type="submit" form="CC_dayform">
                Save
              </button>
              <a href="#" data-rel="back" class="ui-btn ui-corner-all ui-shadow ui-btn-a">Cancel</a>
            </fieldset>
    
        </form>
      </main>
      </div>
    
      <a href="#CC_dayformPopup" data-rel="popup" data-transition="pop" data-dayform="OO" class="dayformButton ui-btn ui-btn-a ui-btn-inline">OO chosen</a>
      <a href="#CC_dayformPopup" data-rel="popup" data-transition="pop" data-dayform="CLO" class="dayformButton ui-btn ui-btn-a ui-btn-inline">CLO chosen</a>
      <a href="#CC_dayformPopup" data-rel="popup" data-transition="pop" data-dayform="DO" class="dayformButton ui-btn ui-btn-a ui-btn-inline ">DO Chosen</a>