0

I'm building a tabbed content page. I was trying to build a form that would take a value from the form and create a new tab and also create a new div that would attach to the tab, that would be triggered by an on click function. I was having some trouble creating the div, it didn't seem to launch. When the value is entered, the tab is supposed to go active so the content would show up. I think I'm either doing something wrong with the new div or the on click function. I wasn't sure if those two code pieces should be combined, since they seemed to be in conflict. Thanks.

jQuery(document).ready(function() {
  jQuery('.tabs .tab-links a').on('click', function(e) {
    var currentAttrValue = jQuery(this).attr('href');
    $('.tabs ' + currentAttrValue).show();
    $('.tabs ' + currentAttrValue).animate({
      opacity: 1,
      paddingLeft: '30%'
    }, 400);
    $('.tabs ' + currentAttrValue).siblings().css({
      opacity: 0,
      paddingLeft: '0%'
    });
    $('.tabs ' + currentAttrValue).fadeIn(400).siblings().hide();
    jQuery(this).parent('li').addClass('active').siblings().removeClass('active');
    e.preventDefault();
  });
});

$(function() {
  var $textInput = $('input:text');
  $('#examine').on('submit', function(e) {
    e.preventDefault();
    var newText = $textInput.val();
    $('ul:last').append('<li><a href="#tab5">Searching...</a></li>');
    $('#tab-content').append('<div id ="tab5' + '"class="tab active"><p>the quick brown fox</p></div>');
    jQuery(this).parent('li').addClass('active').siblings().removeClass('active');
    $textInput.val('');
  });
});
.tab-links {
  float: left;
}
.tab-links:after {
  display: block;
  clear: both;
  content: '';
}
.tab-links li {
  list-style-type: none;
  background-color: #303030;
  border-bottom: 3px solid #858585;
  font-family: 'Jacques Francois', serif;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  margin-left: -25%;
}
.tab-links li a {
  color: #f2f2f2;
  display: block;
  padding: 3px 10px 3px 10px;
  text-decoration: none;
}
.tab-links a:hover {
  background: #a7cce5;
  text-decoration: none;
}
.tab-links li.active,
.tab-links li.hover {
  background-color: #e5e5e5;
  border-bottom: 3px solid #e5e5e5;
}
.tab-links li.active a,
.tab-links li a:hover {
  color: #666;
  background-color: #e5e5e5;
}
/*----- Content of Tabs -----*/

