Bug 964433 - overflowedItem fix for Australis overflowable toolbar, r=jaws
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Wed, 29 Jan 2014 17:22:52 +0000
changeset 181805 bb24d5ea7f897325bb0a043891fb4c3058bb5eec
parent 181804 9b3dc7c6dae9863ce59b2be44903f86ab1ca7313
child 181806 90bfbf075f3f4f2e49cfe4b7155289b00f2a05c8
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws
bugs964433
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 964433 - overflowedItem fix for Australis overflowable toolbar, r=jaws
browser/components/customizableui/src/CustomizableUI.jsm
browser/components/customizableui/test/browser.ini
browser/components/customizableui/test/browser_914138_widget_API_overflowable_toolbar.js
--- a/browser/components/customizableui/src/CustomizableUI.jsm
+++ b/browser/components/customizableui/src/CustomizableUI.jsm
@@ -1953,17 +1953,22 @@ let CustomizableUIInternal = {
     for (let [window, ] of gBuildWindows) {
       let windowCache = gSingleWrapperCache.get(window);
       if (windowCache) {
         windowCache.delete(aWidgetId);
       }
       let widgetNode = window.document.getElementById(aWidgetId) ||
                        window.gNavToolbox.palette.getElementsByAttribute("id", aWidgetId)[0];
       if (widgetNode) {
+        let container = widgetNode.parentNode
+        this.notifyListeners("onWidgetBeforeDOMChange", widgetNode, null,
+                             container, true);
         widgetNode.remove();
+        this.notifyListeners("onWidgetAfterDOMChange", widgetNode, null,
+                             container, true);
       }
       if (widget.type == "view") {
         let viewNode = window.document.getElementById(widget.viewId);
         if (viewNode) {
           for (let eventName of kSubviewEvents) {
             let handler = "on" + eventName;
             if (typeof widget[handler] == "function") {
               viewNode.removeEventListener(eventName, widget[handler], false);
@@ -3397,17 +3402,17 @@ OverflowableToolbar.prototype = {
   },
 
   _enable: function() {
     this._enabled = true;
     this.onOverflow();
   },
 
   onWidgetBeforeDOMChange: function(aNode, aNextNode, aContainer) {
-    if (aContainer != this._target) {
+    if (aContainer != this._target && aContainer != this._list) {
       return;
     }
     // When we (re)move an item, update all the items that come after it in the list
     // with the minsize *of the item before the to-be-removed node*. This way, we
     // ensure that we try to move items back as soon as that's possible.
     if (aNode.parentNode == this._list) {
       let updatedMinSize;
       if (aNode.previousSibling) {
@@ -3420,17 +3425,17 @@ OverflowableToolbar.prototype = {
       while (nextItem) {
         this._collapsed.set(nextItem.id, updatedMinSize);
         nextItem = nextItem.nextSibling;
       }
     }
   },
 
   onWidgetAfterDOMChange: function(aNode, aNextNode, aContainer) {
-    if (aContainer != this._target) {
+    if (aContainer != this._target && aContainer != this._list) {
       return;
     }
 
     let nowInBar = aNode.parentNode == aContainer;
     let nowOverflowed = aNode.parentNode == this._list;
     let wasOverflowed = this._collapsed.has(aNode.id);
 
     // If this wasn't overflowed before...
--- a/browser/components/customizableui/test/browser.ini
+++ b/browser/components/customizableui/test/browser.ini
@@ -24,19 +24,16 @@ skip-if = os == "mac"
 [browser_890262_destroyWidget_after_add_to_panel.js]
 [browser_892955_isWidgetRemovable_for_removed_widgets.js]
 [browser_892956_destroyWidget_defaultPlacements.js]
 [browser_909779_overflow_toolbars_new_window.js]
 [browser_901207_searchbar_in_panel.js]
 [browser_913972_currentset_overflow.js]
 
 [browser_914138_widget_API_overflowable_toolbar.js]
-# Because of the specific widths, this test is fragile and has been disabled.
-# NB: it was designed for mac only, but started randomly failing there.
-skip-if = true
 
 [browser_914863_disabled_help_quit_buttons.js]
 [browser_918049_skipintoolbarset_dnd.js]
 [browser_923857_customize_mode_event_wrapping_during_reset.js]
 [browser_927717_customize_drag_empty_toolbar.js]
 [browser_932928_show_notice_when_palette_empty.js]
 
 [browser_934113_menubar_removable.js]
--- a/browser/components/customizableui/test/browser_914138_widget_API_overflowable_toolbar.js
+++ b/browser/components/customizableui/test/browser_914138_widget_API_overflowable_toolbar.js
@@ -4,16 +4,17 @@
 
 "use strict";
 
 let navbar = document.getElementById(CustomizableUI.AREA_NAVBAR);
 let overflowList = document.getElementById(navbar.getAttribute("overflowtarget"));
 
 const kTestBtn1 = "test-addWidgetToArea-overflow";
 const kTestBtn2 = "test-removeWidgetFromArea-overflow";
+const kTestBtn3 = "test-createWidget-overflow";
 const kHomeBtn = "home-button";
 const kDownloadsBtn = "downloads-button";
 const kSearchBox = "search-container";
 const kStarBtn = "bookmarks-menu-button";
 
 let originalWindowWidth;
 
 // Adding a widget should add it next to the widget it's being inserted next to.
@@ -22,61 +23,46 @@ add_task(function() {
   createDummyXULButton(kTestBtn1, "Test");
   ok(!navbar.hasAttribute("overflowing"), "Should start with a non-overflowing toolbar.");
   ok(CustomizableUI.inDefaultState, "Should start in default state.");
 
   window.resizeTo(400, window.outerHeight);
   yield waitForCondition(() => navbar.hasAttribute("overflowing"));
   ok(navbar.hasAttribute("overflowing"), "Should have an overflowing toolbar.");
   ok(!navbar.querySelector("#" + kHomeBtn), "Home button should no longer be in the navbar");
-  ok(overflowList.querySelector("#" + kHomeBtn), "Home button should be overflowing");
+  let homeBtnNode = overflowList.querySelector("#" + kHomeBtn);
+  ok(homeBtnNode, "Home button should be overflowing");
+  ok(homeBtnNode && homeBtnNode.classList.contains("overflowedItem"), "Home button should have overflowedItem class");
 
   let placementOfHomeButton = CustomizableUI.getWidgetIdsInArea(navbar.id).indexOf(kHomeBtn);
   CustomizableUI.addWidgetToArea(kTestBtn1, navbar.id, placementOfHomeButton);
   ok(!navbar.querySelector("#" + kTestBtn1), "New button should not be in the navbar");
-  ok(overflowList.querySelector("#" + kTestBtn1), "New button should be overflowing");
-  let nextEl = document.getElementById(kTestBtn1).nextSibling;
+  let newButtonNode = overflowList.querySelector("#" + kTestBtn1);
+  ok(newButtonNode, "New button should be overflowing");
+  ok(newButtonNode && newButtonNode.classList.contains("overflowedItem"), "New button should have overflowedItem class");
+  let nextEl = newButtonNode && newButtonNode.nextSibling;
   is(nextEl && nextEl.id, kHomeBtn, "Test button should be next to home button.");
 
   window.resizeTo(originalWindowWidth, window.outerHeight);
   yield waitForCondition(() => !navbar.hasAttribute("overflowing"));
   ok(!navbar.hasAttribute("overflowing"), "Should not have an overflowing toolbar.");
   ok(navbar.querySelector("#" + kHomeBtn), "Home button should be in the navbar");
+  ok(homeBtnNode && !homeBtnNode.classList.contains("overflowedItem"), "Home button should no longer have overflowedItem class");
   ok(!overflowList.querySelector("#" + kHomeBtn), "Home button should no longer be overflowing");
   ok(navbar.querySelector("#" + kTestBtn1), "Test button should be in the navbar");
   ok(!overflowList.querySelector("#" + kTestBtn1), "Test button should no longer be overflowing");
+  ok(newButtonNode && !newButtonNode.classList.contains("overflowedItem"), "New button should no longer have overflowedItem class");
   let el = document.getElementById(kTestBtn1);
   if (el) {
     CustomizableUI.removeWidgetFromArea(kTestBtn1);
     el.remove();
   }
   window.resizeTo(originalWindowWidth, window.outerHeight);
 });
 
-// Removing a widget from the toolbar should try to move items back.
-add_task(function() {
-  // This is pretty weird. We're going to try to move only the home button into the overlay:
-  let downloadsBtn = document.getElementById(kDownloadsBtn);
-  // Guarantee overflow of too much stuff:
-  window.resizeTo(700, window.outerHeight);
-  let inc = 15;
-  while (window.outerWidth < originalWindowWidth &&
-         downloadsBtn.parentNode != navbar.customizationTarget) {
-    window.resizeTo(window.outerWidth + inc, window.outerHeight);
-    yield waitFor(500);
-  }
-  ok(overflowList.querySelector("#home-button"), "Home button should be overflowing");
-  CustomizableUI.removeWidgetFromArea("downloads-button");
-  is(document.getElementById("home-button").parentNode, navbar.customizationTarget, "Home button should move back.");
-  ok(!navbar.hasAttribute("overflowing"), "Navbar is no longer overflowing");
-  window.resizeTo(originalWindowWidth, window.outerHeight);
-  yield waitForCondition(function() !navbar.hasAttribute("overflowing"));
-  CustomizableUI.reset();
-});
-
 // Removing a widget should remove it from the overflow list if that is where it is, and update it accordingly.
 add_task(function() {
   createDummyXULButton(kTestBtn2, "Test");
   ok(!navbar.hasAttribute("overflowing"), "Should start with a non-overflowing toolbar.");
   ok(CustomizableUI.inDefaultState, "Should start in default state.");
   CustomizableUI.addWidgetToArea(kTestBtn2, navbar.id);
   ok(!navbar.hasAttribute("overflowing"), "Should still have a non-overflowing toolbar.");
 
@@ -98,48 +84,48 @@ add_task(function() {
   let el = document.getElementById(kTestBtn2);
   if (el) {
     CustomizableUI.removeWidgetFromArea(kTestBtn2);
     el.remove();
   }
   window.resizeTo(originalWindowWidth, window.outerHeight);
 });
 
-// Overflow everything that can, then reorganize that list
+// Constructing a widget while overflown should set the right class on it.
 add_task(function() {
+  originalWindowWidth = window.outerWidth;
   ok(!navbar.hasAttribute("overflowing"), "Should start with a non-overflowing toolbar.");
   ok(CustomizableUI.inDefaultState, "Should start in default state.");
 
-  window.resizeTo(360, window.outerHeight);
-  yield waitForCondition(() => navbar.getAttribute("overflowing") == "true");
-  ok(!navbar.querySelector("#" + kSearchBox), "Search container should be overflowing");
-  let placements = CustomizableUI.getWidgetIdsInArea(navbar.id);
-  let searchboxPlacement = placements.indexOf(kSearchBox);
-  CustomizableUI.moveWidgetWithinArea(kHomeBtn, searchboxPlacement);
-  yield waitForCondition(() => navbar.querySelector("#" + kHomeBtn));
-  ok(navbar.querySelector("#" + kHomeBtn), "Home button should have moved back");
-  let inc = 15;
-  window.resizeTo(640, window.outerHeight);
-  while (window.outerWidth < originalWindowWidth &&
-         !navbar.querySelector("#" + kSearchBox)) {
-    window.resizeTo(window.outerWidth + inc, window.outerHeight);
-    yield waitFor(500);
-  }
-  ok(!navbar.querySelector("#" + kStarBtn), "Star button should still be overflowed");
-  CustomizableUI.moveWidgetWithinArea(kStarBtn);
-  let starButtonOverflowed = overflowList.querySelector("#" + kStarBtn);
-  ok(starButtonOverflowed && !starButtonOverflowed.nextSibling, "Star button should be last item");
-  window.resizeTo(window.outerWidth + 15, window.outerHeight);
-  yield waitForCondition(() => navbar.querySelector("#" + kDownloadsBtn) && navbar.hasAttribute("overflowing"));
-  ok(navbar.hasAttribute("overflowing"), "navbar should still be overflowing");
-  CustomizableUI.moveWidgetWithinArea(kHomeBtn);
-  let homeButtonOverflowed = overflowList.querySelector("#" + kHomeBtn);
-  ok(homeButtonOverflowed, "Home button should be in overflow list");
-  ok(navbar.hasAttribute("overflowing"), "navbar should still be overflowing");
-  ok(homeButtonOverflowed && !homeButtonOverflowed.nextSibling, "Home button should be last item");
+  window.resizeTo(400, window.outerHeight);
+  yield waitForCondition(() => navbar.hasAttribute("overflowing"));
+  ok(navbar.hasAttribute("overflowing"), "Should have an overflowing toolbar.");
+  ok(!navbar.querySelector("#" + kHomeBtn), "Home button should no longer be in the navbar");
+  let homeBtnNode = overflowList.querySelector("#" + kHomeBtn);
+  ok(homeBtnNode, "Home button should be overflowing");
+  ok(homeBtnNode && homeBtnNode.classList.contains("overflowedItem"), "Home button should have overflowedItem class");
+
+  let testBtnSpec = {id: kTestBtn3, label: "Overflowable widget test", defaultArea: "nav-bar"};
+  CustomizableUI.createWidget(testBtnSpec);
+  let testNode = overflowList.querySelector("#" + kTestBtn3);
+  ok(testNode, "Test button should be overflowing");
+  ok(testNode && testNode.classList.contains("overflowedItem"), "Test button should have overflowedItem class");
+
+  CustomizableUI.destroyWidget(kTestBtn3);
+  testNode = document.getElementById(kTestBtn3);
+  ok(!testNode, "Test button should be gone");
+
+  CustomizableUI.createWidget(testBtnSpec);
+  testNode = overflowList.querySelector("#" + kTestBtn3);
+  ok(testNode, "Test button should be overflowing");
+  ok(testNode && testNode.classList.contains("overflowedItem"), "Test button should have overflowedItem class");
+
+  CustomizableUI.removeWidgetFromArea(kTestBtn3);
+  testNode = document.getElementById(kTestBtn3);
+  ok(!testNode, "Test button should be gone");
+  CustomizableUI.destroyWidget(kTestBtn3);
   window.resizeTo(originalWindowWidth, window.outerHeight);
-  yield waitForCondition(() => !navbar.hasAttribute("overflowing"));
-  ok(!navbar.hasAttribute("overflowing"), "Should not have an overflowing toolbar.");
 });
 
 add_task(function asyncCleanup() {
+  window.resizeTo(originalWindowWidth, window.outerHeight);
   yield resetCustomization();
 });