Opened 11 years ago

Closed 11 years ago

Last modified 3 years ago

#8735 closed bug (notabug)

activate event not fired for first tab when created

Reported by: Cardgage Owned by:
Priority: minor Milestone: 1.10.0
Component: ui.tabs Version: 1.9.1
Keywords: Cc:
Blocked by: Blocking:

Description

In versions which used the show event, that event was fired for the first tab when it was shown the first time. Now with the activate event, that event is not fired off for the first tab - the one selected by default.

http://jsfiddle.net/R2pBp/

In the example provided by the jsfiddle link, I expect to see the "active" alert as soon as the page loads, not just after going to another tab and then back to the first tab.

Change History (40)

comment:1 Changed 11 years ago by Cardgage

Here is a jsfiddle showing the old, expected behavior:

http://jsfiddle.net/uuGq4/

comment:2 Changed 11 years ago by Scott González

Resolution: notabug
Status: newclosed

This is by design. Use the create event.

comment:3 in reply to:  2 Changed 11 years ago by Cardgage

I have functionality that I want to happen when a tab is shown/activated, not when it is created. When a tab is created and then shown, it is made active. Why is it by design that the activate event is not executed when indeed a tab is being activated?

comment:4 Changed 11 years ago by Scott González

It is not being activated, it is active at the time of initialization. This is the equivalent of a change event being fired on page load for a select element because it starts with a value already selected.

comment:5 Changed 11 years ago by Cardgage

Here's my working scenario: When a tab is shown, I perform methods to assemble the content of that tab. So if the activate event doesn't fire for the first tab, nothing is shown for that tab. Nor is it possible to force an activate event because the 0th tab is already active. This doesn't seem like a rare use case and I'm having trouble thinking of a use case where a user would prefer the activate event didn't occur for the tab that is active by default.

comment:6 Changed 11 years ago by Cardgage

By "force an activate event", I mean to use the following code:

$(".tabs").tabs("option", "active", 0); this doesn't work

The jquery ui code recognizes that the 0th tab is already active and simply returns.

comment:7 Changed 11 years ago by Scott González

Please explain why you can't use the create event.

comment:8 Changed 11 years ago by Cardgage

Sure. The create event fires once for the whole tab control. The content that I'm assembling involves ajax calls and other code that I want to avoid if the user doesn't require the info for that tab (load on demand).

comment:9 Changed 11 years ago by Scott González

That doesn't explain why you can't use it. The create event tells you which tab is active (if any).

comment:10 Changed 11 years ago by Cardgage

OK, so your recommendation is to handle both the "create" and the "activate" events. That works and I'll move my code to that paradigm.

Let me point out that the upgrade guide doesn't mention this discrepancy between 1.8 and 1.9 in describing the switch from "show" to "activate" http://jqueryui.com/upgrade-guide/1.9/#deprecated-show-event-renamed-to-activate

Also, I'd like to reiterate that I can't see a scenario where a user would use the activate event expecting the current behavior. Anyone handling the activate event would need to handle both. Perhaps it's because I've only ever used it that way that I can't see another use for the activate event :)

comment:11 Changed 11 years ago by Scott González

Keywords: needsdocs added

Let me point out that the upgrade guide doesn't mention this discrepancy between...

Thanks, I'll add a note about this to the upgrade guide.

Also, I'd like to reiterate that I can't see a scenario where a user would use the activate event expecting the current behavior.

Do you not see the parallel to <select> elements? There are plenty of scenarios where users will handle the initial state fully on the server and subsequent states fully on the client.

comment:12 Changed 11 years ago by Scott González

Keywords: needsdocs removed

comment:13 Changed 10 years ago by nick4fake

I also suggest you to fix this.

comment:14 Changed 10 years ago by passgod

I also suggest you to fix this. It confuse me for long time,for the first tab have no active event when it's created. after create ,the first tab did ACTIVED,why no event ?

comment:15 Changed 10 years ago by nick4fake

Please, fix it. This "design" is silly.

comment:16 Changed 10 years ago by PawelRoman

