michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: "use strict"; michael@0: michael@0: const kXULWidgetId = "sync-button"; michael@0: const kAPIWidgetId = "feed-button"; michael@0: const kPanel = CustomizableUI.AREA_PANEL; michael@0: const kToolbar = CustomizableUI.AREA_NAVBAR; michael@0: const kVisiblePalette = "customization-palette"; michael@0: const kPlaceholderClass = "panel-customization-placeholder"; michael@0: michael@0: function checkWrapper(id) { michael@0: is(document.querySelectorAll("#wrapper-" + id).length, 1, "There should be exactly 1 wrapper for " + id + " in the customizing window."); michael@0: } michael@0: michael@0: let move = { michael@0: "drag": function(id, target) { michael@0: let targetNode = document.getElementById(target); michael@0: if (targetNode.customizationTarget) { michael@0: targetNode = targetNode.customizationTarget; michael@0: } michael@0: simulateItemDrag(document.getElementById(id), targetNode); michael@0: }, michael@0: "dragToItem": function(id, target) { michael@0: let targetNode = document.getElementById(target); michael@0: if (targetNode.customizationTarget) { michael@0: targetNode = targetNode.customizationTarget; michael@0: } michael@0: let items = targetNode.querySelectorAll("toolbarpaletteitem:not(." + kPlaceholderClass + ")"); michael@0: if (target == kPanel) { michael@0: targetNode = items[items.length - 1]; michael@0: } else { michael@0: targetNode = items[0]; michael@0: } michael@0: simulateItemDrag(document.getElementById(id), targetNode); michael@0: }, michael@0: "API": function(id, target) { michael@0: if (target == kVisiblePalette) { michael@0: return CustomizableUI.removeWidgetFromArea(id); michael@0: } michael@0: return CustomizableUI.addWidgetToArea(id, target, null); michael@0: } michael@0: }; michael@0: michael@0: function isLast(containerId, defaultPlacements, id) { michael@0: assertAreaPlacements(containerId, defaultPlacements.concat([id])); michael@0: is(document.getElementById(containerId).customizationTarget.lastChild.firstChild.id, id, michael@0: "Widget " + id + " should be in " + containerId + " in customizing window."); michael@0: is(otherWin.document.getElementById(containerId).customizationTarget.lastChild.id, id, michael@0: "Widget " + id + " should be in " + containerId + " in other window."); michael@0: } michael@0: michael@0: function getLastVisibleNodeInToolbar(containerId, win=window) { michael@0: let container = win.document.getElementById(containerId).customizationTarget; michael@0: let rv = container.lastChild; michael@0: while (rv && (rv.getAttribute('hidden') == 'true' || (rv.firstChild && rv.firstChild.getAttribute('hidden') == 'true'))) { michael@0: rv = rv.previousSibling; michael@0: } michael@0: return rv; michael@0: } michael@0: michael@0: function isLastVisibleInToolbar(containerId, defaultPlacements, id) { michael@0: let newPlacements; michael@0: for (let i = defaultPlacements.length - 1; i >= 0; i--) { michael@0: let el = document.getElementById(defaultPlacements[i]); michael@0: if (el && el.getAttribute('hidden') != 'true') { michael@0: newPlacements = [...defaultPlacements]; michael@0: newPlacements.splice(i + 1, 0, id); michael@0: break; michael@0: } michael@0: } michael@0: if (!newPlacements) { michael@0: assertAreaPlacements(containerId, defaultPlacements.concat([id])); michael@0: } else { michael@0: assertAreaPlacements(containerId, newPlacements); michael@0: } michael@0: is(getLastVisibleNodeInToolbar(containerId).firstChild.id, id, michael@0: "Widget " + id + " should be in " + containerId + " in customizing window."); michael@0: is(getLastVisibleNodeInToolbar(containerId, otherWin).id, id, michael@0: "Widget " + id + " should be in " + containerId + " in other window."); michael@0: } michael@0: michael@0: function isFirst(containerId, defaultPlacements, id) { michael@0: assertAreaPlacements(containerId, [id].concat(defaultPlacements)); michael@0: is(document.getElementById(containerId).customizationTarget.firstChild.firstChild.id, id, michael@0: "Widget " + id + " should be in " + containerId + " in customizing window."); michael@0: is(otherWin.document.getElementById(containerId).customizationTarget.firstChild.id, id, michael@0: "Widget " + id + " should be in " + containerId + " in other window."); michael@0: } michael@0: michael@0: function checkToolbar(id, method) { michael@0: // Place at start of the toolbar: michael@0: let toolbarPlacements = getAreaWidgetIds(kToolbar); michael@0: move[method](id, kToolbar); michael@0: if (method == "dragToItem") { michael@0: isFirst(kToolbar, toolbarPlacements, id); michael@0: } else if (method == "drag") { michael@0: isLastVisibleInToolbar(kToolbar, toolbarPlacements, id); michael@0: } else { michael@0: isLast(kToolbar, toolbarPlacements, id); michael@0: } michael@0: checkWrapper(id); michael@0: } michael@0: michael@0: function checkPanel(id, method) { michael@0: let panelPlacements = getAreaWidgetIds(kPanel); michael@0: move[method](id, kPanel); michael@0: let children = document.getElementById(kPanel).querySelectorAll("toolbarpaletteitem:not(." + kPlaceholderClass + ")"); michael@0: let otherChildren = otherWin.document.getElementById(kPanel).children; michael@0: let newPlacements = panelPlacements.concat([id]); michael@0: // Relative position of the new item from the end: michael@0: let position = -1; michael@0: // For the drag to item case, we drag to the last item, making the dragged item the michael@0: // penultimate item. We can't well use the first item because the panel has complicated michael@0: // rules about rearranging wide items (which, by default, the first two items are). michael@0: if (method == "dragToItem") { michael@0: newPlacements.pop(); michael@0: newPlacements.splice(panelPlacements.length - 1, 0, id); michael@0: position = -2; michael@0: } michael@0: assertAreaPlacements(kPanel, newPlacements); michael@0: is(children[children.length + position].firstChild.id, id, michael@0: "Widget " + id + " should be in " + kPanel + " in customizing window."); michael@0: is(otherChildren[otherChildren.length + position].id, id, michael@0: "Widget " + id + " should be in " + kPanel + " in other window."); michael@0: checkWrapper(id); michael@0: } michael@0: michael@0: function checkPalette(id, method) { michael@0: // Move back to palette: michael@0: move[method](id, kVisiblePalette); michael@0: ok(CustomizableUI.inDefaultState, "Should end in default state"); michael@0: let visibleChildren = gCustomizeMode.visiblePalette.children; michael@0: let expectedChild = method == "dragToItem" ? visibleChildren[0] : visibleChildren[visibleChildren.length - 1]; michael@0: is(expectedChild.firstChild.id, id, "Widget " + id + " was moved using " + method + " and should now be wrapped in palette in customizing window."); michael@0: if (id == kXULWidgetId) { michael@0: ok(otherWin.gNavToolbox.palette.querySelector("#" + id), "Widget " + id + " should be in invisible palette in other window."); michael@0: } michael@0: checkWrapper(id); michael@0: } michael@0: michael@0: let otherWin; michael@0: michael@0: // Moving widgets in two windows, one with customize mode and one without, should work. michael@0: add_task(function MoveWidgetsInTwoWindows() { michael@0: yield startCustomizing(); michael@0: otherWin = yield openAndLoadWindow(null, true); michael@0: yield otherWin.PanelUI.ensureReady(); michael@0: ok(CustomizableUI.inDefaultState, "Should start in default state"); michael@0: michael@0: for (let widgetId of [kXULWidgetId, kAPIWidgetId]) { michael@0: for (let method of ["API", "drag", "dragToItem"]) { michael@0: info("Moving widget " + widgetId + " using " + method); michael@0: checkToolbar(widgetId, method); michael@0: checkPanel(widgetId, method); michael@0: checkPalette(widgetId, method); michael@0: checkPanel(widgetId, method); michael@0: checkToolbar(widgetId, method); michael@0: checkPalette(widgetId, method); michael@0: } michael@0: } michael@0: yield promiseWindowClosed(otherWin); michael@0: otherWin = null; michael@0: yield endCustomizing(); michael@0: }); michael@0: michael@0: add_task(function asyncCleanup() { michael@0: yield resetCustomization(); michael@0: });