I currently have a setup with a form spread out over a number of tab panes. When a user navigates away from a tab, I only want them to be allowed to do so if the form is filled out correctly.
I thought cancelling the "show" event would do it, but it turns out the action of showing a pane isn't dependant on the success of the "show" event propagating.
I've patched the Tab functionality for my use, but would the powers-that-be consider this patch if I made it a pull request, or should I not bother?
tabs will show even with css only. If you want to do this you will have to use jquery and target those elements in the page.
Do you have the code that you used? I do not see a fork on your site for this. I'm looking for the same thing.
The change is in the show() function where the work of triggering is only done .on('show.bootstrap'). I had to namespace the show event in the plugin, in case additional event listeners get added.
!function( $ ){
"use strict"
/* TAB CLASS DEFINITION
* ==================== */
var Tab = function ( element ) {
this.element = $(element)
}
Tab.prototype = {
constructor: Tab
, show: function () {
var $this = this.element
, self = this
, $ul = $this.closest('ul:not(.dropdown-menu)')
, selector = $this.attr('data-target')
, previous
, $target
if (!selector) {
selector = $this.attr('href')
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
}
if ( $this.parent('li').hasClass('active') ) return
previous = $ul.find('.active a').last()[0]
$this.on('show.bootstrap',function(){
$target = $(selector)
self.activate($this.parent('li'), $ul)
self.activate($target, $target.parent(), function () {
$this.trigger({
type: 'shown'
, relatedTarget: previous
})
})
$this.off('show.bootstrap');
});
$this.trigger({
type: 'show'
, relatedTarget: previous
});
}
, activate: function ( element, container, callback) {
var $active = container.find('> .active')
, transition = callback
&& $.support.transition
&& $active.is('.fade')
function next() {
$active
.removeClass('active in')
.find('> .dropdown-menu > .active')
.removeClass('active in')
element.addClass('active')
if (transition) {
element[0].offsetWidth // reflow for transition
element.removeClass('out').addClass('in')
} else {
element.removeClass('fade')
}
if ( element.parent('.dropdown-menu') ) {
element.closest('li.dropdown').addClass('active')
}
callback && callback()
}
transition ?
$active.one($.support.transition.end, next) :
next();
var nextLoc = element.siblings().andSelf().index(element);
var currLoc = $active.siblings().andSelf().index($active);
if(nextLoc > currLoc){
$active.removeClass('in').addClass('out');
$active.next().removeClass('out in');
}
else
$active.removeClass('out in');
}
}
Thanks!!
Actually now that I thought about it and I know it's going to be different for each case, but it seems like one of the problems is if you are using the data-toggle='tab' or data-toggle='pill', that function in the tab data-api is going to get called.
If you do the following:
$('#formTab a').click(function (e) {
e.preventDefault();
if($("#form-contact").valid()){
$(this).tab('show');
}
});
That is working for me. I'm using jQuery validator and it only checks the displayed form elements. So now it can check for validity and if it is valid, show that tab.
you can just call e.preventDefault() on the show event.
Most helpful comment
Actually now that I thought about it and I know it's going to be different for each case, but it seems like one of the problems is if you are using the data-toggle='tab' or data-toggle='pill', that function in the tab data-api is going to get called.
If you do the following:
That is working for me. I'm using jQuery validator and it only checks the displayed form elements. So now it can check for validity and if it is valid, show that tab.