Skip to content

Commit

Permalink
fix #984 Clicking in Rapid Succession Causes Tree Component Interacti…
Browse files Browse the repository at this point in the history
…on to Break
  • Loading branch information
vegegoku committed Dec 8, 2024
1 parent 7d0c7f0 commit 05913e8
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public class Collapsible implements IsElement<Element>, IsCollapsible<Collapsibl
private List<ExpandHandler> expandHandlers = new ArrayList<>();
private List<ExpandHandler> beforeExpandHandlers = new ArrayList<>();
private CollapseStrategy strategy = new DisplayCollapseStrategy();
private boolean expandingCollapsing = false;

/**
* Creates a collapsible wrapping the element
Expand Down Expand Up @@ -138,7 +139,8 @@ public Collapsible setForceCollapsed(boolean forceHidden) {
*/
@Override
public Collapsible expand() {
if (!forceHidden && isCollapsed()) {
if (!forceHidden && isCollapsed() && !expandingCollapsing) {
expandingCollapsing = true;
strategy.expand(element);
element.setAttribute("aria-expanded", "true");
this.collapsed = false;
Expand All @@ -153,7 +155,8 @@ public Collapsible expand() {
*/
@Override
public Collapsible collapse() {
if (!forceHidden && !isCollapsed()) {
if (!forceHidden && !isCollapsed() && !expandingCollapsing) {
expandingCollapsing = true;
strategy.collapse(element);
element.setAttribute("aria-expanded", "false");
this.collapsed = true;
Expand All @@ -162,6 +165,7 @@ public Collapsible collapse() {
}

private void onCollapseCompleted() {
expandingCollapsing = false;
if (nonNull(collapseHandlers)) {
collapseHandlers.forEach(CollapseHandler::apply);
}
Expand All @@ -174,6 +178,7 @@ private void onBeforeCollapse() {
}

private void onExpandCompleted() {
expandingCollapsing = false;
if (nonNull(expandHandlers)) {
expandHandlers.forEach(ExpandHandler::apply);
}
Expand Down Expand Up @@ -202,11 +207,14 @@ public boolean isCollapsed() {
*/
@Override
public Collapsible toggleCollapse() {
if (isCollapsed()) {
expand();
} else {
collapse();
if (!expandingCollapsing) {
if (isCollapsed()) {
expand();
} else {
collapse();
}
}

return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ public class TreeHeightCollapseStrategy implements CollapseStrategy, Collapsible
private final String heightVar;
private CollapsibleHandlers handlers;
private final TreeItem<?> treeItem;
private boolean expanding = false;
private boolean collapsing = false;

/**
* Constructor for TreeHeightCollapseStrategy.
Expand Down Expand Up @@ -94,14 +96,17 @@ public void cleanup(Element element) {
public void expand(Element element) {
treeItem.nowOrWhenAttached(
() -> {
this.handlers.onBeforeExpand().run();
double height = treeItem.getBoundingClientRect().height;
treeItem.setAttribute(DUI_COLLAPSED_HEIGHT, height);
treeItem.getSubTree().show();
treeItem.setCssProperty(this.heightVar, height + "px");
double expandedHeight = getActualHeight();
treeItem.setAttribute(DUI_EXPANDED_HEIGHT, expandedHeight);
expandElement(element);
if (!collapsing) {
this.expanding = true;
this.handlers.onBeforeExpand().run();
double height = treeItem.getBoundingClientRect().height;
treeItem.setAttribute(DUI_COLLAPSED_HEIGHT, height);
treeItem.getSubTree().show();
treeItem.setCssProperty(this.heightVar, height + "px");
double expandedHeight = getActualHeight();
treeItem.setAttribute(DUI_EXPANDED_HEIGHT, expandedHeight);
expandElement(element);
}
});
}

Expand All @@ -119,56 +124,73 @@ private void expandElement(Element element) {
treeItem.setCssProperty(this.heightVar, "auto");
treeItem.removeAttribute(DUI_COLLAPSED);
handlers.onExpandCompleted().run();
expanding = false;
} else {
EventListener stopListener =
evt -> {
resetParentHeight(treeItem);
treeItem.setCssProperty(this.heightVar, "auto");
handlers.onExpandCompleted().run();
expanding = false;
};

AddEventListenerOptions addEventListenerOptions = AddEventListenerOptions.create();
addEventListenerOptions.setOnce(true);
treeItem
.element()
.addEventListener("webkitTransitionEnd", stopListener, addEventListenerOptions);
treeItem.element().addEventListener("MSTransitionEnd", stopListener, addEventListenerOptions);
treeItem
.element()
.addEventListener("mozTransitionEnd", stopListener, addEventListenerOptions);
treeItem.element().addEventListener("oanimationend", stopListener, addEventListenerOptions);
treeItem.element().addEventListener("animationend", stopListener, addEventListenerOptions);
createAnimationEndListeners(stopListener);

String expandedHeight = treeItem.getAttribute(DUI_EXPANDED_HEIGHT);
treeItem.setCssProperty(this.heightVar, expandedHeight + "px");
treeItem.removeAttribute(DUI_COLLAPSED);
}
}

private void createAnimationEndListeners(EventListener stopListener) {
AddEventListenerOptions addEventListenerOptions = AddEventListenerOptions.create();
addEventListenerOptions.setOnce(true);
treeItem
.element()
.addEventListener("webkitTransitionEnd", stopListener, addEventListenerOptions);
treeItem.element().addEventListener("MSTransitionEnd", stopListener, addEventListenerOptions);
treeItem.element().addEventListener("mozTransitionEnd", stopListener, addEventListenerOptions);
treeItem.element().addEventListener("oanimationend", stopListener, addEventListenerOptions);
treeItem.element().addEventListener("animationend", stopListener, addEventListenerOptions);
}

/** @dominokit-site-ignore {@inheritDoc} */
@Override
public void collapse(Element element) {
treeItem.setCssProperty(this.heightVar, getActualHeight() + "px");
boolean disableAnimation = dui_transition_none.isAppliedTo(treeItem);
treeItem.apply(
self -> {
if (self.isAttached()) {
this.handlers.onBeforeCollapse().run();
collapseElement(element);
handlers.onCollapseCompleted().run();
} else {
self.onAttached(
(e, mutationRecord) -> {
this.handlers.onBeforeCollapse().run();
treeItem.addCss(dui_transition_none);
collapseElement(element);
if (!disableAnimation) {
dui_transition_none.remove(treeItem);
}
handlers.onCollapseCompleted().run();
});
}
});
if (!expanding) {
collapsing = true;
treeItem.setCssProperty(this.heightVar, getActualHeight() + "px");
boolean disableAnimation = dui_transition_none.isAppliedTo(treeItem);
treeItem.apply(
self -> {
if (self.isAttached()) {
this.handlers.onBeforeCollapse().run();
EventListener stopListener =
evt -> {
handlers.onCollapseCompleted().run();
collapsing = false;
};
createAnimationEndListeners(stopListener);
collapseElement(element);
} else {
self.onAttached(
(e, mutationRecord) -> {
this.handlers.onBeforeCollapse().run();
treeItem.addCss(dui_transition_none);
EventListener stopListener =
evt -> {
if (!disableAnimation) {
dui_transition_none.remove(treeItem);
}
handlers.onCollapseCompleted().run();
collapsing = false;
};
createAnimationEndListeners(stopListener);
collapseElement(element);
});
}
});
}
}

private void resetParentHeight(TreeItem<?> treeItem) {
Expand Down

0 comments on commit 05913e8

Please sign in to comment.