initMouseEvent instead of MouseEvent, label ghost click fixes

This commit is contained in:
Adam Bradley
2014-01-29 19:59:44 -06:00
parent 4354828ce1
commit aac82a1ebb
4 changed files with 92 additions and 40 deletions

51
dist/js/ionic.js vendored
View File

@@ -1912,14 +1912,15 @@ window.ionic = {
ionic.clickElement = function(ele, e) {
// simulate a normal click by running the element's click method then focus on it
if(ele.disabled) return;
var c = getCoordinates(e);
// using initMouseEvent instead of MouseEvent for our Android friends
var clickEvent = document.createEvent("MouseEvents");
clickEvent.initMouseEvent('click', true, true, window,
1, 0, 0, c.x, c.y,
false, false, false, false, 0, null);
var c = getCoordinates(e.gesture);
var clickEvent = new MouseEvent('click', {
clientX: c.x,
clientY: c.y,
bubbles: true,
cancelable: true
});
ele.dispatchEvent(clickEvent);
if(ele.tagName === 'INPUT' || ele.tagName === 'TEXTAREA' || ele.tagName === 'SELECT') {
@@ -1949,11 +1950,12 @@ window.ionic = {
if(e.target.lastClick && e.target.lastClick + CLICK_PREVENT_DURATION > Date.now()) {
// if a click recently happend on this element, don't continue
// (yes on some devices it's possible for a click to happen before a touchend)
return;
}
while(ele) {
// climb up the DOM looking to see the tapped is, or has a parent, of one of these
// climb up the DOM looking to see if the tapped element is, or has a parent, of one of these
if( ele.tagName === "INPUT" ||
ele.tagName === "A" ||
ele.tagName === "BUTTON" ||
@@ -1984,9 +1986,22 @@ window.ionic = {
function preventGhostClick(e) {
if(e.target.tagName === "LABEL" && e.target.control) {
// if this is a label and it has an associated input, then the input's click event will
// propagate so don't bother letting this label's click propagate cuz it causes double clicks
// However, do NOT preventDefault, because the label still needs to click the input
// this is a label that has an associated input
if(e.target.control.labelLastTap && e.target.control.labelLastTap + CLICK_PREVENT_DURATION > Date.now()) {
// Android will fire a click for the label, and a click for the input which it is associated to
// this stops the second ghost click from the label from continuing
e.stopPropagation();
e.preventDefault();
return false;
}
// remember the last time this label was clicked to it can prevent a second label ghostclick
e.target.control.labelLastTap = Date.now();
// The input's click event will propagate so don't bother letting this label's click
// propagate cuz it causes double clicks. However, do NOT e.preventDefault(), because
// the label still needs to click the input
e.stopPropagation();
return;
}
@@ -2016,7 +2031,7 @@ window.ionic = {
function isRecentTap(event) {
// loop through the tap coordinates and see if the same area has been tapped recently
var tapId, existingCoordinates, currentCoordinates,
hitRadius = 15;
hitRadius = 20;
for(tapId in tapCoordinates) {
existingCoordinates = tapCoordinates[tapId];
@@ -2051,11 +2066,13 @@ window.ionic = {
function getCoordinates(event) {
// This method can get coordinates for both a mouse click
// or a touch depending on the given event
if(event) {
var touches = event.touches && event.touches.length ? event.touches : [event];
var e = (event.changedTouches && event.changedTouches[0]) ||
(event.originalEvent && event.originalEvent.changedTouches &&
event.originalEvent.changedTouches[0]) ||
var gesture = (event.gesture ? event.gesture : event);
if(gesture) {
var touches = gesture.touches && gesture.touches.length ? gesture.touches : [gesture];
var e = (gesture.changedTouches && gesture.changedTouches[0]) ||
(gesture.originalEvent && gesture.originalEvent.changedTouches &&
gesture.originalEvent.changedTouches[0]) ||
touches[0].originalEvent || touches[0];
if(e) return { x: e.clientX, y: e.clientY };

View File

File diff suppressed because one or more lines are too long

View File

@@ -16,7 +16,7 @@
<script src="../../../../dist/js/ionic-angular.js"></script>
<style>
.item-content {
padding: 2px !important;
padding: 8px !important;
}
.list {
margin: 5px !important;
@@ -38,7 +38,7 @@
<body ng-controller="MyCtrl">
<form id="form">
<button class="button" ng-click="buttonClick()">button</button>
<div class="div button" ng-click="buttonClick()">div</div>
<div class="div button" ng-click="divClick()">div</div>
{{ buttonValue }} -
{{ radioModel.data }}
@@ -100,6 +100,11 @@
console.log('button ng-click', 'click')
$scope.buttonValue = Math.floor(Math.random() * 9999);
};
$scope.divClick = function() {
console.log('div ng-click', 'click')
$scope.buttonValue = Math.floor(Math.random() * 9999);
};
$scope.radioModel = {}
$scope.radioChange = function() {
console.log('radio ng-change', 'change', $scope.radioModel.data)
@@ -154,7 +159,7 @@
console.log('mouseup');
});
document.addEventListener('click', function(event){
console.log('click', 'x: ' + event.clientX, 'y: ' + event.clientY);
console.log('click', 'clientX: ' + event.clientX, 'clientY: ' + event.clientY);
});
document.getElementById('clear').addEventListener('click', function(){
setTimeout(clearMsgs, 200);
@@ -172,6 +177,17 @@
var msgs = [];
var index = 0;
window.stopped = false;
var winConsoleError = console.error;
console.error = function() {
winConsoleError.apply(this, arguments);
var args = ['ERROR!'];
for (var i = 0, j = arguments.length; i < j; i++){
args.push(arguments[i]);
}
console.log.apply(this, args);
};
console.log = function() {
//return;
if(stopped) return;
@@ -186,6 +202,8 @@
msg = msg.join(', ');
if(arguments[0] === 'ERROR!') msg = '<span style="color:red;font-weight:bold">' + msg + '</span>';
if(arguments[0] === 'touchstart') msg = '<span style="color:blue">' + msg + '</span>';
if(arguments[0] === 'touchend') msg = '<span style="color:darkblue">' + msg + '</span>';

View File

@@ -32,14 +32,15 @@
ionic.clickElement = function(ele, e) {
// simulate a normal click by running the element's click method then focus on it
if(ele.disabled) return;
var c = getCoordinates(e);
// using initMouseEvent instead of MouseEvent for our Android friends
var clickEvent = document.createEvent("MouseEvents");
clickEvent.initMouseEvent('click', true, true, window,
1, 0, 0, c.x, c.y,
false, false, false, false, 0, null);
var c = getCoordinates(e.gesture);
var clickEvent = new MouseEvent('click', {
clientX: c.x,
clientY: c.y,
bubbles: true,
cancelable: true
});
ele.dispatchEvent(clickEvent);
if(ele.tagName === 'INPUT' || ele.tagName === 'TEXTAREA' || ele.tagName === 'SELECT') {
@@ -69,11 +70,12 @@
if(e.target.lastClick && e.target.lastClick + CLICK_PREVENT_DURATION > Date.now()) {
// if a click recently happend on this element, don't continue
// (yes on some devices it's possible for a click to happen before a touchend)
return;
}
while(ele) {
// climb up the DOM looking to see the tapped is, or has a parent, of one of these
// climb up the DOM looking to see if the tapped element is, or has a parent, of one of these
if( ele.tagName === "INPUT" ||
ele.tagName === "A" ||
ele.tagName === "BUTTON" ||
@@ -104,9 +106,22 @@
function preventGhostClick(e) {
if(e.target.tagName === "LABEL" && e.target.control) {
// if this is a label and it has an associated input, then the input's click event will
// propagate so don't bother letting this label's click propagate cuz it causes double clicks
// However, do NOT preventDefault, because the label still needs to click the input
// this is a label that has an associated input
if(e.target.control.labelLastTap && e.target.control.labelLastTap + CLICK_PREVENT_DURATION > Date.now()) {
// Android will fire a click for the label, and a click for the input which it is associated to
// this stops the second ghost click from the label from continuing
e.stopPropagation();
e.preventDefault();
return false;
}
// remember the last time this label was clicked to it can prevent a second label ghostclick
e.target.control.labelLastTap = Date.now();
// The input's click event will propagate so don't bother letting this label's click
// propagate cuz it causes double clicks. However, do NOT e.preventDefault(), because
// the label still needs to click the input
e.stopPropagation();
return;
}
@@ -136,7 +151,7 @@
function isRecentTap(event) {
// loop through the tap coordinates and see if the same area has been tapped recently
var tapId, existingCoordinates, currentCoordinates,
hitRadius = 15;
hitRadius = 20;
for(tapId in tapCoordinates) {
existingCoordinates = tapCoordinates[tapId];
@@ -171,11 +186,13 @@
function getCoordinates(event) {
// This method can get coordinates for both a mouse click
// or a touch depending on the given event
if(event) {
var touches = event.touches && event.touches.length ? event.touches : [event];
var e = (event.changedTouches && event.changedTouches[0]) ||
(event.originalEvent && event.originalEvent.changedTouches &&
event.originalEvent.changedTouches[0]) ||
var gesture = (event.gesture ? event.gesture : event);
if(gesture) {
var touches = gesture.touches && gesture.touches.length ? gesture.touches : [gesture];
var e = (gesture.changedTouches && gesture.changedTouches[0]) ||
(gesture.originalEvent && gesture.originalEvent.changedTouches &&
gesture.originalEvent.changedTouches[0]) ||
touches[0].originalEvent || touches[0];
if(e) return { x: e.clientX, y: e.clientY };