Nuestra aplicación utiliza selectionStart en los campos de entrada para determinar si mover automáticamente al usuario al campo siguiente / anterior cuando presione las teclas de flecha (es decir, cuando la selección está al final del texto y el usuario presiona la flecha derecha, nos movemos a el siguiente campo, de lo contrario)
Chrome ahora evita que selectionStart se utilice donde type = "number". Ahora lanza la excepción:
Failed to read the 'selectionStart' property from 'HTMLInputElement': The input element's type ('number') does not support selection.
Ver siguiente:
https://codereview.chromium.org/100433008/#ps60001
http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#do-not-apply
¿Hay alguna forma de determinar la ubicación del símbolo de intercalación en un campo de entrada de tipo = "número"?
javascript
google-chrome
Steven
fuente
fuente
text
, verificar la posición del cursor y luego volver a cambiar el tipo anumber
?Respuestas:
Solo se permite la selección con texto / búsqueda, URL, teléfono y contraseña . La razón probable por la que la selección se ha deshabilitado para las entradas de número de tipo es que en algunos dispositivos, o en algunas circunstancias (por ejemplo, cuando la entrada se presenta como un corto
list
), puede que no haya un signo de intercalación. La única solución que encontré fue cambiar el tipo de entrada a texto (con el patrón apropiado para restringir la entrada). Todavía estoy buscando una manera de hacerlo sin cambiar el tipo de entrada y publicaré una actualización cuando encuentre algo.fuente
<input type="number"/>
campo como un campo de texto que establece el teclado en pantalla predeterminado (si está disponible) en el teclado numérico, pero aún representa el campo como un campo de "entrada de texto". Cualquier intento existente / futuro de agregar una calculadora o una función similar de manipulación de valores para el campo ahora se vuelve inútil a menos que fuercemos el campo a volver al texto y arruinemos la experiencia del usuario.Encontré una solución alternativa simple (probada en Chrome) para
setSelectionRange()
. Simplemente puede cambiartype
atext
antes de usarsetSelectionRange()
y luego volver a cambiarlo anumber
.Aquí hay un ejemplo simple con jquery que colocará el signo de intercalación en la posición 4 en la entrada del número cada vez que haga clic en la entrada (agregue más de 5 números en la entrada para ver el comportamiento)
plunker
fuente
email
entradas (que es como terminé en esta página preguntándome por quésetSelectionRange()
funcionó en IE11 (!) Y no en Chrome).input.type = 'text'
, Chrome quita el foco de la entrada y el cursor desaparece para queinput.selectionStart
etc. devuelva nulo.Actualmente, los únicos elementos que permiten la selección de texto de forma segura son:
<input type="text|search|password|tel|url">
como se describe en:whatwg: atributo selectionStart .
También puede leer la documentación de la interfaz HTMLInputElement para ver más de cerca los elementos de entrada.
Para superar este "problema" de forma segura, lo mejor por ahora es lidiar con
<input type="text">
y aplicar una máscara / restricción que acepte solo números. Hay algunos complementos que satisfacen el requisito:Puede ver una demostración en vivo de uno de los complementos anteriores aquí:
Si desea usarlo de manera segura
selectionStart
, puede verificar los elementos que lo admiten (ver atributos de tipo de entrada )Implementación
// Fix: failed to read the 'selectionStart' property from 'HTMLInputElement' // The @fn parameter provides a callback to execute additional code var _fixSelection = (function() { var _SELECTABLE_TYPES = /text|password|search|tel|url/; return function fixSelection (dom, fn) { var validType = _SELECTABLE_TYPES.test(dom.type), selection = { start: validType ? dom.selectionStart : 0, end: validType ? dom.selectionEnd : 0 }; if (validType && fn instanceof Function) fn(dom); return selection; }; }()); // Gets the current position of the cursor in the @dom element function getCaretPosition (dom) { var selection, sel; if ('selectionStart' in dom) { return _fixSelection(dom).start; } else { // IE below version 9 selection = document.selection; if (selection) { sel = selection.createRange(); sel.moveStart('character', -dom.value.length); return sel.text.length; } } return -1; }
Uso
// If the DOM element does not support `selectionStart`, // the returned object sets its properties to -1. var box = document.getElementById("price"), pos = getCaretPosition(box); console.log("position: ", pos);
El ejemplo anterior se puede encontrar aquí: jsu.fnGetCaretPosition ()
fuente
Esto nos estaba sucediendo mientras usábamos el complemento numérico de jQuery, versión 1.3.x, por lo que al ajustar el
selectionStart
yselectionEnd
con untry...catch{}
pudimos suprimir el error.Fuente: https://github.com/joaquingatica/jQuery-Plugins/commit/a53f82044759d29ff30bac698b09e3202b456545
fuente
Como solución temporal, el
type="tel"
tipo de entrada proporciona una funcionalidad muy similar a latype="number"
de Chrome y no tiene esta limitación (como señaló Patrice).fuente
Hay una forma en que puede lograr esto en Chrome (y tal vez en otros navegadores, pero Chrome es el gran infractor aquí). Use
window.getSelection()
para recuperar el objeto de selección de la entrada actual y luego pruebe extender la selección hacia atrás (o hacia adelante) y vea si eltoString()
valor de la selección cambia. Si no es así, el cursor está al final de la entrada y puede pasar a la siguiente entrada. Si es así, debe invertir la operación para deshacer la selección.s = window.getSelection(); len = s.toString().length; s.modify('extend', 'backward', 'character'); if (len < s.toString().length) { // It's not at the beginning of the input, restore previous selection s.modify('extend', 'forward', 'character'); } else { // It's at the end, you can move to the previous input }
Tengo esta idea de esta SO respuesta: https://stackoverflow.com/a/24247942
fuente
¿No podemos simplemente revertir la verificación del elemento para incluir los elementos que son compatibles, como este:
if (deviceIsIOS && targetElement.setSelectionRange && ( targetElement.type === 'text' || targetElement.type === 'search' || targetElement.type === 'password' || targetElement.type === 'url' || targetElement.type === 'tel' ) ) {
en lugar de esto:
if (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time' && targetElement.type !== 'month' ) {
fuente
Si bien el problema con los eventos en desuso para este tipo de campo de formulario puede seguir siendo relevante, por lo que puedo ver, este tipo de campo se puede escuchar con el evento "cambiar", como de costumbre.
Llegué a este artículo aquí mientras buscaba una respuesta al problema de eventos para este tipo de campo, pero mientras lo probaba, descubrí que simplemente puedo confiar en el evento de "cambio" mencionado.
fuente
Recibí este error en un sitio web de angularjs.
Había creado un atributo de datos personalizado en una entrada y también estaba usando ng-blur (con $ event).
Cuando se llamó a mi devolución de llamada, estaba tratando de acceder al valor de 'id de datos' como:
var id = $event.target.attributes["data-id"]
Y debería haber sido así:
var id = $event.target.attributes["data-id"].value
No parece haber mucho acerca de este error en ninguna parte, así que lo dejo aquí.
fuente
Sé que esta respuesta llega demasiado tarde, pero aquí hay un complemento que implementa selectionStart para todo tipo de elementos, para la mayoría de los navegadores (antiguos y nuevos):
https://github.com/adelriosantiago/caret
Lo actualicé para tratar el
type="number"
problema usando la respuesta de @ncohen.fuente
Resuelve
Failed to read the 'selectionStart' property from 'HTMLInputElement': The input element's type ('number') does not support selection.
como sigue:var checkFocus = false; var originalValue = ""; $(document).ready(function() { $("input").focus(function() { var that = this; if ($('#' + $(this).context.id).attr("type") == "text") { setTimeout(function() { if (that.selectionStart != null || that.selectionEnd != null) { that.selectionStart = that.selectionEnd = 10000; } }, 0); } else if ($('#' + $(this).context.id).attr("type") == "number") { if (checkFocus) { moveCursorToEnd($('#' + $(this).context.id), $(this).context.id); checkValue($('#' + $(this).context.id)) checkFocus = false; } else { $('#' + $(this).context.id).blur(); } } }); }); function FocusTextBox(id) { checkFocus = true; document.getElementById(id).focus(); } function checkValue(input) { if ($(input).val() == originalValue || $(input).val() == "") { $(input).val(originalValue) } } function moveCursorToEnd(input, id) { originalValue = input.val(); input.val(''); document.getElementById(id).focus(); return originalValue; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> <button onclick="FocusTextBox('textid')"> <input id="textid" type="number" value="1234" > </button>
fuente
Tenga cuidado con los falsos positivos en esto en Angular si usa el modo de prueba del dispositivo de Chrome.
Entonces, esto es claramente Chrome y no un iPhone real; sin embargo, el error aún se genera porque
_platform.IOS
devuelve verdadero y luegosetSelectionRange
falla.Esto es Angular, pero pueden existir problemas similares en otros marcos / entornos.
fuente