19 回答
The problem is that iScroll cancels the default behavior of your select
tag (Not a very good implementation if you ask me).
This occurs in the _start()
function on line 195:
e.preventDefault();
If you comment that out you'll notice the select
tag works again.
But commenting it out means you've hacked the library which might break other desirable iScroll functionality. So here's a better workaround:
var selectField = document.getElementById('Field10');
selectField.addEventListener('touchstart' /*'mousedown'*/, function(e) {
e.stopPropagation();
}, false);
That code will allow the default behavior to occur, without propagating the event to iScroll where it screws everything up.
Since your JS is not inside any jQuery-like onReady()
event, you'll have to make sure to you put this code AFTER the HTML where your select
elements are defined.
Note that for mobile devices the event is touchstart
, but for your PC browser it will be mousedown
我在 android 上的 iScroll 4.1.9 上遇到了同样的问题,我只是替换了第 95 行(在我的版本上):
onBeforeScrollStart: function (e) { e.preventDefault(); },
经过 :
onBeforeScrollStart: function (e) {var nodeType = e.explicitOriginalTarget ? e.explicitOriginalTarget.nodeName.toLowerCase():(e.target ? e.target.nodeName.toLowerCase():''); if(nodeType !='select' && nodeType !='option' && nodeType !='input' && nodeType!='textarea') e.preventDefault(); },
可以专注于输入、选择和文本区域标签
最后为Android修复了这个问题。最终在 iscroll.js 中修改了几行
下面是我们如何初始化 iScroll。
// code from https://github.com/cubiq/iscroll/blob/master/examples/form-fields/index.html
// don't preventDefault for form controls
_menuScroll = new iScroll('menu_wrapper',{
useTransform: false,
onBeforeScrollStart: function (e) {
var target = e.target;
while (target.nodeType != 1) target = target.parentNode;
if (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA')
e.preventDefault();
}
});
onBeforeScrollStart 允许控件的默认行为发生。Android浏览器好像useTransform有问题,所以转为false。
最后,当 useTransform 为 false 时,需要排除一些额外的 iscroll 代码:
// iscroll.js v4.1.9
// line 216:
if (that.options.useTransform) bar.style.cssText += ';pointer-events:none;-' + vendor + '-transition-property:-' + vendor + '-transform;-' + vendor + '-transition-timing-function:cubic-bezier(0.33,0.66,0.66,1);-' + vendor + '-transition-duration:0;-' + vendor + '-transform:' + trnOpen + '0,0' + trnClose;
// line 295:
if (that.options.useTransform) that[dir + 'ScrollbarIndicator'].style[vendor + 'Transform'] = trnOpen + (dir == 'h' ? pos + 'px,0' : '0,' + pos + 'px') + trnClose;
在意识到它与iscroll添加的css有关之前尝试了其他几种方法。
我知道迟到了,但它可能对某些人有帮助,
在 pageshow 事件中编写以下代码,但请确保 div id 不相同。
这是因为,isroller 阻止了元素的默认行为
$('#yourpage').bind('pageshow',function (event, ui) {
var myScroll;
if (this.id in myScroll) {
myScroll[this.id].refresh();
}else{
myScroll[this.id] = new iScroll('wrapper', { //wrapper is div id
checkDOMChanges: true,
onBeforeScrollStart: function (e) {
var target = e.target;
while (target.nodeType != 1)
target =target.parentNode;
if (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA'){ e.preventDefault(); }
}
});
}
document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
});
这是解决方案
/* on page add this after all scripts */
<script type="text/javascript">
var myScroll;
function loaded() {
myScroll = new iScroll('wrapper');
}
document.addEventListener('DOMContentLoaded', function(){ setTimeout(loaded,500);}, false);
</script>
/* attach a script for fix */
$(document).ready(function(){
var my_select = document.getElementsByTagName('select');
for (var i=0; i<my_select.length; i++) {
my_select[i].addEventListener('touchstart' /*'mousedown'*/, function(e) {
myScroll.destroy();
setTimeout(function(){myScroll = new iScroll('wrapper');},500);
}, false);
}
/*if you have input problems */
var input = document.getElementById('input');
if (input) {
input.addEventListener('touchstart' /*'mousedown'*/, function(e) {
e.stopPropagation();
}, false);
}
});
换线,onBeforeScrollStart: function (e) { e.preventDefault(); },
经过
onBeforeScrollStart: function (e) {
var nodeType = e.explicitOriginalTarget ? e.explicitOriginalTarget.nodeName.toLowerCase():(e.target ? e.target.nodeName.toLowerCase():'');
if(nodeType !='select' && nodeType !='option' && nodeType !='input' && nodeType!='textarea') {
e.preventDefault();
}
},
在iScroll.js
作品中
解决方案的另一个代码示例。并感谢之前的评论!使用jQuery!
后:
$(document).ready(function() {
document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
document.addEventListener('DOMContentLoaded', setTimeout(function () { loaded(); }, 200), false);
});
在加载函数中
function loaded() {
var allSelects = $('select');
allSelects.each(function(index, item) {
item.addEventListener('touchstart' /*'mousedown'*/, function(e) { e.stopPropagation(); }, false);
});
}
从这段代码开始。这个解决方案对我有用:
<script type="text/javascript">
var myScroll;
function iScrollLoad() {
myScroll = new iScroll('wrapper');
enableFormsInIscroll();
}
function enableFormsInIscroll(){
[].slice.call(document.querySelectorAll('input, select, button, textarea')).forEach(function(el){
el.addEventListener(('ontouchstart' in window)?'touchstart':'mousedown', function(e){
e.stopPropagation();
})
})
}
document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
document.addEventListener('DOMContentLoaded', function () { setTimeout(iScrollLoad, 200); }, false);
</script>
// Setup myScroll
myScroll = new IScroll('#wrapper', {
scrollX: horizontalSwipe,
scrollY: !horizontalSwipe,
momentum: false,
snap: document.querySelectorAll('#scroller .slide'),
snapSpeed: 400,
bounceEasing: 'back',
keyBindings: true,
click: true
});
对我来说,我只需要在最后一行添加 click: true ......花了一整天的时间调试和实施所有建议的解决方案无济于事......
我迟到了,但我把我的解决方案留给你。
如果您使用的是 jQuery,您可以尝试一下。
$('input, textarea, button, a, select').off('touchstart mousedown').on('touchstart mousedown', function(e) {
e.stopPropagation();
});
他任何人。
我知道你所有的答案,但我有新的方法可以提供。没有 java-script 或 drop iscroll 函数。
所有这些解决方案的最大问题是当您滚动输入的元素时,页面上没有滚动。当你只输入一个或两个输入时并不重要,但是当页面是一个表单时,滚动页面有很大的问题。
我提供的解决方案是将输入包装在标签标签中,或者使用指向输入的指针制作标签标签。然后使用绝对定位和 z-index 制作输入上方的标签。当您触摸标签时,您会关注输入。
请举例
HTML
<fieldset>
<label>
<input type="text" />
</label>
</fieldset>
CSS
fieldset {position:relative;z-index:20;}
label {position:relative;z-index:initial;}
input {position:relative;z-index:-1;}
您也可以通过这种方式将输入的标签侧放入输入的绝对位置并将其放入标签区域
正在 100% 工作,检查一下
即使您在 onBeforeScrollStart() 中排除了表单元素,android 2.2/2.3 浏览器/webview 中还有另一个错误:
https://www.html5dev-software.intel.com/viewtopic.php?f=26&t=1278 https://github.com/01org/appframework/issues/104
您不能在具有“-webkit-transform” css 样式的 div 中的输入元素中输入中文字符。iscroll 4 将“-webkit-transform”与滚动条 div 一起应用。
解决方案是将表单字段保留在滚动条之外的绝对 div 中。
怎么样,这对我有用!:
$('input, select').on('touchstart', function(e) {
e.stopPropagation();
});
当 -webkit-transform:translate3d 应用于具有选择框或密码框 [1] 的容器时,Android 存在错误。激活这些元素的方框区域移动,而不是您认为它们所在的位置。此外,密码框绘制在不同的位置,因此看起来您有两个输入元素而不是一个。
我在 AppMobi 工作,我们开发了一个工具包库来修复这些问题。我们已经实现了自定义选择框小部件并替换了密码输入字段。看看下面。
https://github.com/imaffett/AppMobi.toolkit
[1] 我认为评论的作者正在谈论这个错误https://bugs.webkit.org/show_bug.cgi?id=50552
我玩游戏有点晚了,但如果有人仍然感兴趣,我采用@bastien 的方法并对其进行了一些调整以使其在 Android 上运行。我在我的实现中使用 JQM。
基本上我所做的是:
function scrollMe(element) {
var contentID = $wrapper.get(0).id;
var scroller = elm.find('[data-iscroll="scroller"]').get(0);
if (scroller) {
var iscroll = new iScroll(contentID, {
hScroll : false,
vScroll : true,
hScrollbar : false,
vScrollbar : true,
fixedScrollbar : true,
fadeScrollbar : false,
hideScrollbar : false,
bounce : true,
momentum : true,
lockDirection : true,
useTransition : true,
//the preceding options and their values do not have any to do with the fix
//THE FIX:
onBeforeScrollStart: function(e) {
var nodeType = e.explicitOriginalTarget ? e.explicitOriginalTarget.nodeName.toLowerCase() : (e.target ? e.target.nodeName.toLowerCase():''); //get element node type
if(nodeType !='select' && nodeType !='option' && nodeType !='input' && nodeType!='textarea') e.preventDefault(); //be have normally if clicked element is not a select, option, input, or textarea.
else if (iscroll != null) { //makes sure there is an instance to destory
iscroll.destroy();
iscroll = null;
//when the user clicks on a form element, my previously instanced iscroll element is destroyed
}
},
onScrollStart: function(e) {
if (iscroll == null) { //check to see if iscroll instance was previously destoryed
var elm = $.mobile.activePage; //gets current active page
var scrollIt = setTimeout( function(){ scrollMe(elm) }, 0 );
} //recursively call function that re-instances iscroll element, as long as the user doesn't click on a form element
}
});
elm.data("iscroll-plugin", iscroll);
}
}
基本上,您需要做的就是在用户选择表单元素时销毁您的 iScroll 实例,但在他们实际开始滚动之前(onBeforeScrollStart)并且如果用户单击具有自定义属性的元素内的任何其他内容data-iscroll="scroller"
,他们可以使用滚动iScroll 像往常一样。
<div data-role="page" id="pageNameHere" data-iscroll="enable">
试试这个解决方案 if (e.target.nodeName.toLowerCase() == "select" || e.target.tagName.toLowerCase() == 'input' || e.target.tagName.toLowerCase() == 'textarea ') {
返回;}
这是一个对我有用的非常简单的修复方法。我注意到在 Android 浏览器中,在初始页面加载时我无法单击选择框,但我能够单击用于搜索的文本输入字段。然后我注意到,在我点击文本输入字段后,它会识别出我点击了一个选择框。所以我所做的只是将它添加到我用来加载搜索页面的 javascript 函数中......
$('#search').focus();
所以当搜索页面加载时,它会自动关注文本输入字段但不会弹出键盘,这正是我想要的。抱歉,我的示例无法公开访问,但希望这仍然可以帮助某人。
Android 浏览器错误是 Android 内部非常旧版本的 WebKit 的结果,即使在 Android 4.3 内部也是如此。错误的根本原因 - iScroll 发送回浏览器的点击事件处理错误(删除 preventDefault 只是停止发送此点击事件) Android Chrome 浏览器没有这个错误,因为它已经升级了内部的 WebKit 库。
等待 Google 的 Android WebKit 升级。
检查这个。这解决了我的问题
https://github.com/cubiq/iscroll/issues/576
在我选择的选项中
click:false, preventDefaultException:{tagName:/.*/}