.tab-content {
  background-color: #e5e5e5;
  color: #666;
  min-height: 150px;
  overflow: auto;
}
#tab1 {
  padding-left: 30%;
}
#tab2,
#tab3,
#tab4,
#tab5 {
  display: none;
  opacity: 0;
  padding-left: 0%;
}
.tab-content p {
  margin: 20px;
  text-indent: -40%;
}
.tab-content.active {
  display: block;
  text-indent: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="sidebar">
  <div id="explore">
    <form id="examine">
      <p>Search</p>
      <input type="search" name="explore" placeholder="Search Items" />
      <p>Choose Your Search Restrictions</p>
      <input type="radio" name="location" required="required" value="Your School" />Inside
      <input type="radio" name="location" required="required" value="Whole system" />Outside
      <input type="submit" value="Search" />
    </form>
  </div>
  <div class="tabs">
    <ul class="tab-links">
      <li class="active"><a href="#tab1">Tab1</a>
      </li>
      <li><a href="#tab2">Tab2</a>
      </li>
      <li><a href="#tab3">Tab3</a>
      </li>
      <li><a href="#tab4">Tab4</a>
      </li>
    </ul>
    <div class="tab-content">
      <div id="tab1" class="tab active">
        <p>Tab1 content</p>
      </div>
      <div id="tab2" class="tab">
        <p>Tab2 content</p>
      </div>
      <div id="tab3" class="tab">
        <p>Tab3 content</p>
      </div>
      <div id="tab4" class="tab">
        <p>Tab4 content</p>
      </div>
Mark Schultheiss
  • 32,614
  • 12
  • 69
  • 100
K.Thomas
  • 15
  • 3

2 Answers2

1
  • First off you do not need two document ready handlers.
  • For clarity, I have added the NEW index to the "Searching..." string so you may need to edit that.
  • Use the index to get the new ID and append that to the list.
  • cache the tab and not process DOM for the tab
  • I assume you have some need for $textInput.val(''); so I left it
  • put your click handler on the .tab-links so new ones will have it (not on a1)
  • consider using classes and indexes instead of new IDs for tab5 etc.
  • if you use classes you could then clone the last tab and put in new content into the clone, making it more maintainable if the markup changes
  • I put a trigger on the newly added tab to activate it - it SEEMED as if that was your desire?
  • Consider a BUTTON rather than <input type="submit"...

Revised code:

jQuery(document).ready(function() {
  jQuery('.tabs').find('.tab-links').on('click', 'a', function(e) {
    var currentAttrValue = jQuery(this).attr('href');
    // cache instead of multiple
    var thisTab = $(currentAttrValue);
    thisTab.show().animate({
      opacity: 1,
      paddingLeft: '30%'
    }, 400);
    thisTab.siblings().css({
      opacity: 0,
      paddingLeft: '0%'
    });
    thisTab.fadeIn(400).siblings().hide();
    jQuery(this).parent('li').addClass('active').siblings().removeClass('active');
    e.preventDefault();
  });

  var $textInput = $('input:text');
  $('#examine').on('submit', function(e) {
    e.preventDefault();
    var newText = $textInput.val();
    var newIndex = $('.tab-links').find('li').length + 1;
    $('.tab-content').append('<div id="tab' + newIndex + '" class="tab"><p>the quick brown fox ' + newIndex + '</p></div>');
    $textInput.val('');
    $('.tab-links').append('<li><a href="#tab' + newIndex + '">Searching...' + newIndex + '</a></li>');
    $('.tab-links').find('a').eq(newIndex - 1).trigger('click');
  });
});f

EDIT: Per comment, update if already at max count:

This is not super efficient but you can get started with this.

jQuery(document).ready(function() {
  jQuery('.tabs').find('.tab-links').on('click', 'a', function(e) {
    var currentAttrValue = jQuery(this).attr('href');
    //  console.log(currentAttrValue);
    var thisTab = $(currentAttrValue);
    thisTab.show().animate({
      opacity: 1,
      paddingLeft: '30%'
    }, 400);
    thisTab.siblings().css({
      opacity: 0,
      paddingLeft: '0%'
    });
    thisTab.fadeIn(400).siblings().hide();
    jQuery(this).parent('li').addClass('active').siblings().removeClass('active');
    e.preventDefault();
  });

  var maxTabCount = 5;
  var $textInput = $('input[type=search]');
  $('#examine').on('submit', function(e) {
    e.preventDefault();
    var newText = $textInput.val();
    var tabCount = $('.tab-links').find('li').length;
    var newIndex = tabCount + 1;
    var newText = $textInput.val() ? $textInput.val() : "Default Tab Text";
    if (tabCount < maxTabCount) {
      $('.tab-content').append('<div id="tab' + newIndex + '" class="tab"><p>the quick brown fox ' + newIndex + '</p></div>');
      $('.tab-links').append('<li><a href="#tab' + newIndex + '">Searching...' + newIndex + '</a></li>');
    } else {
      $('.tab-content').find('div.tab').last().find('p').html("New Search Content");
      $('.tab-links').find('li').last().find('a').html(newText);// new tab text
    }
    $textInput.val('');
    $('.tab-links').find('a').last().trigger('click');
  });
});
Mark Schultheiss
  • 32,614
  • 12
  • 69
  • 100
  • Growing pains, I'm still new at this. Thank you for the edit and update. I had forgot to mention that I wanted to only add one tab, if another value was entered the new li and div would delete the old and update to the new one. If I were to add upon this code, would it cause any "collision" of the code? – K.Thomas May 03 '16 at 20:52
-2

You are using id for tab-content instead of class. Use the following line:

 $('.tab-content').append('<div id ="tab5' + '"class="tab active">...</div>');

Replace this line jQuery('.tabs .tab-links a').on('click', function(e) with the following:

jQuery(document).on("click",".tabs .tab-links a",function() {
Sparky
  • 98,165
  • 25
  • 199
  • 285
Aparna
  • 255
  • 1
  • 8
  • That seems to still not resolve the problem. It doesn't appear to connect the div. – K.Thomas May 03 '16 at 17:39
  • Please use back-tick characters to surround any inline code and indent code blocks with four spaces. Edited. Thanks. – Sparky May 03 '16 at 18:16
  • My pleasure.. @K.Thomas – Aparna May 03 '16 at 18:36
  • 1
    Not a good practice to put the click handler on the `document`,. it should be on the `.tabs` or `.tab-links` wrappers instead – Mark Schultheiss May 03 '16 at 18:45
  • 1
    On the second append `'
    – Mark Schultheiss May 03 '16 at 18:47
  • @MarkSchultheiss yeah, agreed with your answer but when a new element gets added to DOM, then document click will work only not a normal click event. – Aparna May 04 '16 at 18:51
  • @Aparna attaching the event handler to the closest "fixed" element is preferable as it reduces the need to process the entire DOM when the click occurs on the target element. i.e `jQuery(".tabs").on("click",".tab-links a"...` Reference here in this question:http://stackoverflow.com/questions/12824549/should-all-jquery-events-be-bound-to-document – Mark Schultheiss May 05 '16 at 16:55