IScroll 4 не работает с элементом формы <select> iPhone Safari и Android-браузер
Я использую этот код HTML:
<form action="#" method="post">
<fieldset>
<label class="desc" id="title10" for="Field10">
How many children do you have?
</label>
<select id="Field10" name="Field10" class="field select large" tabindex="5">
<option value="0" selected="selected">0 </option>
<option value="1">1 </option>
<option value="2">2 </option>
<option value="3">3 </option>
<option value="4">4 </option>
<option value="5">5 </option>
<option value="6">6 </option>
<option value="7">7 </option>
<option value="8">8 </option>
<option value="9">9 </option>
</select>
<input type="submit" value="Send message" />
</fieldset>
</form>
<select>
не работает на iPhone и Android. Когда я нажимаю кнопку выбора, ничего не происходит.
Я использую iScroll 4, который создает проблему.
<script type="application/javascript" src="iscroll-lite.js"></script>
<script type="text/javascript">
var myScroll;
function loaded() {
myScroll = new iScroll('wrapper');
}
document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
document.addEventListener('DOMContentLoaded', loaded, false);
</script>
Я думаю, это решение, но я не знаю, как его реализовать.
Ответы
Ответ 1
Проблема заключается в том, что iScroll отменяет поведение вашего тега select
по умолчанию (не очень хорошая реализация, если вы спросите меня).
Это происходит в функции _start()
в строке 195:
e.preventDefault();
Если вы прокомментируете это, вы заметите, что тег select
работает снова.
Но комментирование означает, что вы взломали библиотеку, которая может сломать другие желаемые функции iScroll. Итак, вот лучшее обходное решение:
var selectField = document.getElementById('Field10');
selectField.addEventListener('touchstart' /*'mousedown'*/, function(e) {
e.stopPropagation();
}, false);
Этот код позволит использовать поведение по умолчанию, не распространяя событие на iScroll, где он все закручивает.
Так как ваш JS не находится внутри какого-либо события jQuery-like onReady()
, вам нужно убедиться, что вы поместите этот код ПОСЛЕ HTML, где определены ваши элементы select
.
Обратите внимание, что для мобильных устройств событие touchstart
, но для вашего браузера вашего компьютера это будет mousedown
Ответ 2
У меня была такая же проблема в iScroll 4.1.9 на Android, я просто заменил строку 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(); },
которые позволяют сфокусироваться на тегах ввода, выбора и textarea
Ответ 3
Наконец, это исправлено для 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.
Наконец, некоторый дополнительный код iscroll, который необходимо исключить, когда useTransform имеет значение false:
// 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;
Пробовал несколько других методов, прежде чем понять, что это связано с css, который добавляет iscroll.
Ответ 4
Я знаю, что поздно, но это может быть полезно для кого-то,
напишите следующий код в событии showhow, но убедитесь, что div id не совпадает.
это потому, что iscroller предотвращает поведение элементов по умолчанию
$('#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);
});
Ответ 5
Вот решение
/* 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);
}
});
Ответ 6
другой пример кода для решения. и спасибо за предыдущие комментарии!
Использование 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);
});
}
Ответ 7
Замена строки, 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
Работы
Ответ 8
Начните с этого кода. Это решение работало для меня:
<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>
Ответ 9
Я опаздываю, но я оставляю вам свое решение.
Если вы используете jQuery, вы можете попробовать это.
$('input, textarea, button, a, select').off('touchstart mousedown').on('touchstart mousedown', function(e) {
e.stopPropagation();
});
Ответ 10
// 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 в последней строке...
Провел весь день отладки и реализации всех предлагаемых решений безрезультатно...
Ответ 11
он любой.
Я знаю обо всех ваших ответах, но у меня есть новый способ предложить. без java- script или отбрасывать функции 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%, проверьте его
Ответ 12
Есть ошибка с Android, когда -webkit-transform: translate3d применяется к контейнеру с полем выбора или паролем [1]. Поле в коробке, чтобы активировать эти элементы, перемещается, и не там, где вы думаете, что они будут. Кроме того, поля паролей рисуются в другом месте, поэтому кажется, что у вас есть два входных элемента вместо одного.
Я работаю в AppMobi, и мы разработали библиотеку инструментальных средств, для которой есть исправления. Мы внедрили пользовательские виджеты флажков и заменили поле ввода пароля. Проверьте это ниже.
https://github.com/imaffett/AppMobi.toolkit
[1] Я думаю, автор комментария говорит об этой ошибке https://bugs.webkit.org/show_bug.cgi?id=50552
Ответ 13
Вот очень легкое решение, которое сработало для меня. Я заметил в браузерах Android, что при начальной загрузке страницы я не мог нажать на поле выбора, но мне удалось щелкнуть текстовое поле ввода, которое я использовал для поиска. Затем я заметил, что после того, как я нажал на поле ввода текста, он узнает, что я нажимаю кнопку выбора. Так что все, что я сделал, это добавить к функции javascript, которую я использовал для загрузки страницы поиска...
$('#search').focus();
Поэтому, когда страница поиска загружается, она автоматически фокусируется на текстовом поле ввода, но не открывает клавиатуру, и именно этого я и хотел. Извините, мой пример не является общедоступным, но, надеюсь, это может помочь кому-то.
Ответ 14
Я немного опаздываю в игру, но если кто-то все еще интересуется, я применил подход @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">
Ответ 15
попробуйте это решение
if (e.target.nodeName.toLowerCase() == "select" || e.target.tagName.toLowerCase() == 'input' || e.target.tagName.toLowerCase() == 'textarea') {
вернуть; }
Ответ 16
Как насчет того, что работает для меня!:
$('input, select').on('touchstart', function(e) {
e.stopPropagation();
});
Ответ 17
Даже если вы исключили элементы формы в onBeforeScrollStart(), есть еще одна ошибка в браузере android 2.2/2.3 в браузере android:
https://www.html5dev-software.intel.com/viewtopic.php?f=26&t=1278
https://github.com/01org/appframework/issues/104
Вы не можете вводить символы китайского языка в элементы ввода в div с типом css -webkit-transform. Искрол 4 применил "-webkit-transform" с помощью скроллера div.
Решение состоит в том, чтобы сохранить поля формы в абсолютном div из скроллера.
Ответ 18
Ошибка браузера Android - результат очень старой версии WebKit внутри Android, даже в Android 4.3. Коренная причина ошибки - неправильная обработка события click, которое iScroll отправляет обратно в браузер (удаление preventDefault просто прекращает отправку этого события кликов)
Браузер Android Chrome свободен от этой ошибки, потому что он обновил библиотеку WebKit внутри.
Ожидание обновления Android WebKit от Google.