This ticket should be reopened and this should be fixed because this design is seriously flawed. The answer to the question "Please explain why you can't use the create event." is this: Because I don't want to use different event to do THE SAME THINGS only because it's first tab. This is ridiculous to make me use create() event to handle something specifically for the FIRST tab and use activate() event for all other tabs. First tab is not special. It should be handled exactly like any other tabs.

My real-life case is this: I have tabs within tabs within tabs (2 to 4 levels), where 'leaf' tabs are ajax-loaded. I didn't want to initialize entire 'tab tree' in advance because there are a lot of leaf tabs and each would generate an ajax call. So I figured, I could call tabs() in a lazy-fashion for lower level tabs, on beforeActivate event, i.e. just when the user clicks given tab. The problem is that first tab clicks itself without any user activity (which is obvious) but it somehow doesn't fire beforeActivate event!

Now, if I use create() event as suggested above, it means that I'm using different event to accomplish exactly the same thing (i.e. initialize sub-tabs in this tab). Which makes the first tab somehow special by design. It does not make any sense and it's completely counter-intuitive. If I use create() event just to do something for the first tab and then I change order of my tabs (some other tab becomse the "magical" first tab) then my code will stop working correctly.

comment:17 Changed 10 years ago by Scott González

The problem is that first tab clicks itself without any user activity (which is obvious) but it somehow doesn't fire beforeActivate event!

The firs tab does not click itself. Please see my earlier comment.

comment:18 Changed 10 years ago by Scott González

#9450 is a duplicate of this ticket.

comment:19 Changed 10 years ago by Schleis

This ticket should be reopened. It seems counter-intuitive that the initial tab is "active" when the tabs are first created. The initial tab should go through the same process as when the user clicks on the tab to open it.

When using remote tabs, the beforeLoad event is fired for the initial tab also. So it seems inconsistent to not also fire the beforeActivate event when not using remote tabs.

comment:20 in reply to:  19 Changed 10 years ago by Scott González

Replying to Schleis:

When using remote tabs, the beforeLoad event is fired for the initial tab also. So it seems inconsistent to not also fire the beforeActivate event when not using remote tabs.

There is no inconsistency. beforeLoad and beforeActivate are two very different events.

Do you find it counter-intuitive that a change event is not triggered for <select> elements upon page load?

comment:21 Changed 10 years ago by dmeet

I agree with all the comments. The design has been changed to bad. It became less intuitive and inconvenient.

Are there any significant advantages over the old design? If no, why not to change it back?

comment:22 Changed 10 years ago by Cardgage

A <select> element has only one part and it makes no sense to load the contents of an <option> when that <option> is selected. In a tab, with a tab and the panel, it does make sense to load the content of the panel when the tab becomes active. The comparison with the <select> element is not apt. They are not equivalent controls.

comment:23 Changed 10 years ago by Dakus

Please reopen this ticket. I have exactly the same situation as described by PawelRoman.

comment:24 Changed 10 years ago by jmaughan

"It is not being activated, it is active at the time of initialization." So what you are saying is during initialization you activate the tab but you do not fire the activate event. That seems odd.

The change event for a select box is a bad analogy. One is an event that happens when something CHANGES the other is an event when something ACTIVATES. But the initially selected tab is activated and therefore should have the activate event fire.

The create event should take care of things that need to happen during creation of the entire tab widget, for instance verify something exists in the DOM, it should not to load the data for a tab that is already handled when the tab activates. Even if that activation is during the initialization.

Logically you would expect the widget to initialize itself and then activate the chosen tab or activate the first tab.

comment:25 Changed 10 years ago by captainill

Whats the situation on this bug? The first tab is activated (auto) so would like to have an event to handle it's display as with other tabs. It's inconsistent. After the content of a tab is loaded (async) and displayed you may need to run methods against it. Not being able to on the first load is frustrating and unexpected. I'm looking for a hack solution. Anyone solve this?

comment:26 Changed 10 years ago by captainill

Last edited 10 years ago by captainill (previous) (diff)

