MyBB Community Forums

Full Version: tabs(); jQuery (answer found, thank you!!)
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I'm exploring the intricacies of the JQuery UI, because, well, I've been dragging my feet and it's about time I did.

Anyway, I've noticed when I make the tabs portion a list the code works perfectly, however normal divs do NOT. For instance, this works:

<div id="tabs">
<ul>
<li><a href="#tabs-1"><div>this 1</div></a></li>
<li><a href="#tabs-2"><div>this 2</div></a></li>
</ul>
<div id="tabs-1">this 1 content</div>
<div id="tabs-2">this 2 content</div>
</div>

However, this does not:
<div id="tabs">
<a href="#tabs-1"><div>this 1</div></a>
<a href="#tabs-2"><div>this 2</div></a>

<div id="tabs-1">this 1 content</div>
<div id="tabs-2">this 2 content</div>
</div>

Literally the only thing that is different is the fact that the list is gone. Which, from what I'm able to see, read, research etc. really shouldn't have any effect. Seriously, what gives? Does anyone know what's going on?
It is possible that the jQuery ui is looking for an ul li list.
For your first example putting a div inside of an anchor is plain weird... Anchors should only contain inline elements and may have their own CSS class, so really there is no need for a div there. Divs are block elements.

I'm fairly sure jQuery UI looks for list elements because it makes sense. The list is like a table of contents, and the divs contain the content. The second example just looks messy to me.

Also, if you look through the jQuery UI source code on GitHub you see the following:

	_getList: function() {
		return this.element.find( "ol,ul" ).eq( 0 );
	},

This function attempts to find the list elements that comprise the navigation for the tabs


Likewise, the show function also looks for list elements:

	// handles show/hide for selecting tabs
		function show() {
			eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );

			if ( toShow.length && that.options.show ) {
				that._show( toShow, that.options.show, complete );
			} else {
				toShow.show();
				complete();
			}
		}

		// start out by hiding, then showing, then completing
		if ( toHide.length && this.options.hide ) {
			this._hide( toHide, this.options.hide, function() {
				eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
				show();
			});
		} else {
			eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
			toHide.hide();
			show();
		}

		toHide.attr({
			"aria-expanded": "false",
			"aria-hidden": "true"
		});
		eventData.oldTab.attr( "aria-selected", "false" );
		// If we're switching tabs, remove the old tab from the tab order.
		// If we're opening from collapsed state, remove the previous tab from the tab order.
		// If we're collapsing, then keep the collapsing tab in the tab order.
		if ( toShow.length && toHide.length ) {
			eventData.oldTab.attr( "tabIndex", -1 );
		} else if ( toShow.length ) {
			this.tabs.filter(function() {
				return $( this ).attr( "tabIndex" ) === 0;
			})
			.attr( "tabIndex", -1 );
		}

		toShow.attr({
			"aria-expanded": "true",
			"aria-hidden": "false"
		});
		eventData.newTab.attr({
			"aria-selected": "true",
			tabIndex: 0
		});
	},
Right, the HTML list is required for the list to work properly. But you can always modify the lists in CSS so that they don't have any bearing on your code and its as if they aren't there. Something as simple as #tabs li {display: block;list-style: none;} should be enough to make it function how you want, just as anchors.
The list styling was the main issue, and something I was trying to avoid if I could. If it's built into the UI though, there's not a whole lot I can do with it besides rig up my own javascript, so I'll take the path of most-laziness. I appreciate the clarification on these points!

(The reason I put the a around the div is so that clicking on the whole div, as opposed to just the word, is "clickable". It's worked fine with no problems in the past for me, regardless of should or should not. I'm not wrapping whole tables with it mind you, because wtf why, but there's the logic behind it at least, if you were curious. I get that question a lot, as it's something I frequently do. Not correct, no, but a habit of mine I've run across zero reasons to break XD)
And what is the problem with putting a span element around them in a link instead of a div. Same output, but it's semantically correct (span is an inline element) Smile

And as audentio said, you can apply all of the styling you were going to apply to the divs to the list elements anyway, and give then "display:block; list-style:none;".

Really it's just a habit you need to break. I don't really see any situation where you NEED to use div over span