Skip to main content

Search and Top Navigation

Ticket #4575: ui.dialog-opera-scroll.patch
File ui.dialog-opera-scroll.patch, 4.2 KB (added by Mikko Rantanen, June 12, 2009 09:06PM UTC)

ui.dialog patch for ticket #4575

Index: ui.dialog.js
===================================================================
--- ui.dialog.js	(revision 2731)
+++ ui.dialog.js	(working copy)
@@ -30,7 +30,9 @@
 		'ui-dialog ' +
 		'ui-widget ' +
 		'ui-widget-content ' +
-		'ui-corner-all ';
+		'ui-corner-all ',
+        
+    uiDialogPool = {};
 
 $.widget("ui.dialog", {
 
@@ -63,7 +65,10 @@
 					'aria-labelledby': titleId
 				})
 				.mousedown(function(event) {
-					self.moveToTop(false, event);
+					self.moveToTop(false, event, true);
+				})
+				.mouseup(function(event) {
+					self._fixZIndex(event);
 				}),
 
 			uiDialogContent = self.element
@@ -126,6 +131,9 @@
 				.html(title)
 				.prependTo(uiDialogTitlebar);
 
+		// Title ID is unique to a dialog so we'll use that one to identify the dialogs.
+		uiDialogPool[titleId] = self;
+
 		uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
 
 		(options.draggable && $.fn.draggable && self._makeDraggable());
@@ -150,6 +158,8 @@
 			.hide().appendTo('body');
 		self.uiDialog.remove();
 
+		uiDialogPool[self] = null;
+
 		(self.originalTitle && self.element.attr('title', self.originalTitle));
 
 		return self;
@@ -195,7 +205,7 @@
 
 	// the force parameter allows us to move modal dialogs to their correct
 	// position on open
-	moveToTop: function(force, event) {
+	moveToTop: function(force, event, isMouseEvent) {
 		var self = this,
 			options = self.options;
 		
@@ -209,12 +219,30 @@
 		}
 		(self.overlay && self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = ++$.ui.dialog.maxZ));
 
-		//Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
-		//  http://ui.jquery.com/bugs/ticket/3193
-		var saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
-		self.uiDialog.css('z-index', ++$.ui.dialog.maxZ);
-		self.element.attr(saveScroll);
-		self._trigger('focus', event);
+		// If this is a result of a mouse event drop other dialogs below the current one since Opera 9.5+ resets scroll positions when parent z-Index is changed.
+		// and the mouse event could be interaction with a scroll bar.
+		//  http://dev.jqueryui.com/ticket/3193
+		//  http://dev.jqueryui.com/ticket/4575
+		if (isMouseEvent) {
+		
+			var orderedDialogs = []
+			for (var dialogID in uiDialogPool)
+				if (uiDialogPool[dialogID] != self)
+					orderedDialogs.push(uiDialogPool[dialogID]);
+			orderedDialogs.sort(function(d1, d2) { return d2.uiDialog.css('z-index') -
+			                                              d1.uiDialog.css('z-index'); });
+		
+			var topZ = self.uiDialog.css('z-index');
+			
+			// Move the dialogs back starting from the backmost dialog to prevent flickering.
+			for (var i = orderedDialogs.length; i > 0; i--) {
+				orderedDialogs[i-1]._setZIndex(topZ - i);
+			}
+		} else {
+			self._setZIndex(++$.ui.dialog.maxZ);
+		}
+		
+		self._trigger('focus', event);	
 
 		return self;
 	},
@@ -519,6 +547,46 @@
 
 		(this.uiDialog.is(':ui-resizable') &&
 			this.uiDialog.resizable('option', 'minHeight', this._minHeight()));
+	},
+	
+	_fixZIndex: function() {
+		var orderedArray = [];
+		for (var dialogID in uiDialogPool)
+			orderedArray.push(uiDialogPool[dialogID]);
+
+		orderedArray.sort(function(d1, d2) { return d2.uiDialog.css('z-index') - d1.uiDialog.css('z-index') });
+
+		for (var i = 0; i < orderedArray.length; i++) {
+			orderedArray[i]._setZIndex($.ui.dialog.maxZ - i);
+		}
+	},
+	
+	_setZIndex: function(index) {
+		var self = this;
+		
+		// Store the scroll positions before modifying the z-index.
+		//  http://dev.jqueryui.com/ticket/3193
+		//  http://dev.jqueryui.com/ticket/4575
+		var saveScroll = []
+		self.uiDialog.find("*").each(function() {
+			var currentElement = $(this)
+			var scrollTop = currentElement.attr('scrollTop');
+			var scrollLeft = currentElement.attr('scrollLeft');
+			if (scrollTop || scrollLeft) {
+				saveScroll.push({ 
+					element: currentElement, 
+					attr: { scrollTop: currentElement.attr('scrollTop'),
+					        scrollLeft: currentElement.attr('scrollLeft') }
+				});
+			}
+		});
+
+		self.uiDialog.css('z-index', index);
+
+		for (var i = 0; i < saveScroll.length; i++) {
+			var savedScroll = saveScroll[i];
+			savedScroll.element.attr(savedScroll.attr);
+		}
 	}
 });

Download in other formats:

Original Format