mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
fix to prevent ghostclick of an input under a modal
This commit is contained in:
@@ -15,47 +15,86 @@
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<body ng-controller="AppCtrl">
|
||||
|
||||
<view id="view">
|
||||
<header>
|
||||
<label class="item item-input">
|
||||
<span class="input-label">Header</span>
|
||||
<input type="text" value="header input">
|
||||
</label>
|
||||
</header>
|
||||
<content has-header="true" padding="true" overflow-scroll="false">
|
||||
<div class="list">
|
||||
<label class="item item-input">
|
||||
<span class="input-label" ng-required>Your Name</span>
|
||||
<input type="text" value="name">
|
||||
<span class="input-label">Your Name</span>
|
||||
<input type="text" value="name input">
|
||||
</label>
|
||||
<a class="item item-checkbox no-arrow">
|
||||
<div class="item item-checkbox">
|
||||
<span class="input-label">Remember me</span>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox">
|
||||
</label>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label class="item item-input">
|
||||
<span class="input-label">From</span>
|
||||
<input type="text" class="text-right" value="from">
|
||||
<input type="text" value="from input">
|
||||
</label>
|
||||
|
||||
<label class="item item-input">
|
||||
<span class="input-label">To</span>
|
||||
<input type="text" class="text-right" value="to">
|
||||
<input type="text" value="to input">
|
||||
</label>
|
||||
|
||||
<label class="item item-input item-stacked-label">
|
||||
<label class="item item-input item-stacked-label">
|
||||
<span class="input-label">Comment</span>
|
||||
<textarea id="textarea">textarea</textarea>
|
||||
<textarea id="textarea">comment textarea</textarea>
|
||||
</label>
|
||||
|
||||
<button class="button button-block button-energized">
|
||||
Submit
|
||||
<button class="button button-block button-energized" ng-click="openModal()">
|
||||
Open Modal
|
||||
</button>
|
||||
|
||||
<p>
|
||||
<a href="clickTests.html">Click Tests</a> -
|
||||
<a href="tapInputs.html">Tap Inputs</a> -
|
||||
<a href="/test/">CSS Tests</a>
|
||||
</p>
|
||||
</content>
|
||||
</view>
|
||||
|
||||
<script id="modal.html" type="text/ng-template">
|
||||
<div class="modal" ng-controller="ModalCtrl">
|
||||
<header class="bar bar-header bar-positive">
|
||||
<h1 class="title">New Contact</h1>
|
||||
<button class="button button-clear button-primary" ng-click="closeModal()" stop-event="click">Cancel</button>
|
||||
</header>
|
||||
<content has-header="true">
|
||||
<div class="padding">
|
||||
<div class="list">
|
||||
<label class="item item-input">
|
||||
<span class="input-label">First Name</span>
|
||||
<input type="text" placeholder="">
|
||||
</label>
|
||||
<label class="item item-input">
|
||||
<span class="input-label">Last Name</span>
|
||||
<input type="text" placeholder="">
|
||||
</label>
|
||||
<label class="item item-input">
|
||||
<span class="input-label">Email</span>
|
||||
<input type="text" placeholder="">
|
||||
</label>
|
||||
<button class="button button-full button-positive" ng-click="closeModal()">Create</button>
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script src="../../../../dist/js/ionic.bundle.js"></script>
|
||||
<script>
|
||||
angular.module('navTest', ['ionic']);
|
||||
|
||||
var msgs = [];
|
||||
var timerId;
|
||||
@@ -91,6 +130,29 @@
|
||||
return d.getSeconds() + '.' + d.getMilliseconds();
|
||||
}
|
||||
|
||||
|
||||
angular.module('navTest', ['ionic'])
|
||||
|
||||
.controller('AppCtrl', function($scope, $ionicModal) {
|
||||
|
||||
$scope.openModal = function() {
|
||||
$scope.modal.show();
|
||||
};
|
||||
$ionicModal.fromTemplateUrl('modal.html', function(modal) {
|
||||
$scope.modal = modal;
|
||||
}, {
|
||||
animation: 'slide-in-up',
|
||||
focusFirstInput: true
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
.controller('ModalCtrl', function($scope) {
|
||||
$scope.closeModal = function() {
|
||||
$scope.modal.hide();
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -47,7 +47,6 @@
|
||||
|
||||
if(ele.tagName === 'INPUT' || ele.tagName === 'TEXTAREA' || ele.tagName === 'SELECT') {
|
||||
ele.focus();
|
||||
e.preventDefault();
|
||||
} else {
|
||||
ele.blur();
|
||||
}
|
||||
@@ -72,14 +71,14 @@
|
||||
if( isRecentTap(e) ) {
|
||||
// if a tap in the same area just happened, don't continue
|
||||
console.debug('tapPolyfill', 'isRecentTap', ele.tagName);
|
||||
return;
|
||||
return stopEvent(e);
|
||||
}
|
||||
|
||||
if(ele.lastClick && ele.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)
|
||||
console.debug('tapPolyfill', 'recent lastClick', ele.tagName);
|
||||
return;
|
||||
return stopEvent(e);
|
||||
}
|
||||
|
||||
while(ele) {
|
||||
@@ -120,9 +119,7 @@
|
||||
// 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
|
||||
console.debug('preventGhostClick', 'labelLastTap');
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
return false;
|
||||
return stopEvent(e);
|
||||
}
|
||||
|
||||
// remember the last time this label was clicked to it can prevent a second label ghostclick
|
||||
@@ -130,7 +127,7 @@
|
||||
|
||||
// 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
|
||||
// the native layer still needs to click the input which the label controls
|
||||
console.debug('preventGhostClick', 'label stopPropagation');
|
||||
e.stopPropagation();
|
||||
return;
|
||||
@@ -139,17 +136,13 @@
|
||||
if( isRecentTap(e) ) {
|
||||
// a tap has already happened at these coordinates recently, ignore this event
|
||||
console.debug('preventGhostClick', 'isRecentTap', e.target.tagName);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
return false;
|
||||
return stopEvent(e);
|
||||
}
|
||||
|
||||
if(e.target.lastTap && e.target.lastTap + CLICK_PREVENT_DURATION > Date.now()) {
|
||||
// this element has already had the tap poly fill run on it recently, ignore this event
|
||||
console.debug('preventGhostClick', 'e.target.lastTap', e.target.tagName);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
return false;
|
||||
return stopEvent(e);
|
||||
}
|
||||
|
||||
// remember the last time this element was clicked
|
||||
@@ -160,6 +153,12 @@
|
||||
recordCoordinates(e);
|
||||
}
|
||||
|
||||
function stopEvent(e){
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
function isRecentTap(event) {
|
||||
// loop through the tap coordinates and see if the same area has been tapped recently
|
||||
var tapId, existingCoordinates, currentCoordinates,
|
||||
|
||||
Reference in New Issue
Block a user