Skip to main content

Search and Top Navigation

#10664 closed feature (wontfix)

Opened October 17, 2014 04:56PM UTC

Closed October 17, 2014 06:23PM UTC

Last modified October 22, 2014 04:41PM UTC

Add possibility to make tab contents not visible rather set display to none

Reported by: dma_k Owned by:
Priority: minor Milestone: none
Component: ui.tabs Version: 1.10.3
Keywords: Cc:
Blocked by: Blocking:
Description

In case tab contents is very heavy (tab controls switching panels of the application), tab switching becomes quite slow on Firefox and IE. I think this happens because once element is hidden, FF fires resize event (with zero size) and once element is shown, FF fires another resize event (with actual size), resulting two events needed to be processed (for hiding tab and for showing tab) on each tab switch. If tab contents logic tries to adjust its contents based on e.g. width (for example DataTables), it takes some time to switch tabs.

Solution: Implement alternative strategy that will apply "visible:hidden" CSS style to tab panel rather than "display:none" (or delegate this functionality to customizable callback or function that could be overridden). This strategy will only work if tab panels are absolutely positioned.

Chrome is not affected: it is smart not to send these events and switching happens very quickly.

Attachments (0)
Change History (4)

Changed October 17, 2014 06:23PM UTC by scottgonzalez comment:1

resolution: → wontfix
status: newclosed

Sounds like DataTables should handle this situation better.

Changed October 21, 2014 02:26PM UTC by dma_k comment:2

DataTables is just an example. There are other in-house components that listen on window resize and do some recalculation. Maybe you've go an idea how this could be handled better? Let's assume that event handler gets two events: one that new box dimensions are 275×0 (when it is hidden) and another is 288×804 (once it is shown back). Filtering out these events is not trivial.

Changed October 21, 2014 02:29PM UTC by scottgonzalez comment:3

.is( ":visible" ) seems very trivial to me. Is there a reason that's not sufficient? Any complex layout changes during a resize or scroll already need a fair amount of logic to not destroy the frame rate, so I would say developers should already be aware of these issues.

Changed October 22, 2014 04:41PM UTC by dma_k comment:4

.is(":visible")
will filter the 1st event – that's true. But 2nd event triggered when panel is shown, does not differ from "normal" resize event and is fired when panel is visible. I can see how element positions are recalculated and they are shifted / adjusted when panel is shown, so it is the most performance.

I considered the following solutions:

  • Suppress the 2nd event, if the previous event for fired for hidden panel (e.g. height=0). This is not very clean solution, as there are several events in a row fired when panel is shown.
  • Listen on
    beforeActivate()
    and set some flag (say,
    uiTabIsSwitching
    ) which is reset in
    activate()
    ; if the flag is raised, then ignore resize events. A bit cumbersome solution, as some deep component should have a reference to tab control (or some global) to access this flag.
  • Finally, try to intercept the hiding of the element. By examining the code of tab UI, I found out that it is already possible. Here is the sketch that worked for me:
$.widget("ui.tabs", $.ui.tabs, {
	options: {
		visibilityHide: false
	},

	_create: function() {
		this._super();

		if (this.options.visibilityHide) {
			this.options.hide = true;
			this.options.show = true;
		}
	},
	
	_hide: function(element, options, callback) {
		if (!this.options.visibilityHide) {
			this._super(element, options, callback);
			return;
		}
		
		element.css({ "visibility" : "hidden" });
		callback();
	},

	_show: function(element, options, callback) {
		if (!this.options.visibilityHide) {
			this._super(element, options, callback);
			return;
		}
		
		element.css({ "visibility" : "", "display" : "" });
		callback();
	}
});