How to properly update URL hash upon selecting a jQuery tab? - javascript

HTML:
<div id="tabs">
<ul>
<li>Settings</li>
<li>Fields</li>
</ul>
<div id="settings">
//Tab Contents
</div>
<div id="fields">
//Tab Contents
</div>
</div>
How can I apply jQueryUI's Tab functionality and force it to update the URL hash upon selecting a new tab?

Use this code to create your jQuery UI tabs:
$('#tabs').tabs({
beforeActivate: function (event, ui) {
window.location.hash = ui.newPanel.selector;
}
});
I created this answer because I cannot find a single one with an up-to-date method. Hope this helps somebody else!

Besides updating the hash on tab change (with the beforeActivate event as in shruggernaut's reply) it is very useful to update the active tab on hash change (i.e. enabling browser history, back/forward buttons and user typing in the hash manually):
$(window).on('hashchange', function () {
if (!location.hash) {
$('#tabs').tabs('option', 'active', 0); // activate first tab by default
return;
}
$('#tabs > ul > li > a').each(function (index, a) {
if ($(a).attr('href') == location.hash) {
$('#tabs').tabs('option', 'active', index);
}
});
});

Related

Does an added class in jQuery carry over after page reload?

I'm trying to remember which tabs were open in my menu after reload. Here's my js:
$(document).ready(function () {
$(".sidebar div").hide();
$(".sidebar li a").click(function () {
// alert($(this).attr("class"));
var myClass=$(this).attr("class");
if ($("#div"+myClass).attr("class")!='active') {
$("#div"+myClass).slideToggle(); //open tab
$("#div"+myClass).addClass('active');
}
else {
$("#div"+myClass).slideToggle(); //close tab
$("#div"+myClass).removeClass('active');
}
});
});
It's constantly adding and taking away the class "active" each time I click on it. I also have this right below it:
$(window).load(function () {
$(".active").slideToggle();
});
Whenever I reload my page, even when a couple of tabs have an active class, they do not appear to be slideToggling. Am I doing this wrong? Is there an easy way around this?

activating jquery tabber based on link URL

I'm pretty new to jquery and I decided to build a jquery tabber. So far so good but I have a little problem!!! I cant see how I can activate the tabber based on the URL. For instance when the link is www.myweb.com#tab2, the second tabber becomes activated. My jquery is as follows.
$(document).ready(function() {
// When page loads...
$(".tab_content").hide(); //Hide all content
$("ul.tabs li:first").addClass("active").show(); //Activate first tab
$(".tab_content:first").show(); //Show first tab content
// On Click Event
$("ul.tabs li").click(function() {
$("ul.tabs li").removeClass("active"); //Remove any "active" class
$(this).addClass("active"); //Add "active" class to selected tab
$(".tab_content").hide(); //Hide all tab content
var activeTab = $(this).find("a").attr("href"); //Find the href attribute value to identify the active tab + content
$(activeTab).fadeIn(); //Fade in the active ID content
return false;
});
});
and HTML list as follows
<ul class="tabs">
<li>Design Team</li>
<li>Publications</li>
<li>Awards & Recognitions</li>
<li>Our Mission</li>
<li class="last-item">Company Profile</li>
</ul>
now when someone visit my website with this link www.mywebsite.com#tab3, I want tab3 to be activated. I know jquery tabber has this but I don't know how achieve this with my own jquery tabber. Any help will be greatly appreciated
Activate an item with href attribute equal to location.hash:
$(document).ready(function () {
var hash = location.hash;
$(".tab_content").hide(); //Hide all content
if ($("ul.tabs li a[href='" + hash + "']").length) { //check if such link exists
$("ul.tabs li a[href='" + hash + "']").parent().addClass("active"); //Activate tab
$(hash).show();
}
else {
$("ul.tabs li:first").addClass('active');
$(".tab_content:first").show()
}
}
Pretty simple. You can trigger click event based on your hash index.
This will work for you. If you refresh the page after clicking for say tab3 and your url contains hash index #tab3, your third tab will be focused automatically.
I assume that you have an id tab1, tab2, tab3, tab4 in your li or a tag and its viola.
Add these codes to your existing code without affecting them and you are done.
$(function(){
if(location.href.indexOf('#') != -1){
var namedAnchor = window.location.hash;
var findToTab = namedAnchor;
$(findToTab).trigger('click');
}
});
Edit:
How ever if you don't want to assign any ids to either li or a tag, you can do this.
$(function(){
if(location.href.indexOf('#') != -1){
var namedAnchor = window.location.hash;
var findToTab = namedAnchor;
$("ul.tabs li a[href='" + findToTab + "']").trigger('click');
}
});

Adding a click event inside jquery plugin while maintain access to main jquery object

In the below code I have a couple of unordered lists, and in the plugin I am attempting to fire a click event when the li element is clicked. How can I do this inside the plugin and still have access to the main ul jquery object?
See comments in code for further explanation
<ul class="testing">
<li>clicking this should fire a click event</li>
</ul>
<ul class="testing">
<li>clicking this should fire a click event</li>
</ul>
(function($) {
$.fn.myPlugin = function(options) {
return this.each(function() {
//how should I trigger the onClick when the li is clicked???
});
function onClick(){
console.log('you clicked an li');
//I also need access to the main ul element inside here
}
}
})(jQuery);
$(function() {
$('.testing').myPlugin();
});
(function($) {
$.fn.myPlugin = function(options) {
return this.find('li').click(onClick)
function onClick(){
console.log('you clicked an li');
$(this).parent(); // This is the <ul>
}
}
})(jQuery);
$(".testing").myPlugin()
Copy the following example and see if this helps solidify what you are attempting to accomplish.
The proof of getting to the main ul tags are the alerts. You will see I have created 'testing1' and 'testing2' classes. Depending on which li tag is clicked, the user will receive an alert of what class is associated to the parent ul tag of the clicked li tag.
I hope this helps!
<ul class="testing1">
<li>clicking this should fire a click event</li>
</ul>
<ul class="testing2">
<li>clicking this should fire a click event</li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
$('ul')
.on('click', 'li', function() {
$(this).myPlugin();
});
});
$.fn.myPlugin = function(options) {
return this.each(function() {
//how should I trigger the onClick when the li is clicked???
onClick(this);
});
function onClick(jqObj) {
console.log('you clicked an li');
//I also need access to the main ul element inside here
alert($(jqObj).parent('ul').attr('class'));
}
}
</script>

