From ea1858cde227efccfdcb9d9754198a553d9f1211 Mon Sep 17 00:00:00 2001 From: Andreas Svensson Date: Mon, 21 Jul 2014 14:50:40 +0200 Subject: [PATCH] Cond IE8 --- src/browser/eventPlugins/ChangeEventPlugin.js | 8 ++- .../eventPlugins/EnterLeaveEventPlugin.js | 10 ++- .../syntheticEvents/SyntheticMouseEvent.js | 25 ++++---- .../syntheticEvents/SyntheticUIEvent.js | 9 +-- .../syntheticEvents/SyntheticWheelEvent.js | 10 ++- src/browser/ui/ReactInputSelection.js | 44 +++++++------ src/browser/ui/dom/CSSPropertyOperations.js | 4 +- src/browser/ui/dom/DOMChildrenOperations.js | 29 ++++----- src/browser/ui/dom/setInnerHTML.js | 63 +++++++++---------- src/vendor/core/ExecutionEnvironment.js | 4 +- src/vendor/core/dom/focusNode.js | 9 ++- 11 files changed, 112 insertions(+), 103 deletions(-) diff --git a/src/browser/eventPlugins/ChangeEventPlugin.js b/src/browser/eventPlugins/ChangeEventPlugin.js index 499a88280283..118edb5f1147 100644 --- a/src/browser/eventPlugins/ChangeEventPlugin.js +++ b/src/browser/eventPlugins/ChangeEventPlugin.js @@ -18,6 +18,8 @@ "use strict"; +var ExecutionEnvironment = require('ExecutionEnvironment'); + var EventConstants = require('EventConstants'); var EventPluginHub = require('EventPluginHub'); var EventPropagators = require('EventPropagators'); @@ -340,10 +342,10 @@ var ChangeEventPlugin = { var getTargetIDFunc, handleEventFunc; if (shouldUseChangeEvent(topLevelTarget)) { - if (doesChangeEventBubble) { - getTargetIDFunc = getTargetIDForChangeEvent; - } else { + if (ExecutionEnvironment.isIE8) { handleEventFunc = handleEventsForChangeEventIE8; + } else { + getTargetIDFunc = getTargetIDForChangeEvent; } } else if (isTextInputElement(topLevelTarget)) { if (isInputEventSupported) { diff --git a/src/browser/eventPlugins/EnterLeaveEventPlugin.js b/src/browser/eventPlugins/EnterLeaveEventPlugin.js index 6dbfaa439956..bcf2d8b3c0b8 100644 --- a/src/browser/eventPlugins/EnterLeaveEventPlugin.js +++ b/src/browser/eventPlugins/EnterLeaveEventPlugin.js @@ -19,6 +19,8 @@ "use strict"; +var ExecutionEnvironment = require('ExecutionEnvironment'); + var EventConstants = require('EventConstants'); var EventPropagators = require('EventPropagators'); var SyntheticMouseEvent = require('SyntheticMouseEvent'); @@ -87,12 +89,8 @@ var EnterLeaveEventPlugin = { win = topLevelTarget; } else { // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8. - var doc = topLevelTarget.ownerDocument; - if (doc) { - win = doc.defaultView || doc.parentWindow; - } else { - win = window; - } + var doc = topLevelTarget.ownerDocument || document; + win = ExecutionEnvironment.isIE8 ? doc.parentWindow : doc.defaultView; } var from, to; diff --git a/src/browser/syntheticEvents/SyntheticMouseEvent.js b/src/browser/syntheticEvents/SyntheticMouseEvent.js index 912eca26f7c4..788400ca88d9 100644 --- a/src/browser/syntheticEvents/SyntheticMouseEvent.js +++ b/src/browser/syntheticEvents/SyntheticMouseEvent.js @@ -19,6 +19,7 @@ "use strict"; +var ExecutionEnvironment = require('ExecutionEnvironment'); var SyntheticUIEvent = require('SyntheticUIEvent'); var ViewportMetrics = require('ViewportMetrics'); @@ -42,15 +43,16 @@ var MouseEventInterface = { // Webkit, Firefox, IE9+ // which: 1 2 3 // button: 0 1 2 (standard) - var button = event.button; - if ('which' in event) { - return button; - } + // IE<9 // which: undefined // button: 0 0 0 // button: 1 4 2 (onmouseup) - return button === 2 ? 2 : button === 4 ? 1 : 0; + + // IE8: uses non-standard button values + return ExecutionEnvironment.isIE8 ? + (button === 2 ? 2 : button === 4 ? 1 : 0) : + event.button; }, buttons: null, relatedTarget: function(event) { @@ -61,15 +63,16 @@ var MouseEventInterface = { ); }, // "Proprietary" Interface. + // IE8: does not support pageX/Y pageX: function(event) { - return 'pageX' in event ? - event.pageX : - event.clientX + ViewportMetrics.currentScrollLeft; + return ExecutionEnvironment.isIE8 ? + event.clientX + ViewportMetrics.currentScrollLeft : + event.pageX; }, pageY: function(event) { - return 'pageY' in event ? - event.pageY : - event.clientY + ViewportMetrics.currentScrollTop; + return ExecutionEnvironment.isIE8 ? + event.clientY + ViewportMetrics.currentScrollTop : + event.pageY; } }; diff --git a/src/browser/syntheticEvents/SyntheticUIEvent.js b/src/browser/syntheticEvents/SyntheticUIEvent.js index 02537f3af3b0..17e71f58ad27 100644 --- a/src/browser/syntheticEvents/SyntheticUIEvent.js +++ b/src/browser/syntheticEvents/SyntheticUIEvent.js @@ -19,6 +19,7 @@ "use strict"; +var ExecutionEnvironment = require('ExecutionEnvironment'); var SyntheticEvent = require('SyntheticEvent'); var getEventTarget = require('getEventTarget'); @@ -39,13 +40,9 @@ var UIEventInterface = { return target; } - var doc = target.ownerDocument; // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8. - if (doc) { - return doc.defaultView || doc.parentWindow; - } else { - return window; - } + var doc = target.ownerDocument || document; + win = ExecutionEnvironment.isIE8 ? doc.parentWindow : doc.defaultView; }, detail: function(event) { return event.detail || 0; diff --git a/src/browser/syntheticEvents/SyntheticWheelEvent.js b/src/browser/syntheticEvents/SyntheticWheelEvent.js index 8fb92fd34aab..3a4bcfe54357 100644 --- a/src/browser/syntheticEvents/SyntheticWheelEvent.js +++ b/src/browser/syntheticEvents/SyntheticWheelEvent.js @@ -19,6 +19,7 @@ "use strict"; +var ExecutionEnvironment = require('ExecutionEnvironment'); var SyntheticMouseEvent = require('SyntheticMouseEvent'); /** @@ -34,12 +35,15 @@ var WheelEventInterface = { ); }, deltaY: function(event) { + if (ExecutionEnvironment.isIE8) { + // Fallback to `wheelDelta` for IE<9 and normalize (down is positive). + return -event.wheelDelta; + } + return ( 'deltaY' in event ? event.deltaY : // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive). - 'wheelDeltaY' in event ? -event.wheelDeltaY : - // Fallback to `wheelDelta` for IE<9 and normalize (down is positive). - 'wheelDelta' in event ? -event.wheelDelta : 0 + 'wheelDeltaY' in event ? -event.wheelDeltaY : 0 ); }, deltaZ: null, diff --git a/src/browser/ui/ReactInputSelection.js b/src/browser/ui/ReactInputSelection.js index 5a8b4f8196ed..4b9e7575b30c 100644 --- a/src/browser/ui/ReactInputSelection.js +++ b/src/browser/ui/ReactInputSelection.js @@ -18,6 +18,8 @@ "use strict"; +var ExecutionEnvironment = require('ExecutionEnvironment'); + var ReactDOMSelection = require('ReactDOMSelection'); var containsNode = require('containsNode'); @@ -85,23 +87,25 @@ var ReactInputSelection = { getSelection: function(input) { var selection; - if ('selectionStart' in input) { + if (ExecutionEnvironment.isIE8) { + if (document.selection && input.nodeName === 'INPUT') { + // IE8 input. + var range = document.selection.createRange(); + // There can only be one selection per document in IE, so it must + // be in our element. + if (range.parentElement() === input) { + selection = { + start: -range.moveStart('character', -input.value.length), + end: -range.moveEnd('character', -input.value.length) + }; + } + } + } else if ('selectionStart' in input) { // Modern browser with input or textarea. selection = { start: input.selectionStart, end: input.selectionEnd }; - } else if (document.selection && input.nodeName === 'INPUT') { - // IE8 input. - var range = document.selection.createRange(); - // There can only be one selection per document in IE, so it must - // be in our element. - if (range.parentElement() === input) { - selection = { - start: -range.moveStart('character', -input.value.length), - end: -range.moveEnd('character', -input.value.length) - }; - } } else { // Content editable or old IE textarea. selection = ReactDOMSelection.getOffsets(input); @@ -123,15 +127,17 @@ var ReactInputSelection = { end = start; } - if ('selectionStart' in input) { + if (ExecutionEnvironment.isIE8) { + if (document.selection && input.nodeName === 'INPUT') { + var range = input.createTextRange(); + range.collapse(true); + range.moveStart('character', start); + range.moveEnd('character', end - start); + range.select(); + } + } else if ('selectionStart' in input) { input.selectionStart = start; input.selectionEnd = Math.min(end, input.value.length); - } else if (document.selection && input.nodeName === 'INPUT') { - var range = input.createTextRange(); - range.collapse(true); - range.moveStart('character', start); - range.moveEnd('character', end - start); - range.select(); } else { ReactDOMSelection.setOffsets(input, offsets); } diff --git a/src/browser/ui/dom/CSSPropertyOperations.js b/src/browser/ui/dom/CSSPropertyOperations.js index 8bb292ee7e46..e40a672b9c9c 100644 --- a/src/browser/ui/dom/CSSPropertyOperations.js +++ b/src/browser/ui/dom/CSSPropertyOperations.js @@ -19,6 +19,8 @@ "use strict"; +var ExecutionEnvironment = require('ExecutionEnvironment'); + var CSSProperty = require('CSSProperty'); var dangerousStyleValue = require('dangerousStyleValue'); @@ -79,7 +81,7 @@ var CSSPropertyOperations = { style[styleName] = styleValue; } else { var expansion = CSSProperty.shorthandPropertyExpansions[styleName]; - if (expansion) { + if (ExecutionEnvironment.isIE8 && expansion) { // Shorthand property that IE8 won't like unsetting, so unset each // component to placate it for (var individualStyleName in expansion) { diff --git a/src/browser/ui/dom/DOMChildrenOperations.js b/src/browser/ui/dom/DOMChildrenOperations.js index 0c53caf2c968..6ddcd52d71b5 100644 --- a/src/browser/ui/dom/DOMChildrenOperations.js +++ b/src/browser/ui/dom/DOMChildrenOperations.js @@ -52,24 +52,17 @@ function insertChildAt(parentNode, childNode, index) { ); } -var updateTextContent; -if (textContentAccessor === 'textContent') { - /** - * Sets the text content of `node` to `text`. - * - * @param {DOMElement} node Node to change - * @param {string} text New text content - */ - updateTextContent = function(node, text) { - node.textContent = text; - }; -} else { - /** - * Sets the text content of `node` to `text`. - * - * @param {DOMElement} node Node to change - * @param {string} text New text content - */ +/** + * Sets the text content of `node` to `text`. + * + * @param {DOMElement} node Node to change + * @param {string} text New text content + */ +var updateTextContent = function(node, text) { + node.textContent = text; +}; + +if (ExecutionEnvironment.isIE8) { updateTextContent = function(node, text) { // In order to preserve newlines correctly, we can't use .innerText to set // the contents (see #1080), so we empty the element then append a text node diff --git a/src/browser/ui/dom/setInnerHTML.js b/src/browser/ui/dom/setInnerHTML.js index a81caa437590..55e624e61d5e 100644 --- a/src/browser/ui/dom/setInnerHTML.js +++ b/src/browser/ui/dom/setInnerHTML.js @@ -32,46 +32,41 @@ var setInnerHTML = function(node, html) { node.innerHTML = html; }; -if (ExecutionEnvironment.canUseDOM) { +if (ExecutionEnvironment.isIE8) { // IE8: When updating a just created node with innerHTML only leading // whitespace is removed. When updating an existing node with innerHTML // whitespace in root TextNodes is also collapsed. // @see quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html - // Feature detection; only IE8 is known to behave improperly like this. - var testElement = document.createElement('div'); - testElement.innerHTML = ' '; - if (testElement.innerHTML === '') { - setInnerHTML = function(node, html) { - // Magic theory: IE8 supposedly differentiates between added and updated - // nodes when processing innerHTML, innerHTML on updated nodes suffers - // from worse whitespace behavior. Re-adding a node like this triggers - // the initial and more favorable whitespace behavior. - // TODO: What to do on a detached node? - if (node.parentNode) { - node.parentNode.replaceChild(node, node); - } + setInnerHTML = function(node, html) { + // Magic theory: IE8 supposedly differentiates between added and updated + // nodes when processing innerHTML, innerHTML on updated nodes suffers + // from worse whitespace behavior. Re-adding a node like this triggers + // the initial and more favorable whitespace behavior. + // TODO: What to do on a detached node? + if (node.parentNode) { + node.parentNode.replaceChild(node, node); + } - // We also implement a workaround for non-visible tags disappearing into - // thin air on IE8, this only happens if there is no visible text - // in-front of the non-visible tags. Piggyback on the whitespace fix - // and simply check if any non-visible tags appear in the source. - if (html.match(/^[ \r\n\t\f]/) || - html[0] === '<' && ( - html.indexOf('