From 41f734b10c5692530800bf57289929674baa6a7c Mon Sep 17 00:00:00 2001 From: "luke.whyte" Date: Wed, 29 Apr 2015 19:11:29 -0700 Subject: [PATCH 1/2] fix .selectionStart error --- src/key.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/key.js b/src/key.js index 8c63c923..851becdb 100644 --- a/src/key.js +++ b/src/key.js @@ -5,12 +5,21 @@ require('./browsers'); var h = syn.helpers, + selectionStartAvailable = function (el) { + // checking for selectionStart might throw error + try { + return el.selectionStart !== undefined; + } catch (e) { + return false; + } + }, + // gets the selection of an input or textarea getSelection = function (el) { var real, r, start; // use selectionStart if we can - if (el.selectionStart !== undefined) { + if (selectionStartAvailable(el)) { // this is for opera, so we don't have to focus to type how we think we would if (document.activeElement && document.activeElement !== el && el.selectionStart === el.selectionEnd && el.selectionStart === 0) { @@ -291,7 +300,7 @@ h.extend(syn, { // selects text on an element selectText: function (el, start, end) { - if (el.setSelectionRange) { + if (el.setSelectionRange && selectionStartAvailable(el)) { if (!end) { syn.__tryFocus(el); el.setSelectionRange(start, start); From b5804dd5beb65e593aa6ea93893857a426b4b0ee Mon Sep 17 00:00:00 2001 From: "luke.whyte" Date: Mon, 4 May 2015 10:59:23 -0700 Subject: [PATCH 2/2] Added filtering of 'typeable' inputs to syn.typeable --- src/key.js | 29 +++++++++++++++++++---------- src/typeable.js | 9 +++++++-- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/key.js b/src/key.js index 851becdb..1f49af5c 100644 --- a/src/key.js +++ b/src/key.js @@ -5,21 +5,29 @@ require('./browsers'); var h = syn.helpers, - selectionStartAvailable = function (el) { - // checking for selectionStart might throw error - try { - return el.selectionStart !== undefined; - } catch (e) { - return false; + inputSupportsSelectionStart = {}, + + supportsSelectionStart = function (el) { + // checking selection attrs will trigger errors on all inputs but text, url, search, tel & password. + // Ultimately, this creates an issue specifically w/ email and number inputs + if (!inputSupportsSelectionStart[el.type]) { // try to avoid having to run the try/catch repeatedly + try { + return inputSupportsSelectionStart[el.type] = el.selectionStart !== undefined; + } catch (e) { + return inputSupportsSelectionStart[el.type] = false; + } + } else { + return inputSupportsSelectionStart[el.type]; } }, // gets the selection of an input or textarea getSelection = function (el) { - var real, r, start; + var real, r, start, + isInput = el.nodeName.toLowerCase() === 'input'; // use selectionStart if we can - if (selectionStartAvailable(el)) { + if (isInput ? supportsSelectionStart(el) : el.selectionStart !== undefined) { // this is for opera, so we don't have to focus to type how we think we would if (document.activeElement && document.activeElement !== el && el.selectionStart === el.selectionEnd && el.selectionStart === 0) { @@ -36,7 +44,7 @@ var h = syn.helpers, //check if we aren't focused try { //try 2 different methods that work differently (IE breaks depending on type) - if (el.nodeName.toLowerCase() === 'input') { + if (isInput) { real = h.getWindow(el) .document.selection.createRange(); r = el.createTextRange(); @@ -76,6 +84,7 @@ var h = syn.helpers, }; } } catch (e) { + // the elements most likely to get caught here are input[type=number] & input[type=email] var prop = formElExp.test(el.nodeName) ? "value" : "textContent"; return { @@ -300,7 +309,7 @@ h.extend(syn, { // selects text on an element selectText: function (el, start, end) { - if (el.setSelectionRange && selectionStartAvailable(el)) { + if (el.setSelectionRange && supportsSelectionStart(el)) { if (!end) { syn.__tryFocus(el); el.setSelectionRange(start, start); diff --git a/src/typeable.js b/src/typeable.js index 261e31b3..fef2f8d7 100644 --- a/src/typeable.js +++ b/src/typeable.js @@ -54,9 +54,14 @@ syn.typeable.test = function (el) { var type = syn.typeable; // Inputs and textareas -var typeableExp = /input|textarea/i; +var typeableExp = /input|textarea/i, + selectableInputs = ['textarea', 'email', 'number', 'password', 'search', 'tel', 'text', 'url'], + isSelectable = function (type) { + return __indexOf.call(selectableInputs, type) !== -1; + }; + type(function (el) { - return typeableExp.test(el.nodeName); + return typeableExp.test(el.nodeName) && isSelectable(el.type); }); // Content editable