jQuery UI Tabs - Show all Tab

Hey everyone. I saw another post on using a specific jQuery UI tab to open all tab content at once. This is more or less a "show all" tab. It doesn't seem to be working for me. In any event, my page structure looks like this:
<div id="tabs">
<ul class="tabs-1">
<li><a href="#tabs-1"> Some Tab </li>
<li><a href="#tabs-2"> Some Tab </li>
<li><a href="#tabs-3"> Some Tab </li>
<li><a href="#"> Show All </li>
</ul>
<fieldset id="tabs-1"> Content </fieldset>
<fieldset id="tabs-2"> Content </fieldset>
<fieldset id="tabs-3"> Content </fieldset>
</div>
This is the JavaScript that I have used, based on a previous example:
var user_tabs = $("#tabs").tabs({
select: function(event, ui) {
if (ui.index == 3) {
$("fieldset[id^=tabs-]").show();
} else {
$("fieldset[id^=tabs-]").hide();
$(ui.panel).show()
}
}
});
The tabs that I use have initialized correctly, but the "show all tab" doesn't work at all
Any ideas?
Firstly, fix the html code within your tabs. You are missing the </a> for all the links.
Then change your last tab to:
<li> Show All </li>
add another panel (can be empty):
<fieldset id="tabs-4"></fieldset>
And change your javascript to this:
var user_tabs = $("#tabs").tabs({
show: function(event, ui) {
if (ui.index == 3) {
$("fieldset[id^='tabs-']").removeClass('ui-tabs-hide');
$("fieldset[id='tabs-4']").addClass('ui-tabs-hide');
}
}
});
(Note the change from select to show)
Example: http://jsfiddle.net/niklasvh/km7Le/
This works (for me) in jQuery-ui-1.10.0. Note that I use divs, not fieldsets as done in the question.
//Do the tabs
$('#tabs').tabs({
activate: function (event, ui) {
if (ui.newPanel.selector == "#tabs-4") {
$("div[id^='tabs-']").attr('style', "display:block;");
$("div[id^='tabs-']").attr('aria-expanded', true);
$("div[id^='tabs-']").attr('aria-hidden', false);
}
else {
$("div[id^='tabs-']").attr('style', "display:none;");
$("div[id^='tabs-']").attr('aria-expanded', false);
$("div[id^='tabs-']").attr('aria-hidden', true);
$(ui.newPanel.selector).attr('style', "display:block;");
$(ui.newPanel.selector).attr('aria-expanded', true);
$(ui.newPanel.selector).attr('aria-hidden', false);
}
}
});
In version jQuery UI 1.12 event changed to 'beforeActivate' and 'ui' and returns arguments newTab
So new function will look like:
var user_tabs = $("#tabs").tabs({
beforeActivate: function(event, ui) {
if (ui.newTab.find('a').attr('href') === '#tabs-4') {
$("fieldset[id^='tabs-']").removeClass('ui-tabs-hide');
$("fieldset[id='tabs-4']").addClass('ui-tabs-hide');
}
}
});
In JQuery UI Tabs 1.12.1, this works perfectly:
var user_tabs = $("#tabs").tabs(
{activate:
function(event, ui) {
if ( ui.newTab.find('a').attr('href') === '#tabs-4') {
$("div[id^='tabs-']").show();
}
}
}
)