comment:27 Changed 10 years ago by karger

I would like to support the argument that the current approach is inconsistent and problematic by describing my use case and the bug that the current approach forced me to track down.

I am using tabs with panel-content that is dynamically generated when a tab is selected; I bind to beforeActivate to generate that content. The tab which is initially open is based on some system state which can be captured by an integer i: if the system is in state i then tab i should be the initially open one.

Since I have already bound beforeActivate the obvious way to set up the panel is to invoke tabs('option', 'active', i) to cause it to fill in the panel for tab i.

This works great, *unless* the system happens to be in state 0. In this case, since by your current approach tab 0 is "already active", calling tabs('option', 'active', 0) does *not* trigger a beforeActivate event, so the panel is not initialized.

I could manually initialize the panel based on i when I create the tabs, but this means I am duplicating code. If instead the beforeActivate event was triggered for whichever panel was initially selected, I would have clean code. Instead, as a quick fix, I am calling tabs('option', 'active', i-1) followed by tabs('option', 'active', i) in order to ensure that the beforeActivation event gets triggered. But this is clearly wasteful as it leads to the generation of an entire panel which is then discarded.

comment:28 Changed 10 years ago by Scott González

There's nothing forcing you to duplicate code, that's what functions are for.

comment:29 Changed 10 years ago by vladmu

I also support the argument that the current approach is inconsistent and problematic. So if 'activate' is analog to 'change' of selectbox then you need to roll back 'show' event that will triggered when the tab is shown, I sure many people do something on the tab 'show' event. Please re-open this bug and fix it!

Last edited 10 years ago by vladmu (previous) (diff)

comment:30 in reply to:  12 Changed 10 years ago by alexgeorgas

Replying to scott.gonzalez:

I've updated the upgrade guide: http://jqueryui.com/upgrade-guide/1.9/#deprecated-show-event-renamed-to-activate

I just cannot comprehend this design decision. It seems to brake the code and make things more complicated. If one would allow the activate event to fire on the first instance of showing a tab, things would be ok.

It is clear a number of people are using these events to populate tab content. It is also possible that links to pages including anchor tags will direct a different tab to be opened at page initiation. Having to struggle with two events and with different methods of figuring out which tab has been activated makes no sense.

What makes things worse is that I cannot see many valid useful use cases for the activate event that do not fit a scenario which would involve this been fired at the appearance of the first tab.

This issue should be addressed

comment:31 Changed 9 years ago by NicoO

I think it's really counterintuitive, that the beforeActivate event is not triggered on initiation. This should be changed. After some frustration i've created a fiddle of a workaround: http://jsfiddle.net/NicoO/eq69p/6/

comment:32 in reply to:  description Changed 9 years ago by dmittner

Got to add my voice to the crowd. This is unintuitive behavior, though at least I kind of expected it so didn't waste a lot of time identifying the problem.

And to compare the "activate" event to a select's "change" event is silly. If you wanted them to be synonymous then you should have called the event "change". "Activate" means something clearly different in this context and that includes the first tab initially activating.

comment:33 Changed 8 years ago by markm

OK, so how does one raise the level of this issue? Sorry, but this design is simply wrong. It is critical that event driven UI controls generate events at the right time, and are semantically relevant. CREATE and ACTIVATE are semantically different, happen logically at different times in the lifecycle of the UI, and require different responses from the application code. ACTIVATE should logically happen any time a tab is show - the "first" time is no special case, and collapsing it with CREATE is semantically incorrect. It requires every application to create a 'hack' that handles CREATE events even if that event is of no interest to the application.

This problem (of initial state and events) has been addressed many times over the years in other event-based UI systems - just take a look at the event model for Win32, Motif, Swing, SWT... similar controls (lists, tabs, etc) generate 'selected' or 'activated' events consistently, including an event that reflects initial state of the control.

Please learn something from 20 years of UI design history, this is no longer rocket science and it not even really debatable, the issue has long since been decided in favor of application simplicity and consistency.

But, I suspect adding a comment to a closed bug report is not useful... so how can the user community get this fixed??

