Trying to set the pages up with a single panel on the left which is fixed-width, so as to always have enough space for the list of links to display there, but without taking more than needed. The “Small” option isn’t wide enough on smaller monitors; the “Medium” option takes too much on anything but small monitors. Is there someplace proper to specify a fixed width for this?
We have been requested by our users if this panel could be variable and it’s width dragged by mouse. Is this worth a feature request or way beyond possibilities?
Regards, Simpel
The following JavaScriptExtension uses the CSS resize feature to make the width of a panel dynamic.
var panelObserver = new ResizeObserver(function (entries) {
entries.forEach(function (entry) {
var leftPanelsWidth = function () {
var leftPanels = document.getElementById("leftPanels");
if (leftPanels == null) {
return 0
} else {
return leftPanels.getWidth()
}
};
var rightPanelsWidth = function () {
var rightPanels = document.getElementById("rightPanels");
if (rightPanels == null) {
return 0
} else {
return rightPanels.getWidth()
}
};
if (entry.target.id == "leftPanels" || entry.target.id == "rightPanels") {
var contentColumn = document.getElementById("contentcolumn").children[0];
var leftPanels = document.getElementById("leftPanels");
var containerWidth = document.getElementById("contentcontainerinner").getWidth();
var paddingCorrection = 60;
contentColumn.style["left"] = 100 * leftPanelsWidth() / containerWidth + "%";
contentColumn.style["width"] = 100 * (containerWidth - rightPanelsWidth() - leftPanelsWidth() - paddingCorrection) / containerWidth + "%";
if (leftPanels != null) {
leftPanels.style["right"] = contentColumn.style["width"]
};
};
});
});
if (document.getElementById("leftPanels") != null) {
document.getElementById("leftPanels").style["resize"] = "horizontal";
document.getElementById("leftPanels").style["overflow"] = "hidden";
panelObserver.observe(document.getElementById("leftPanels"));
};
if (document.getElementById("rightPanels") != null) {
document.getElementById("rightPanels").style["resize"] = "horizontal";
document.getElementById("rightPanels").style["overflow"] = "hidden";
panelObserver.observe(document.getElementById("rightPanels"));
};
It is a bit “dirty”, as it uses the HTML ids of the page layout, but it works.
(Used with flamingo skin).
Since the above ticket was closed as ‘won’t fix’ we had to find another solution.
I made several attempts to find the right compromise between hackiness and user-friendliness.
This is what we have today. There are some requirements:
- We use the navigation panel on the left side.
- We don’t have any other panel on the left.
- We use Flamingo skin.
JavaScriptExtension:
document.addEventListener("DOMContentLoaded", function () {
const leftPanel = document.getElementById('leftPanels');
if (window.innerWidth > 991) {
if (leftPanel) {
try {
const container = document.querySelector("#contentcontainerinner > .leftsidecolumns");
const main = container.querySelector(".main");
// create splitter
const splitter = document.createElement("div");
splitter.id = "splitter";
splitter.title = "Click and drag to adjust the width. Double-click to reset the width.";
splitter.style.height = main.offsetHeight + "px";
// insert splitter
container.insertBefore(splitter, leftPanel.nextSibling);
// double-click splitter: delete localStorage and reload page to reset
splitter.addEventListener("dblclick", () => {
localStorage.removeItem("leftPanelWidthPercent");
location.reload();
});
// drag functions
let isDragging = false;
splitter.addEventListener("mousedown", function () {
isDragging = true;
document.body.style.cursor = "ew-resize";
});
document.addEventListener("mousemove", function (e) {
if (!isDragging) return;
const newWidth = e.clientX - container.getBoundingClientRect().left;
if (newWidth > 100 && newWidth < window.innerWidth * 0.8) {
const containerWidth = container.offsetWidth;
const percent = ((newWidth / containerWidth) * 100).toFixed(1);
document.documentElement.style.setProperty("--variable-left-panel-width", percent + "%");
document.documentElement.style.setProperty("--variable-main-width", 100 - percent + "%");
localStorage.setItem("leftPanelWidthPercent", percent);
}
});
document.addEventListener("mouseup", function () {
isDragging = false;
document.body.style.cursor = "";
});
} catch (err) {
//console.log(err)
}
}
}
});
UIExtension ‘org.xwiki.platform.html.head’ as extension point ID:
{{html}}
<script>
// following function is executed in <head> as it is inserted with this UIX in 'org.xwiki.platform.html.head' as extension point ID
// This code has to be executed very early otherwise the width of navigation panel and article will jump (first default and later requested values)
// see https://www.xwiki.org/xwiki/bin/view/Documentation/DevGuide/Tutorials/UIXTutorial and
// see https://www.xwiki.org/xwiki/bin/view/Documentation/DevGuide/ExtensionPoint
(function() {
const percent = localStorage.getItem("leftPanelWidthPercent");
if (percent) {
document.documentElement.style.setProperty("--variable-left-panel-width", percent + "%");
document.documentElement.style.setProperty("--variable-main-width", 100 - percent + "%");
} else {
document.documentElement.style.setProperty("--variable-left-panel-width", "16.7%");
document.documentElement.style.setProperty("--variable-main-width", "83.3%");
}
})();
</script>
{{/html}}
StyleSheetExtension:
/* only bigger devices */
@media (min-width: 992px) {
#body.hideright.panel-left-width-Medium .main {
left: var(--variable-left-panel-width, 16.7%);
width: var(--variable-main-width, 83.3%);
}
#body.hideright.panel-left-width-Medium #leftPanels {
width: var(--variable-left-panel-width, 16.7%);
right: var(--variable-main-width, 83.3%);
}
#splitter {
width: 11px;
position: absolute;
left: calc(var(--variable-left-panel-width) - 5px);
z-index: 10;
background: transparent;
transition: background .2s;
cursor: ew-resize;
}
#splitter::before {
content: "";
position: absolute;
left: 5px;
top: 0;
bottom: 0;
width: 1px;
background: #e8e8e8;
}
#splitter:hover::before {
background: #888;
}
}
Note that since XWiki 17.3.0, panel resizing is supported by XWiki, no need for any customizations.
That’s great. So I remove my code when upgrading next year as we do use the lts.