Chevron buttons are unreliable for touch usage
It is difficult to trigger the click action on the chevron buttons using touch, using Chromium on Microsoft Surface Pro & Webkit on iPAD - I suspect this problem will occur on any touch platform.
My application uses angular-touch. I guess that the problem observed is related to the use of this particular component.
A quick double-click speed action may trigger a click; a longer touch never triggers a click.
It is not clear to me why this is occurring as I do not have this problem with code I have written for the same platforms that combines both drag and click handling on the same element.
As a workaround rather than a cure, I used the touchend event to trigger a click. The code is fussy about which element it operates upon, as any page element seems to be capable of triggering a touchend event in the ui-layout handler - this does not sound right to me.
The main changes for this workaround are applied to the mouseup / touchend handler as follows:
htmlElement.on('mouseup touchend', function (event) {
scope.$apply(angular.bind(ctrl, ctrl.mouseUpHandler, event));
htmlElement.off('mousemove touchmove');
if (event.type === "touchend") {
var touchMoveDistance = Math.abs(ctrl.lastPos - ctrl.startPos);
if (event.target.tagName === "A" &&
event.target.children.length === 1 &&
event.target.children[0].className.indexOf("glyphicon-chevron") !== -1 &&
touchMoveDistance < 5) {
$(event.target).trigger("click");
} else if (event.target.tagName === "SPAN" &&
event.target.className.indexOf("glyphicon-chevron") !== -1 &&
touchMoveDistance < 5) {
$(event.target.parentNode).trigger("click");
}
}
});
I am sure this could be coded better, but it works. I did not succeed in calling directly the appropriate click handler, as the ctrl variable in this event handler does not contain the correct data.
I added the following to the touchstart handler, to allow calculation of touch move distance, as I did not want the click action to trigger when the user drags the splitbar:
if (e.originalEvent && e.originalEvent.changedTouches) {
ctrl.startPos = e.originalEvent.changedTouches[0][ctrl.sizeProperties.mouseProperty];
ctrl.lastPos = ctrl.startPos;
}
To support this, I added the following to the controller, renaming the original lastPos and all its references:
ctrl.startPos = 0;
ctrl.lastPos = 0;
I must be only person using this component on touch platforms, as nobody has commented on this problem; it works well as long as the split bar is wide enough - as well as increasing the bar width, I had also increased the button area size.
I have now upgraded my implementation to make the whole splitbar trigger the button action, using top and bottom half to correspond to the two buttons (this would be left and right if I was to implement this for a row split, which I have not done.) The following is the code, with includes a modified handler for mouseup/touchend.
function touchEndEventSelectAnchorToClick(event) {
if (event.target.children[0].offsetTop === 0) { // only left chevron displayed?
$(event.target.children[1]).trigger("click");
} else if (event.target.children[1].offsetTop === 0) { // only right chevron displayed?
$(event.target.children[0]).trigger("click");
} else {
var $secondAnchor = $(event.target.children[1]);
var touchEndY = event.originalEvent.changedTouches[0].screenY;
if (touchEndY < $secondAnchor.offset().top) { // touch in top or bottom of div?
$(event.target.children[0]).trigger("click");
} else {
$secondAnchor.trigger("click");
}
}
}
htmlElement.on('mouseup touchend', function (event) {
scope.$apply(angular.bind(ctrl, ctrl.mouseUpHandler, event));
htmlElement.off('mousemove touchmove');
if (event.type === "touchend") {
var touchMoveDistance = Math.abs(ctrl.lastPos - ctrl.startPos);
if (event.target.tagName === "A" &&
event.target.children.length === 1 &&
event.target.children[0].className.indexOf("glyphicon-chevron") !== -1 &&
touchMoveDistance < 5) {
$(event.target).trigger("click");
} else if (event.target.tagName === "SPAN" &&
event.target.className.indexOf("glyphicon-chevron") !== -1 &&
touchMoveDistance < 5) {
$(event.target.parentNode).trigger("click");
} else if (event.target.tagName === "DIV" &&
event.target.className.indexOf("ui-splitbar") !== -1 &&
touchMoveDistance < 5) {
touchEndEventSelectAnchorToClick(event);
}
}
});
Not sure about making the whole splitbar a button, but can you create a PR for the first solution?
I'll take a look at this.
I have created a PR for the first solution.
Unfortunately it appears that the fix applied for #82, was incorrect - well at least for the test cases I use. My PR fixes touch usage when the jQuery library is present.
Sorry that I've left some problems in the unit tests, but I cannot spend any more time on this at the moment.