Skip to content

ReactJS support for IE6/IE7 (reimplemented) #2169

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 106 additions & 7 deletions src/browser/eventPlugins/ChangeEventPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ var activeElement = null;
var activeElementID = null;
var activeElementValue = null;
var activeElementValueProp = null;
var activeElementChangeEventTime = null;
var activeElementMouseEventTime = null;
var activeElementKeyEventTime = null;

/**
* SECTION: handle `change` event
Expand Down Expand Up @@ -177,12 +180,46 @@ function startWatchingForValueChange(target, targetID) {
activeElement = target;
activeElementID = targetID;
activeElementValue = target.value;
activeElementValueProp = Object.getOwnPropertyDescriptor(
target.constructor.prototype,
'value'
);

Object.defineProperty(activeElement, 'value', newValueProp);
if (typeof target['constructor'] !== 'undefined') {
activeElementValueProp = Object.getOwnPropertyDescriptor(
target.constructor.prototype,
'value'
);
Object.defineProperty(activeElement, 'value', newValueProp);
} else {
// IE6/IE7 shim
// possible cases:
// 1. keyboard key press (keydown, keypress, CHANGE, keyup)
// 2. keyboard backspace (keydown, CHANGE, keyup)
// 3. keyboard delete (keydown, CHANGE, keyup)
// 4. select text and press key on keyboard (keydown, keypress,
// CHANGE[w/o selected text], CHANGE[with new char], keyup)
// 5. keyboard ctrl+x (keydown, cut, CHANGE, keyup)
// 6. keyboard ctrl+v (keydown, paste, CHANGE, keyup)
// 7. mouse paste (contextmenu, paste, CHANGE)
// 8. mouse cut (contextmenu, cut, CHANGE)
// 9. mouse delete all (mousedown, mouseup, CHANGE)
// 10. keyboard ctrl+z (keydown, CHANGE, select, keyup)
// 11. keyboard ctrl+y (keydown, CHANGE, select, keyup)
// 12. mouse context menu undo (contextmenu, CHANGE)
// 13. mouse context menu redo (contextmenu, CHANGE)
// 14. mouse context menu delete (contextmenu, CHANGE)
//
// for keyboard:
// change -> save timestamp (only if value chage)
// keyup -> fire dispatch and timediff < 500
// for mouse:
// contextmenu, paste, cut, mouseup -> save timestamp
// change -> fire dispatch (only if value chaged and timediff < 500)
// activeElement.attachEvent('onkeyup', handleKeyUp);
activeElement.attachEvent('onkeyup', handleKeyUp);
activeElement.attachEvent('onkeydown', handleKeydown);
activeElement.attachEvent('oncut', handleMouseInput);
activeElement.attachEvent('onpaste', handleMouseInput);
activeElement.attachEvent('oncontextmenu', handleMouseInput);
activeElement.attachEvent('onmouseup', handleMouseInput);
}
activeElement.attachEvent('onpropertychange', handlePropertyChange);
}

Expand All @@ -196,15 +233,50 @@ function stopWatchingForValueChange() {
}

// delete restores the original property definition
delete activeElement.value;
try {
delete activeElement.value;
} catch(err) {}
activeElement.detachEvent('onpropertychange', handlePropertyChange);

// IE6/IE7 shim
if (typeof activeElement['constructor'] === 'undefined') {
activeElement.detachEvent('onkeyup', handleKeyUp);
activeElement.detachEvent('onkeydown', handleKeydown);
activeElement.detachEvent('oncut', handleMouseInput);
activeElement.detachEvent('onpaste', handleMouseInput);
activeElement.detachEvent('oncontextmenu', handleMouseInput);
activeElement.detachEvent('onmouseup', handleMouseInput);
activeElementChangeEventTime = null;
activeElementMouseEventTime = null;
activeElementKeyEventTime = null;
}

activeElement = null;
activeElementID = null;
activeElementValue = null;
activeElementValueProp = null;
}

/**
* IE6/IE7 shim: save keydown event time to distinguish from cut&paste generated
* by mouse
*/
function handleKeydown(nativeEvent) {
activeElementKeyEventTime = new Date();
}

/**
* IE6/IE7 shim: save timestamp of mouse generated cut&paste events
*/
function handleMouseInput(nativeEvent) {
activeElementMouseEventTime = null;
if (!activeElementKeyEventTime ||
(new Date() - activeElementKeyEventTime) > 500) {
activeElementMouseEventTime = new Date();
}
activeElementKeyEventTime = null;
}

/**
* (For old IE.) Handles a propertychange event, sending a `change` event if
* the value of the active element has changed.
Expand All @@ -219,7 +291,34 @@ function handlePropertyChange(nativeEvent) {
}
activeElementValue = value;

manualDispatchChangeEvent(nativeEvent);
if (typeof activeElement['constructor'] !== 'undefined') {
manualDispatchChangeEvent(nativeEvent);
} else {
// IE6/IE7 shim
if (activeElementMouseEventTime) {
// for mouse event dispatch
var timediff = new Date() - activeElementMouseEventTime;
activeElementMouseEventTime = null;
if (timediff < 500) {
manualDispatchChangeEvent(nativeEvent);
return;
}
}
// for keyboard events save timestamp
activeElementChangeEventTime = new Date();
}
}

/**
* IE6/IE7 shim: dispatch user event by keyup
*/
function handleKeyUp(nativeEvent) {
if (!activeElementChangeEventTime) return;
var timediff = new Date() - activeElementChangeEventTime;
activeElementChangeEventTime = null;
if (timediff < 500) {
manualDispatchChangeEvent(nativeEvent);
}
}

/**
Expand Down
6 changes: 5 additions & 1 deletion src/browser/ui/dom/Danger.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,14 @@ var Danger = {
emptyFunction // Do nothing special with <script> tags.
);

// IE6/IE7 fix: hasAttribute isn't available
// using getAttributeNode instead
for (i = 0; i < renderNodes.length; ++i) {
var renderNode = renderNodes[i];
if (renderNode.hasAttribute &&
renderNode.hasAttribute(RESULT_INDEX_ATTR)) {
renderNode.hasAttribute(RESULT_INDEX_ATTR) ||
renderNode.getAttributeNode &&
renderNode.getAttributeNode(RESULT_INDEX_ATTR) !== null) {

resultIndex = +renderNode.getAttribute(RESULT_INDEX_ATTR);
renderNode.removeAttribute(RESULT_INDEX_ATTR);
Expand Down
3 changes: 2 additions & 1 deletion src/browser/ui/dom/setInnerHTML.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,9 @@ if (ExecutionEnvironment.canUseDOM) {
// 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.
// IE6/IE7 fix: charAt(0) instead of [0]
if (WHITESPACE_TEST.test(html) ||
html[0] === '<' && NONVISIBLE_TEST.test(html)) {
html.charAt(0) === '<' && NONVISIBLE_TEST.test(html)) {
// Recover leading whitespace by temporarily prepending any character.
// \uFEFF has the potential advantage of being zero-width/invisible.
node.innerHTML = '\uFEFF' + html;
Expand Down