JQuery UI: Disable accordion tab?

I have a JQuery UI accordion that contains different parts of the user workflow. I would like to disable accordion "tabs" that the user hasn't reached yet. (So if the user hasn't signed in yet, he can't yet publish content, etc.) Then, as the user completes the necessary steps, more tabs will become enabled.
Is there a way to do this? This doesn't work, even as a way to prevent any tabs from changing:
$("#accordion").accordion({
changestart: function(event, ui) {
return false;
}
});
You should add/remove the class "ui-state-disabled" to each header element (i.e. "<h3>") you want to disable/enable. Then use:
$( "#accordion" ).on( "accordionbeforeactivate", function (){
return ! arguments[1].newHeader.hasClass( "ui-state-disabled" );
})
To add/remove a class dyanamically, use:
$( "selector" ).addClass( "ui-state-disabled" );
$( "selector" ).removeClass( "ui-state-disabled" );
You can add a meaningul "id" attribute to each header element to simplify the "selector" part. For example, "step-1", "step-2", "step-n" for each step the user should traverse along the workflow.
You can try the following if you are positive about the position the tab to be disable has:
// Disable the first tab
$( "#accordion > h3:first-child" ).addClass( "ui-state-disabled" );
// Make sure the fourth tab is enabled
$( $( "#accordion > h3" )[3] ).removeClass( "ui-state-disabled" );
Also note that using "ui-state-disabled" is actually meaningful because it will render the header grayed (or whatever your theme makes disabled things look like).
Another note, if the tab you are dynamically disabling is currently active, it won't do anything special (i.e. it won't collapse or activate another tab). You can add extra logic to activate a default tab or do anything else.
This seems like it should be easier. But here's a solution:
The first thing we need to keep track of is which panels can be legally opened:
// Keep an array of the indexes that the user can open.
// [0,1] would allow ONLY the first and second panels
// to be opened
var available_indexes = [0,1];
Then, when you call your accordion, do it like this
$('#accordion').accordion({
header: 'h3',
change: function(event, ui) {
var newIndex = $(ui.newHeader).index('h3');
if (jQuery.inArray(newIndex, available_indexes) == -1) {
var oldIndex = $(ui.oldHeader).index('h3');
$(this).accordion( "activate" , oldIndex );
alert('That panel is not yet available');
}
}
});
So then, if you want to allow the user to access the third panel, you would do:
available_indexes.push(2);
$("#service_options_available h3").click(
function(e) {
if($(this).hasClass("empty")) {
e.stopImmediatePropagation();
return false;
}
}
);
$("#service_options_available").accordion({
autoHeight: false,
collapsible: true,
active: false,
header: 'h3',
changestart: function(event, ui) {
if($(ui.newHeader).attr("id") != null) {
alert($(ui.newHeader).attr("id"));
}
}
});
This has worked for me:
$("#accordionTabToDisable").click(function(){
$("#acordion" ).accordion( "option", "active",0); //maybe this line could be optional
return false;
});
The tab can be easily disable as below:
<p:tab title="First Tab Title" **disabled=”true”**>
To enable it you can use javascript to enable it again.
Diego Augusto Molina nailed it. ui-state-disabled class is the way to go: http://api.jqueryui.com/theming/css-framework/
Consider this piece of code that allows user go back, but not go to next accordion tab. We do it only programmatically, after proper validation:
function disableAccordionNextTabs () {
var $accordion = $(".accordion");
var active = $accordion.accordion('option', 'active');
var $headers = $accordion.find($accordion.accordion('option', 'header'));
$headers.addClass('ui-state-disabled');
for (var i = active; i >= 0; i--) {
$headers.eq(i).removeClass('ui-state-disabled');
}
}
None of the workarounds really worked for me. Would've been alot nicer if it was supported out of the box ofcourse, but here's the workaround i used. I bound the event to a custom event and added my own click event which can do whatever logic and trigger the customClick event if the navigation is allowed.
JS:
$('#accordion').accordion({
event: 'customClick'
});
$('#accordion > .ui-accordion-header').click(function() {
if(confirm ("Is this allowed?")){
$(this).trigger('customClick');
}
});
Or check out the working jsfiddle here: http://jsfiddle.net/hWTcw/
A pretty easy solution is grabbing the header (<h3>) by content:
$("h3:contains('panel name')").toggleClass('ui-state-disabled');
That way you can enable/disable with the same code or hide the panel all together with:
$("h3:contains('panel name')").toggle();

Categories