comment:34 in reply to:  33 Changed 8 years ago by Scott González

Replying to markm:

Please learn something from 20 years of UI design history, this is no longer rocket science and it not even really debatable, the issue has long since been decided in favor of application simplicity and consistency.

See http://bugs.jqueryui.com/ticket/8735#comment:4 which shows that we're already being consistent with the environment in which we operate.

Last edited 8 years ago by Scott González (previous) (diff)

comment:35 in reply to:  4 Changed 8 years ago by lulhuh

Replying to scott.gonzalez:

It is not being activated, it is active at the time of initialization. This is the equivalent of a change event being fired on page load for a select element because it starts with a value already selected.

It's not "active at the time of initialization" because it's not marked as "ui-state-active". If code change marking to "activated" it should call "activated" method.

Last edited 8 years ago by lulhuh (previous) (diff)

comment:36 in reply to:  description Changed 7 years ago by Taylor Cressy

I really hate to beat on a dead horse here. And I will not be as gratuitous as the others, but I am rather disheartened that this ticket was allowed to wither. The points brought up over the past three years are valid concerns, and the biggest argument to the contrary was that tabs are synonymous to a <select>.

The "activate" hook should be called upon activation of a tab, plain and simple. The alternative solution lacks elegance.

comment:37 Changed 7 years ago by stringfold

I want to add my support for a rethink on this issue too. I'm developing an application that uses the activate event to perform some checks and initialization whenever a panel is displayed. Everything works wonderfully except for the initial display of the first panel when the tabs widget is first created.

The create event is a useless alternative, because the tab widget is not fully initialized at this point -- specifically, when you call the 'option' function, all you get is "cannot call methods on slider prior to initialization." The first panel is not fully activated until much later.

Therefore the create event is simply not an acceptable alternative to an activation event for the first panel. It serves a completely different purpose, and is triggered far to early to be of any use to developers writing panel initialization code.

I have to agree with markm in his last comment. I do not understand the logic behind the current design. What possible reason is there for making the initial display of the first panel the widget a special case? It is the only time the activate event is not triggered when a panel is displayed. Worse, the current design is actually counter-intuitive, since the implication is that the first panel never goes through the activation process internally, which is patently not the case.

comment:38 in reply to:  37 Changed 7 years ago by Scott González

Replying to stringfold:

The create event is a useless alternative, because the tab widget is not fully initialized at this point -- specifically, when you call the 'option' function, all you get is "cannot call methods on slider prior to initialization." The first panel is not fully activated until much later.

I'm sorry, but this is just flat out wrong. The create event is triggered after the entire initialization process has completed. Even if we did fire an activate event during initialization, it would have to be *before* the create event, not after. Referencing a slider instance is also meaningless since there is absolutely no context here.

comment:39 Changed 6 years ago by D. Sidiropoulos

OK, so your recommendation is to handle both the "create" and the "activate" events. That works and I'll move my code to that paradigm. [...] Also, I'd like to reiterate that I can't see a scenario where a developer would use the activate event expecting the current behavior. Anyone handling the activate event would need to handle both.

Pretty much nailed it. It's kinda disheartening for developers to come across such counter-intuitive & alienating behavior from jQueryUI because working around this sort of stuff is bound to lead to unnecessary over-engineering and code-bloat. Firing the activate event for the tab which is selected by-default upon creating the tab-control shouldn't be such a big a deal.

Wish I could understand why we are getting flogged like this for no reason other than pure stubborness which goes against virtually against any and all rules of thumb and common-sense followed by most if not all ui-toolkits out there. Sigh.

comment:40 Changed 3 years ago by Stuardo -StR- Rodríguez

It's incredible I had to find this 8 years old ticket, and no solution. I solved using a wrapper to the function I was trying to trigger on both cases:

$('#tabs').tabs({
    activate: function(event, tab) { onTabRender(tab.newPanel)},
    create: function(event, tab)   { onTabRender(tab.panel)   },
});
Note: See TracTickets for help on using tickets.