Skip to content

Commit

Permalink
fix:#7 accessible action buttons
Browse files Browse the repository at this point in the history
  • Loading branch information
scottdurow committed Dec 1, 2022
1 parent 5ac1686 commit 8a5d56e
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 25 deletions.
2 changes: 1 addition & 1 deletion code-component/PowerDragDrop/ControlManifest.Input.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest>
<control namespace="CustomControl" constructor="PowerDragDrop" version="1.0.21" display-name-key="PowerDragDrop" description-key="PowerDragDrop_Desc" control-type="standard">
<control namespace="CustomControl" constructor="PowerDragDrop" version="1.0.23" display-name-key="PowerDragDrop" description-key="PowerDragDrop_Desc" control-type="standard">
<!--external-service-usage node declares whether this 3rd party PCF control is using external service or not, if yes, this control will be considered as premium and please also add the external domain it is using.-->
<external-service-usage enabled="false"></external-service-usage>
<property name="DropZoneID" description-key="DropZoneID_Desc" display-name-key="DropZoneID" required="true" usage="input" of-type="SingleLine.Text"/>
Expand Down
75 changes: 51 additions & 24 deletions code-component/PowerDragDrop/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ interface RegisteredZone {
zoneId: string;
maximumItems: number | undefined;
sortable: Sortable;
onActionClick: (ev: MouseEvent) => void;
}

const defaultSortableOptions: Sortable.Options = {
Expand Down Expand Up @@ -321,21 +322,26 @@ export class PowerDragDrop implements ComponentFramework.StandardControl<IInputs

if (zoneElement !== null && (!existingZoneRegistration || registeredOnDifferentElement)) {
this.trace('registerZones CREATE', zoneId);
this.zonesRegistered[zoneId] = {
const sortable = new Sortable(zoneElement, {
...this.getDynamicSortableOptions(),
group: masterDropZoneId,
onChoose: this.onChoose,
onUnchoose: this.onUnChoose,
onEnd: this.onEnd,
onMove: this.onMove,
filter: this.actionFilter,
});
const zoneRegistration = {
zoneId: zoneId,
index: index,
maximumItems: maximumItems[index],
sortable: new Sortable(zoneElement, {
...this.getDynamicSortableOptions(),
group: masterDropZoneId,
onChoose: this.onChoose,
onUnchoose: this.onUnChoose,
onEnd: this.onEnd,
onFilter: this.onFilter,
onMove: this.onMove,
filter: this.actionFilter,
}),
onActionClick: (ev: MouseEvent) => {
this.actionClick(ev, zoneElement);
},
sortable: sortable,
};
this.zonesRegistered[zoneId] = zoneRegistration;
zoneElement.addEventListener('click', zoneRegistration.onActionClick);
}
});

Expand Down Expand Up @@ -377,7 +383,12 @@ export class PowerDragDrop implements ComponentFramework.StandardControl<IInputs
const zone = this.zonesRegistered[zoneId];
// Prevent un-registering a zone if there is currently a drag happening
if (this.currentItemZone === null) {
zone.sortable.destroy();
try {
zone.sortable.destroy();
zone.sortable.el.removeEventListener('click', zone.onActionClick);
} catch (e) {
this.trace('unRegisterZone Error', e);
}
} else {
this.sortablesToDestroy.push(zone.sortable);
}
Expand Down Expand Up @@ -417,18 +428,6 @@ export class PowerDragDrop implements ComponentFramework.StandardControl<IInputs
}
}

private onFilter = (event: Sortable.SortableEvent) => {
const actionItemId = event.item.getAttribute(RECORD_ID_ATTRIBUTE);
const actionName = this.getActionFromClass(event.target);
if (actionItemId && actionName) {
this.raiseOnActionScheduled = true;
// Remove the action specifier
this.actionName = actionName.replace(CSS_STYLE_CLASSES.ActionClassPrefix, '');
this.actionItemId = actionItemId;
this.notifyOutputChanged();
}
};

private removeSpaces(input: string) {
return input.replace(/\s/gi, '');
}
Expand Down Expand Up @@ -493,4 +492,32 @@ export class PowerDragDrop implements ComponentFramework.StandardControl<IInputs
}
return false;
};

actionClick = (ev: MouseEvent, zoneElement: HTMLElement): void => {
// For accessibility, action elements raise the OnAction event here
// rather than the onFilter event which only fires for touch events
if (ev.target && (ev.target as HTMLElement).className) {
const actionName = this.getActionFromClass(ev.target as HTMLElement);
// Actions have a class prefixed with action-
if (actionName) {
// Find the closest sortable item using the item class identifier
const element = Sortable.utils.closest(
ev.target as HTMLElement,
'.' + CSS_STYLE_CLASSES.Item,
zoneElement,
);
if (element) {
// Get the item id from the data attribute
const actionItemId = element.getAttribute(RECORD_ID_ATTRIBUTE);
if (actionItemId) {
this.raiseOnActionScheduled = true;
// Remove the action specifier and raise the event
this.actionName = actionName.replace(CSS_STYLE_CLASSES.ActionClassPrefix, '');
this.actionItemId = actionItemId;
this.notifyOutputChanged();
}
}
}
}
};
}

0 comments on commit 8a5d56e

Please sign in to comment.