From 41626cdd7a52cb3595153e54f3f8c0c332373bb7 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Tue, 17 Feb 2015 23:10:49 +0000 Subject: Guard against input elements which don't support selectionStart/End These elements throw an error on access, meaning that we can't do an existence check. --- lib/dom_utils.coffee | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'lib/dom_utils.coffee') diff --git a/lib/dom_utils.coffee b/lib/dom_utils.coffee index 2ae9412e..83fb045c 100644 --- a/lib/dom_utils.coffee +++ b/lib/dom_utils.coffee @@ -167,7 +167,8 @@ DomUtils = node = node.parentNode false - # True if element contains the active selection range. + # True if element contains the active selection range, or if the element does not support its selection + # being accessed. isSelected: (element) -> if element.isContentEditable node = document.getSelection()?.anchorNode @@ -175,7 +176,13 @@ DomUtils = else # Note. This makes the wrong decision if the user has placed the caret at the start of element. We # cannot distinguish that case from the user having made no selection. - element.selectionStart? and element.selectionEnd? and element.selectionEnd != 0 + try + element.selectionEnd != 0 + catch + # This input element doesn't support selectionStart/selectionEnd. + # NOTE(mrmr1993): We choose true here because it does the right thing everywhere in the code. I am + # not certain that this is necessarily what we should do. + true simulateSelect: (element) -> # If element is already active, then we don't move the selection. However, we also won't get a new focus -- cgit v1.2.3 From 90f906b626d370a82f5143f84bf1384060386e46 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Tue, 17 Feb 2015 23:24:06 +0000 Subject: Remove redundant check, make isSelected's behaviour match its contract --- lib/dom_utils.coffee | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'lib/dom_utils.coffee') diff --git a/lib/dom_utils.coffee b/lib/dom_utils.coffee index 83fb045c..fae29e49 100644 --- a/lib/dom_utils.coffee +++ b/lib/dom_utils.coffee @@ -171,13 +171,11 @@ DomUtils = # being accessed. isSelected: (element) -> if element.isContentEditable - node = document.getSelection()?.anchorNode + node = document.getSelection().anchorNode node and @isDOMDescendant element, node else - # Note. This makes the wrong decision if the user has placed the caret at the start of element. We - # cannot distinguish that case from the user having made no selection. try - element.selectionEnd != 0 + element.selectionStart != element.selectionEnd catch # This input element doesn't support selectionStart/selectionEnd. # NOTE(mrmr1993): We choose true here because it does the right thing everywhere in the code. I am -- cgit v1.2.3 From 7a380f3f0db55aefadcf73cf41e942e44e22df79 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Thu, 19 Feb 2015 14:45:47 +0000 Subject: Stop trying to place the cursor at the end of an input on focus --- lib/dom_utils.coffee | 5 ----- 1 file changed, 5 deletions(-) (limited to 'lib/dom_utils.coffee') diff --git a/lib/dom_utils.coffee b/lib/dom_utils.coffee index fae29e49..26e0e736 100644 --- a/lib/dom_utils.coffee +++ b/lib/dom_utils.coffee @@ -190,11 +190,6 @@ DomUtils = handlerStack.bubbleEvent "click", target: element else element.focus() - unless @isSelected element - # When focusing a textbox (without an existing selection), put the selection caret at the end of the - # textbox's contents. For some HTML5 input types (eg. date) we can't position the caret, so we wrap - # this with a try. - try element.setSelectionRange(element.value.length, element.value.length) simulateClick: (element, modifiers) -> modifiers ||= {} -- cgit v1.2.3 From eb7b8bea2ae2a7c4f49960f7d0807c75cb3250b3 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Thu, 19 Feb 2015 14:46:17 +0000 Subject: Make DomUtils.isSelected behave correctly for all editable elements --- lib/dom_utils.coffee | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'lib/dom_utils.coffee') diff --git a/lib/dom_utils.coffee b/lib/dom_utils.coffee index 26e0e736..a68edd6c 100644 --- a/lib/dom_utils.coffee +++ b/lib/dom_utils.coffee @@ -167,20 +167,21 @@ DomUtils = node = node.parentNode false - # True if element contains the active selection range, or if the element does not support its selection - # being accessed. + # True if the current element is editable and contains the active selection range. isSelected: (element) -> if element.isContentEditable node = document.getSelection().anchorNode node and @isDOMDescendant element, node else - try - element.selectionStart != element.selectionEnd - catch - # This input element doesn't support selectionStart/selectionEnd. - # NOTE(mrmr1993): We choose true here because it does the right thing everywhere in the code. I am - # not certain that this is necessarily what we should do. - true + selection = document.getSelection() + if selection.type == "Range" and selection.isCollapsed + # The selection is inside the Shadow DOM of a node. We can check the node it registers as being + # before, since this represents the node whose Shadow DOM it's inside. + containerNode = selection.anchorNode.childNodes[selection.anchorOffset] + + element == containerNode # True if the selection is inside the Shadow DOM of our element. + else + false simulateSelect: (element) -> # If element is already active, then we don't move the selection. However, we also won't get a new focus -- cgit v1.2.3 From 0bda93d8ba36e64d7759d2f4e4f2965a3312425d Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Thu, 19 Feb 2015 17:23:07 +0000 Subject: Only send cursor to end when selection has the cursor at the start This restores behaviour to how it was at commit 7cedc5d2481f61f4b0d1cbf99fbd203bb5c68b54. --- lib/dom_utils.coffee | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'lib/dom_utils.coffee') diff --git a/lib/dom_utils.coffee b/lib/dom_utils.coffee index a68edd6c..3633b285 100644 --- a/lib/dom_utils.coffee +++ b/lib/dom_utils.coffee @@ -191,6 +191,18 @@ DomUtils = handlerStack.bubbleEvent "click", target: element else element.focus() + # If the cursor is at the start of the element's contents, send it to the end. Motivation: + # * the end is a more useful place to focus than the start, + # * we've been moving the cursor to the end for quite some time now, + # * this way preserves the last used position (except when it's at the beginning), so the user can + # 'resume where they left off'. + # NOTE(mrmr1993): Some elements throw an error when we try to access their selection properties, so + # wrap this with a try. + try + if element.selectionStart == 0 and element.selectionEnd == 0 + element.setSelectionRange element.value.length, element.value.length + + simulateClick: (element, modifiers) -> modifiers ||= {} -- cgit v1.2.3 From b959fa5c6b36ba19340f195d822b4b3cca8ccd2d Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Fri, 6 Mar 2015 11:46:26 +0000 Subject: Cosmetic changes (following #1490). Mainly fix the indentation on comments. Also tweak wording a bid. --- lib/dom_utils.coffee | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'lib/dom_utils.coffee') diff --git a/lib/dom_utils.coffee b/lib/dom_utils.coffee index 3633b285..707906b4 100644 --- a/lib/dom_utils.coffee +++ b/lib/dom_utils.coffee @@ -167,18 +167,17 @@ DomUtils = node = node.parentNode false - # True if the current element is editable and contains the active selection range. + # True if element is editable and contains the active selection range. isSelected: (element) -> + selection = document.getSelection() if element.isContentEditable - node = document.getSelection().anchorNode + node = selection.anchorNode node and @isDOMDescendant element, node else - selection = document.getSelection() if selection.type == "Range" and selection.isCollapsed - # The selection is inside the Shadow DOM of a node. We can check the node it registers as being - # before, since this represents the node whose Shadow DOM it's inside. + # The selection is inside the Shadow DOM of a node. We can check the node it registers as being + # before, since this represents the node whose Shadow DOM it's inside. containerNode = selection.anchorNode.childNodes[selection.anchorOffset] - element == containerNode # True if the selection is inside the Shadow DOM of our element. else false @@ -191,13 +190,12 @@ DomUtils = handlerStack.bubbleEvent "click", target: element else element.focus() - # If the cursor is at the start of the element's contents, send it to the end. Motivation: - # * the end is a more useful place to focus than the start, - # * we've been moving the cursor to the end for quite some time now, - # * this way preserves the last used position (except when it's at the beginning), so the user can - # 'resume where they left off'. - # NOTE(mrmr1993): Some elements throw an error when we try to access their selection properties, so - # wrap this with a try. + # If the cursor is at the start of the element's contents, send it to the end. Motivation: + # * the end is a more useful place to focus than the start, + # * this way preserves the last used position (except when it's at the beginning), so the user can + # 'resume where they left off'. + # NOTE(mrmr1993): Some elements throw an error when we try to access their selection properties, so + # wrap this with a try. try if element.selectionStart == 0 and element.selectionEnd == 0 element.setSelectionRange element.value.length, element.value.length -- cgit v1.2.3