Java example source code file (react-with-addons.js)
This example Java source code file (react-with-addons.js) is included in the alvinalexander.com
"Java Source Code
Warehouse" project. The intent of this project is to help you "Learn
Java by Example" TM.
/*
*
* * Copyright 2015 Skymind,Inc.
* *
* * Licensed under the Apache License, Version 2.0 (the "License");
* * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* * limitations under the License.
*
*/
/**
* React (with addons) v0.12.2
*/
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.React=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactWithAddons
*/
/**
* This module exists purely in the open source project, and is meant as a way
* to create a separate standalone build of React. This build has "addons", or
* functionality we've built and think might be useful but doesn't have a good
* place to live inside React core.
*/
"use strict";
var LinkedStateMixin = _dereq_("./LinkedStateMixin");
var React = _dereq_("./React");
var ReactComponentWithPureRenderMixin =
_dereq_("./ReactComponentWithPureRenderMixin");
var ReactCSSTransitionGroup = _dereq_("./ReactCSSTransitionGroup");
var ReactTransitionGroup = _dereq_("./ReactTransitionGroup");
var ReactUpdates = _dereq_("./ReactUpdates");
var cx = _dereq_("./cx");
var cloneWithProps = _dereq_("./cloneWithProps");
var update = _dereq_("./update");
React.addons = {
CSSTransitionGroup: ReactCSSTransitionGroup,
LinkedStateMixin: LinkedStateMixin,
PureRenderMixin: ReactComponentWithPureRenderMixin,
TransitionGroup: ReactTransitionGroup,
batchedUpdates: ReactUpdates.batchedUpdates,
classSet: cx,
cloneWithProps: cloneWithProps,
update: update
};
if ("production" !== "development") {
React.addons.Perf = _dereq_("./ReactDefaultPerf");
React.addons.TestUtils = _dereq_("./ReactTestUtils");
}
module.exports = React;
},{"./LinkedStateMixin":25,"./React":31,"./ReactCSSTransitionGroup":34,"./ReactComponentWithPureRenderMixin":39,"./ReactDefaultPerf":56,"./ReactTestUtils":86,"./ReactTransitionGroup":90,"./ReactUpdates":91,"./cloneWithProps":113,"./cx":118,"./update":159}],2:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule AutoFocusMixin
* @typechecks static-only
*/
"use strict";
var focusNode = _dereq_("./focusNode");
var AutoFocusMixin = {
componentDidMount: function() {
if (this.props.autoFocus) {
focusNode(this.getDOMNode());
}
}
};
module.exports = AutoFocusMixin;
},{"./focusNode":125}],3:[function(_dereq_,module,exports){
/**
* Copyright 2013 Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule BeforeInputEventPlugin
* @typechecks static-only
*/
"use strict";
var EventConstants = _dereq_("./EventConstants");
var EventPropagators = _dereq_("./EventPropagators");
var ExecutionEnvironment = _dereq_("./ExecutionEnvironment");
var SyntheticInputEvent = _dereq_("./SyntheticInputEvent");
var keyOf = _dereq_("./keyOf");
var canUseTextInputEvent = (
ExecutionEnvironment.canUseDOM &&
'TextEvent' in window &&
!('documentMode' in document || isPresto())
);
/**
* Opera <= 12 includes TextEvent in window, but does not fire
* text input events. Rely on keypress instead.
*/
function isPresto() {
var opera = window.opera;
return (
typeof opera === 'object' &&
typeof opera.version === 'function' &&
parseInt(opera.version(), 10) <= 12
);
}
var SPACEBAR_CODE = 32;
var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE);
var topLevelTypes = EventConstants.topLevelTypes;
// Events and their corresponding property names.
var eventTypes = {
beforeInput: {
phasedRegistrationNames: {
bubbled: keyOf({onBeforeInput: null}),
captured: keyOf({onBeforeInputCapture: null})
},
dependencies: [
topLevelTypes.topCompositionEnd,
topLevelTypes.topKeyPress,
topLevelTypes.topTextInput,
topLevelTypes.topPaste
]
}
};
// Track characters inserted via keypress and composition events.
var fallbackChars = null;
// Track whether we've ever handled a keypress on the space key.
var hasSpaceKeypress = false;
/**
* Return whether a native keypress event is assumed to be a command.
* This is required because Firefox fires `keypress` events for key commands
* (cut, copy, select-all, etc.) even though no character is inserted.
*/
function isKeypressCommand(nativeEvent) {
return (
(nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) &&
// ctrlKey && altKey is equivalent to AltGr, and is not a command.
!(nativeEvent.ctrlKey && nativeEvent.altKey)
);
}
/**
* Create an `onBeforeInput` event to match
* http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents.
*
* This event plugin is based on the native `textInput` event
* available in Chrome, Safari, Opera, and IE. This event fires after
* `onKeyPress` and `onCompositionEnd`, but before `onInput`.
*
* `beforeInput` is spec'd but not implemented in any browsers, and
* the `input` event does not provide any useful information about what has
* actually been added, contrary to the spec. Thus, `textInput` is the best
* available event to identify the characters that have actually been inserted
* into the target node.
*/
var BeforeInputEventPlugin = {
eventTypes: eventTypes,
/**
* @param {string} topLevelType Record from `EventConstants`.
* @param {DOMEventTarget} topLevelTarget The listening component root node.
* @param {string} topLevelTargetID ID of `topLevelTarget`.
* @param {object} nativeEvent Native browser event.
* @return {*} An accumulation of synthetic events.
* @see {EventPluginHub.extractEvents}
*/
extractEvents: function(
topLevelType,
topLevelTarget,
topLevelTargetID,
nativeEvent) {
var chars;
if (canUseTextInputEvent) {
switch (topLevelType) {
case topLevelTypes.topKeyPress:
/**
* If native `textInput` events are available, our goal is to make
* use of them. However, there is a special case: the spacebar key.
* In Webkit, preventing default on a spacebar `textInput` event
* cancels character insertion, but it *also* causes the browser
* to fall back to its default spacebar behavior of scrolling the
* page.
*
* Tracking at:
* https://code.google.com/p/chromium/issues/detail?id=355103
*
* To avoid this issue, use the keypress event as if no `textInput`
* event is available.
*/
var which = nativeEvent.which;
if (which !== SPACEBAR_CODE) {
return;
}
hasSpaceKeypress = true;
chars = SPACEBAR_CHAR;
break;
case topLevelTypes.topTextInput:
// Record the characters to be added to the DOM.
chars = nativeEvent.data;
// If it's a spacebar character, assume that we have already handled
// it at the keypress level and bail immediately. Android Chrome
// doesn't give us keycodes, so we need to blacklist it.
if (chars === SPACEBAR_CHAR && hasSpaceKeypress) {
return;
}
// Otherwise, carry on.
break;
default:
// For other native event types, do nothing.
return;
}
} else {
switch (topLevelType) {
case topLevelTypes.topPaste:
// If a paste event occurs after a keypress, throw out the input
// chars. Paste events should not lead to BeforeInput events.
fallbackChars = null;
break;
case topLevelTypes.topKeyPress:
/**
* As of v27, Firefox may fire keypress events even when no character
* will be inserted. A few possibilities:
*
* - `which` is `0`. Arrow keys, Esc key, etc.
*
* - `which` is the pressed key code, but no char is available.
* Ex: 'AltGr + d` in Polish. There is no modified character for
* this key combination and no character is inserted into the
* document, but FF fires the keypress for char code `100` anyway.
* No `input` event will occur.
*
* - `which` is the pressed key code, but a command combination is
* being used. Ex: `Cmd+C`. No character is inserted, and no
* `input` event will occur.
*/
if (nativeEvent.which && !isKeypressCommand(nativeEvent)) {
fallbackChars = String.fromCharCode(nativeEvent.which);
}
break;
case topLevelTypes.topCompositionEnd:
fallbackChars = nativeEvent.data;
break;
}
// If no changes have occurred to the fallback string, no relevant
// event has fired and we're done.
if (fallbackChars === null) {
return;
}
chars = fallbackChars;
}
// If no characters are being inserted, no BeforeInput event should
// be fired.
if (!chars) {
return;
}
var event = SyntheticInputEvent.getPooled(
eventTypes.beforeInput,
topLevelTargetID,
nativeEvent
);
event.data = chars;
fallbackChars = null;
EventPropagators.accumulateTwoPhaseDispatches(event);
return event;
}
};
module.exports = BeforeInputEventPlugin;
},{"./EventConstants":17,"./EventPropagators":22,"./ExecutionEnvironment":23,"./SyntheticInputEvent":101,"./keyOf":147}],4:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule CSSCore
* @typechecks
*/
var invariant = _dereq_("./invariant");
/**
* The CSSCore module specifies the API (and implements most of the methods)
* that should be used when dealing with the display of elements (via their
* CSS classes and visibility on screen. It is an API focused on mutating the
* display and not reading it as no logical state should be encoded in the
* display of elements.
*/
var CSSCore = {
/**
* Adds the class passed in to the element if it doesn't already have it.
*
* @param {DOMElement} element the element to set the class on
* @param {string} className the CSS className
* @return {DOMElement} the element passed in
*/
addClass: function(element, className) {
("production" !== "development" ? invariant(
!/\s/.test(className),
'CSSCore.addClass takes only a single class name. "%s" contains ' +
'multiple classes.', className
) : invariant(!/\s/.test(className)));
if (className) {
if (element.classList) {
element.classList.add(className);
} else if (!CSSCore.hasClass(element, className)) {
element.className = element.className + ' ' + className;
}
}
return element;
},
/**
* Removes the class passed in from the element
*
* @param {DOMElement} element the element to set the class on
* @param {string} className the CSS className
* @return {DOMElement} the element passed in
*/
removeClass: function(element, className) {
("production" !== "development" ? invariant(
!/\s/.test(className),
'CSSCore.removeClass takes only a single class name. "%s" contains ' +
'multiple classes.', className
) : invariant(!/\s/.test(className)));
if (className) {
if (element.classList) {
element.classList.remove(className);
} else if (CSSCore.hasClass(element, className)) {
element.className = element.className
.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)', 'g'), '$1')
.replace(/\s+/g, ' ') // multiple spaces to one
.replace(/^\s*|\s*$/g, ''); // trim the ends
}
}
return element;
},
/**
* Helper to add or remove a class from an element based on a condition.
*
* @param {DOMElement} element the element to set the class on
* @param {string} className the CSS className
* @param {*} bool condition to whether to add or remove the class
* @return {DOMElement} the element passed in
*/
conditionClass: function(element, className, bool) {
return (bool ? CSSCore.addClass : CSSCore.removeClass)(element, className);
},
/**
* Tests whether the element has the class specified.
*
* @param {DOMNode|DOMWindow} element the element to set the class on
* @param {string} className the CSS className
* @return {boolean} true if the element has the class, false if not
*/
hasClass: function(element, className) {
("production" !== "development" ? invariant(
!/\s/.test(className),
'CSS.hasClass takes only a single class name.'
) : invariant(!/\s/.test(className)));
if (element.classList) {
return !!className && element.classList.contains(className);
}
return (' ' + element.className + ' ').indexOf(' ' + className + ' ') > -1;
}
};
module.exports = CSSCore;
},{"./invariant":140}],5:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule CSSProperty
*/
"use strict";
/**
* CSS properties which accept numbers but are not in units of "px".
*/
var isUnitlessNumber = {
columnCount: true,
flex: true,
flexGrow: true,
flexShrink: true,
fontWeight: true,
lineClamp: true,
lineHeight: true,
opacity: true,
order: true,
orphans: true,
widows: true,
zIndex: true,
zoom: true,
// SVG-related properties
fillOpacity: true,
strokeOpacity: true
};
/**
* @param {string} prefix vendor-specific prefix, eg: Webkit
* @param {string} key style name, eg: transitionDuration
* @return {string} style name prefixed with `prefix`, properly camelCased, eg:
* WebkitTransitionDuration
*/
function prefixKey(prefix, key) {
return prefix + key.charAt(0).toUpperCase() + key.substring(1);
}
/**
* Support style names that may come passed in prefixed by adding permutations
* of vendor prefixes.
*/
var prefixes = ['Webkit', 'ms', 'Moz', 'O'];
// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an
// infinite loop, because it iterates over the newly added props too.
Object.keys(isUnitlessNumber).forEach(function(prop) {
prefixes.forEach(function(prefix) {
isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];
});
});
/**
* Most style properties can be unset by doing .style[prop] = '' but IE8
* doesn't like doing that with shorthand properties so for the properties that
* IE8 breaks on, which are listed here, we instead unset each of the
* individual properties. See http://bugs.jquery.com/ticket/12385.
* The 4-value 'clock' properties like margin, padding, border-width seem to
* behave without any problems. Curiously, list-style works too without any
* special prodding.
*/
var shorthandPropertyExpansions = {
background: {
backgroundImage: true,
backgroundPosition: true,
backgroundRepeat: true,
backgroundColor: true
},
border: {
borderWidth: true,
borderStyle: true,
borderColor: true
},
borderBottom: {
borderBottomWidth: true,
borderBottomStyle: true,
borderBottomColor: true
},
borderLeft: {
borderLeftWidth: true,
borderLeftStyle: true,
borderLeftColor: true
},
borderRight: {
borderRightWidth: true,
borderRightStyle: true,
borderRightColor: true
},
borderTop: {
borderTopWidth: true,
borderTopStyle: true,
borderTopColor: true
},
font: {
fontStyle: true,
fontVariant: true,
fontWeight: true,
fontSize: true,
lineHeight: true,
fontFamily: true
}
};
var CSSProperty = {
isUnitlessNumber: isUnitlessNumber,
shorthandPropertyExpansions: shorthandPropertyExpansions
};
module.exports = CSSProperty;
},{}],6:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule CSSPropertyOperations
* @typechecks static-only
*/
"use strict";
var CSSProperty = _dereq_("./CSSProperty");
var ExecutionEnvironment = _dereq_("./ExecutionEnvironment");
var camelizeStyleName = _dereq_("./camelizeStyleName");
var dangerousStyleValue = _dereq_("./dangerousStyleValue");
var hyphenateStyleName = _dereq_("./hyphenateStyleName");
var memoizeStringOnly = _dereq_("./memoizeStringOnly");
var warning = _dereq_("./warning");
var processStyleName = memoizeStringOnly(function(styleName) {
return hyphenateStyleName(styleName);
});
var styleFloatAccessor = 'cssFloat';
if (ExecutionEnvironment.canUseDOM) {
// IE8 only supports accessing cssFloat (standard) as styleFloat
if (document.documentElement.style.cssFloat === undefined) {
styleFloatAccessor = 'styleFloat';
}
}
if ("production" !== "development") {
var warnedStyleNames = {};
var warnHyphenatedStyleName = function(name) {
if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
return;
}
warnedStyleNames[name] = true;
("production" !== "development" ? warning(
false,
'Unsupported style property ' + name + '. Did you mean ' +
camelizeStyleName(name) + '?'
) : null);
};
}
/**
* Operations for dealing with CSS properties.
*/
var CSSPropertyOperations = {
/**
* Serializes a mapping of style properties for use as inline styles:
*
* > createMarkupForStyles({width: '200px', height: 0})
* "width:200px;height:0;"
*
* Undefined values are ignored so that declarative programming is easier.
* The result should be HTML-escaped before insertion into the DOM.
*
* @param {object} styles
* @return {?string}
*/
createMarkupForStyles: function(styles) {
var serialized = '';
for (var styleName in styles) {
if (!styles.hasOwnProperty(styleName)) {
continue;
}
if ("production" !== "development") {
if (styleName.indexOf('-') > -1) {
warnHyphenatedStyleName(styleName);
}
}
var styleValue = styles[styleName];
if (styleValue != null) {
serialized += processStyleName(styleName) + ':';
serialized += dangerousStyleValue(styleName, styleValue) + ';';
}
}
return serialized || null;
},
/**
* Sets the value for multiple styles on a node. If a value is specified as
* '' (empty string), the corresponding style property will be unset.
*
* @param {DOMElement} node
* @param {object} styles
*/
setValueForStyles: function(node, styles) {
var style = node.style;
for (var styleName in styles) {
if (!styles.hasOwnProperty(styleName)) {
continue;
}
if ("production" !== "development") {
if (styleName.indexOf('-') > -1) {
warnHyphenatedStyleName(styleName);
}
}
var styleValue = dangerousStyleValue(styleName, styles[styleName]);
if (styleName === 'float') {
styleName = styleFloatAccessor;
}
if (styleValue) {
style[styleName] = styleValue;
} else {
var expansion = CSSProperty.shorthandPropertyExpansions[styleName];
if (expansion) {
// Shorthand property that IE8 won't like unsetting, so unset each
// component to placate it
for (var individualStyleName in expansion) {
style[individualStyleName] = '';
}
} else {
style[styleName] = '';
}
}
}
}
};
module.exports = CSSPropertyOperations;
},{"./CSSProperty":5,"./ExecutionEnvironment":23,"./camelizeStyleName":112,"./dangerousStyleValue":119,"./hyphenateStyleName":138,"./memoizeStringOnly":149,"./warning":160}],7:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule CallbackQueue
*/
"use strict";
var PooledClass = _dereq_("./PooledClass");
var assign = _dereq_("./Object.assign");
var invariant = _dereq_("./invariant");
/**
* A specialized pseudo-event module to help keep track of components waiting to
* be notified when their DOM representations are available for use.
*
* This implements `PooledClass`, so you should never need to instantiate this.
* Instead, use `CallbackQueue.getPooled()`.
*
* @class ReactMountReady
* @implements PooledClass
* @internal
*/
function CallbackQueue() {
this._callbacks = null;
this._contexts = null;
}
assign(CallbackQueue.prototype, {
/**
* Enqueues a callback to be invoked when `notifyAll` is invoked.
*
* @param {function} callback Invoked when `notifyAll` is invoked.
* @param {?object} context Context to call `callback` with.
* @internal
*/
enqueue: function(callback, context) {
this._callbacks = this._callbacks || [];
this._contexts = this._contexts || [];
this._callbacks.push(callback);
this._contexts.push(context);
},
/**
* Invokes all enqueued callbacks and clears the queue. This is invoked after
* the DOM representation of a component has been created or updated.
*
* @internal
*/
notifyAll: function() {
var callbacks = this._callbacks;
var contexts = this._contexts;
if (callbacks) {
("production" !== "development" ? invariant(
callbacks.length === contexts.length,
"Mismatched list of contexts in callback queue"
) : invariant(callbacks.length === contexts.length));
this._callbacks = null;
this._contexts = null;
for (var i = 0, l = callbacks.length; i < l; i++) {
callbacks[i].call(contexts[i]);
}
callbacks.length = 0;
contexts.length = 0;
}
},
/**
* Resets the internal queue.
*
* @internal
*/
reset: function() {
this._callbacks = null;
this._contexts = null;
},
/**
* `PooledClass` looks for this.
*/
destructor: function() {
this.reset();
}
});
PooledClass.addPoolingTo(CallbackQueue);
module.exports = CallbackQueue;
},{"./Object.assign":29,"./PooledClass":30,"./invariant":140}],8:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ChangeEventPlugin
*/
"use strict";
var EventConstants = _dereq_("./EventConstants");
var EventPluginHub = _dereq_("./EventPluginHub");
var EventPropagators = _dereq_("./EventPropagators");
var ExecutionEnvironment = _dereq_("./ExecutionEnvironment");
var ReactUpdates = _dereq_("./ReactUpdates");
var SyntheticEvent = _dereq_("./SyntheticEvent");
var isEventSupported = _dereq_("./isEventSupported");
var isTextInputElement = _dereq_("./isTextInputElement");
var keyOf = _dereq_("./keyOf");
var topLevelTypes = EventConstants.topLevelTypes;
var eventTypes = {
change: {
phasedRegistrationNames: {
bubbled: keyOf({onChange: null}),
captured: keyOf({onChangeCapture: null})
},
dependencies: [
topLevelTypes.topBlur,
topLevelTypes.topChange,
topLevelTypes.topClick,
topLevelTypes.topFocus,
topLevelTypes.topInput,
topLevelTypes.topKeyDown,
topLevelTypes.topKeyUp,
topLevelTypes.topSelectionChange
]
}
};
/**
* For IE shims
*/
var activeElement = null;
var activeElementID = null;
var activeElementValue = null;
var activeElementValueProp = null;
/**
* SECTION: handle `change` event
*/
function shouldUseChangeEvent(elem) {
return (
elem.nodeName === 'SELECT' ||
(elem.nodeName === 'INPUT' && elem.type === 'file')
);
}
var doesChangeEventBubble = false;
if (ExecutionEnvironment.canUseDOM) {
// See `handleChange` comment below
doesChangeEventBubble = isEventSupported('change') && (
!('documentMode' in document) || document.documentMode > 8
);
}
function manualDispatchChangeEvent(nativeEvent) {
var event = SyntheticEvent.getPooled(
eventTypes.change,
activeElementID,
nativeEvent
);
EventPropagators.accumulateTwoPhaseDispatches(event);
// If change and propertychange bubbled, we'd just bind to it like all the
// other events and have it go through ReactBrowserEventEmitter. Since it
// doesn't, we manually listen for the events and so we have to enqueue and
// process the abstract event manually.
//
// Batching is necessary here in order to ensure that all event handlers run
// before the next rerender (including event handlers attached to ancestor
// elements instead of directly on the input). Without this, controlled
// components don't work properly in conjunction with event bubbling because
// the component is rerendered and the value reverted before all the event
// handlers can run. See https://github.com/facebook/react/issues/708.
ReactUpdates.batchedUpdates(runEventInBatch, event);
}
function runEventInBatch(event) {
EventPluginHub.enqueueEvents(event);
EventPluginHub.processEventQueue();
}
function startWatchingForChangeEventIE8(target, targetID) {
activeElement = target;
activeElementID = targetID;
activeElement.attachEvent('onchange', manualDispatchChangeEvent);
}
function stopWatchingForChangeEventIE8() {
if (!activeElement) {
return;
}
activeElement.detachEvent('onchange', manualDispatchChangeEvent);
activeElement = null;
activeElementID = null;
}
function getTargetIDForChangeEvent(
topLevelType,
topLevelTarget,
topLevelTargetID) {
if (topLevelType === topLevelTypes.topChange) {
return topLevelTargetID;
}
}
function handleEventsForChangeEventIE8(
topLevelType,
topLevelTarget,
topLevelTargetID) {
if (topLevelType === topLevelTypes.topFocus) {
// stopWatching() should be a noop here but we call it just in case we
// missed a blur event somehow.
stopWatchingForChangeEventIE8();
startWatchingForChangeEventIE8(topLevelTarget, topLevelTargetID);
} else if (topLevelType === topLevelTypes.topBlur) {
stopWatchingForChangeEventIE8();
}
}
/**
* SECTION: handle `input` event
*/
var isInputEventSupported = false;
if (ExecutionEnvironment.canUseDOM) {
// IE9 claims to support the input event but fails to trigger it when
// deleting text, so we ignore its input events
isInputEventSupported = isEventSupported('input') && (
!('documentMode' in document) || document.documentMode > 9
);
}
/**
* (For old IE.) Replacement getter/setter for the `value` property that gets
* set on the active element.
*/
var newValueProp = {
get: function() {
return activeElementValueProp.get.call(this);
},
set: function(val) {
// Cast to a string so we can do equality checks.
activeElementValue = '' + val;
activeElementValueProp.set.call(this, val);
}
};
/**
* (For old IE.) Starts tracking propertychange events on the passed-in element
* and override the value property so that we can distinguish user events from
* value changes in JS.
*/
function startWatchingForValueChange(target, targetID) {
activeElement = target;
activeElementID = targetID;
activeElementValue = target.value;
activeElementValueProp = Object.getOwnPropertyDescriptor(
target.constructor.prototype,
'value'
);
Object.defineProperty(activeElement, 'value', newValueProp);
activeElement.attachEvent('onpropertychange', handlePropertyChange);
}
/**
* (For old IE.) Removes the event listeners from the currently-tracked element,
* if any exists.
*/
function stopWatchingForValueChange() {
if (!activeElement) {
return;
}
// delete restores the original property definition
delete activeElement.value;
activeElement.detachEvent('onpropertychange', handlePropertyChange);
activeElement = null;
activeElementID = null;
activeElementValue = null;
activeElementValueProp = null;
}
/**
* (For old IE.) Handles a propertychange event, sending a `change` event if
* the value of the active element has changed.
*/
function handlePropertyChange(nativeEvent) {
if (nativeEvent.propertyName !== 'value') {
return;
}
var value = nativeEvent.srcElement.value;
if (value === activeElementValue) {
return;
}
activeElementValue = value;
manualDispatchChangeEvent(nativeEvent);
}
/**
* If a `change` event should be fired, returns the target's ID.
*/
function getTargetIDForInputEvent(
topLevelType,
topLevelTarget,
topLevelTargetID) {
if (topLevelType === topLevelTypes.topInput) {
// In modern browsers (i.e., not IE8 or IE9), the input event is exactly
// what we want so fall through here and trigger an abstract event
return topLevelTargetID;
}
}
// For IE8 and IE9.
function handleEventsForInputEventIE(
topLevelType,
topLevelTarget,
topLevelTargetID) {
if (topLevelType === topLevelTypes.topFocus) {
// In IE8, we can capture almost all .value changes by adding a
// propertychange handler and looking for events with propertyName
// equal to 'value'
// In IE9, propertychange fires for most input events but is buggy and
// doesn't fire when text is deleted, but conveniently, selectionchange
// appears to fire in all of the remaining cases so we catch those and
// forward the event if the value has changed
// In either case, we don't want to call the event handler if the value
// is changed from JS so we redefine a setter for `.value` that updates
// our activeElementValue variable, allowing us to ignore those changes
//
// stopWatching() should be a noop here but we call it just in case we
// missed a blur event somehow.
stopWatchingForValueChange();
startWatchingForValueChange(topLevelTarget, topLevelTargetID);
} else if (topLevelType === topLevelTypes.topBlur) {
stopWatchingForValueChange();
}
}
// For IE8 and IE9.
function getTargetIDForInputEventIE(
topLevelType,
topLevelTarget,
topLevelTargetID) {
if (topLevelType === topLevelTypes.topSelectionChange ||
topLevelType === topLevelTypes.topKeyUp ||
topLevelType === topLevelTypes.topKeyDown) {
// On the selectionchange event, the target is just document which isn't
// helpful for us so just check activeElement instead.
//
// 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire
// propertychange on the first input event after setting `value` from a
// script and fires only keydown, keypress, keyup. Catching keyup usually
// gets it and catching keydown lets us fire an event for the first
// keystroke if user does a key repeat (it'll be a little delayed: right
// before the second keystroke). Other input methods (e.g., paste) seem to
// fire selectionchange normally.
if (activeElement && activeElement.value !== activeElementValue) {
activeElementValue = activeElement.value;
return activeElementID;
}
}
}
/**
* SECTION: handle `click` event
*/
function shouldUseClickEvent(elem) {
// Use the `click` event to detect changes to checkbox and radio inputs.
// This approach works across all browsers, whereas `change` does not fire
// until `blur` in IE8.
return (
elem.nodeName === 'INPUT' &&
(elem.type === 'checkbox' || elem.type === 'radio')
);
}
function getTargetIDForClickEvent(
topLevelType,
topLevelTarget,
topLevelTargetID) {
if (topLevelType === topLevelTypes.topClick) {
return topLevelTargetID;
}
}
/**
* This plugin creates an `onChange` event that normalizes change events
* across form elements. This event fires at a time when it's possible to
* change the element's value without seeing a flicker.
*
* Supported elements are:
* - input (see `isTextInputElement`)
* - textarea
* - select
*/
var ChangeEventPlugin = {
eventTypes: eventTypes,
/**
* @param {string} topLevelType Record from `EventConstants`.
* @param {DOMEventTarget} topLevelTarget The listening component root node.
* @param {string} topLevelTargetID ID of `topLevelTarget`.
* @param {object} nativeEvent Native browser event.
* @return {*} An accumulation of synthetic events.
* @see {EventPluginHub.extractEvents}
*/
extractEvents: function(
topLevelType,
topLevelTarget,
topLevelTargetID,
nativeEvent) {
var getTargetIDFunc, handleEventFunc;
if (shouldUseChangeEvent(topLevelTarget)) {
if (doesChangeEventBubble) {
getTargetIDFunc = getTargetIDForChangeEvent;
} else {
handleEventFunc = handleEventsForChangeEventIE8;
}
} else if (isTextInputElement(topLevelTarget)) {
if (isInputEventSupported) {
getTargetIDFunc = getTargetIDForInputEvent;
} else {
getTargetIDFunc = getTargetIDForInputEventIE;
handleEventFunc = handleEventsForInputEventIE;
}
} else if (shouldUseClickEvent(topLevelTarget)) {
getTargetIDFunc = getTargetIDForClickEvent;
}
if (getTargetIDFunc) {
var targetID = getTargetIDFunc(
topLevelType,
topLevelTarget,
topLevelTargetID
);
if (targetID) {
var event = SyntheticEvent.getPooled(
eventTypes.change,
targetID,
nativeEvent
);
EventPropagators.accumulateTwoPhaseDispatches(event);
return event;
}
}
if (handleEventFunc) {
handleEventFunc(
topLevelType,
topLevelTarget,
topLevelTargetID
);
}
}
};
module.exports = ChangeEventPlugin;
},{"./EventConstants":17,"./EventPluginHub":19,"./EventPropagators":22,"./ExecutionEnvironment":23,"./ReactUpdates":91,"./SyntheticEvent":99,"./isEventSupported":141,"./isTextInputElement":143,"./keyOf":147}],9:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ClientReactRootIndex
* @typechecks
*/
"use strict";
var nextReactRootIndex = 0;
var ClientReactRootIndex = {
createReactRootIndex: function() {
return nextReactRootIndex++;
}
};
module.exports = ClientReactRootIndex;
},{}],10:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule CompositionEventPlugin
* @typechecks static-only
*/
"use strict";
var EventConstants = _dereq_("./EventConstants");
var EventPropagators = _dereq_("./EventPropagators");
var ExecutionEnvironment = _dereq_("./ExecutionEnvironment");
var ReactInputSelection = _dereq_("./ReactInputSelection");
var SyntheticCompositionEvent = _dereq_("./SyntheticCompositionEvent");
var getTextContentAccessor = _dereq_("./getTextContentAccessor");
var keyOf = _dereq_("./keyOf");
var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space
var START_KEYCODE = 229;
var useCompositionEvent = (
ExecutionEnvironment.canUseDOM &&
'CompositionEvent' in window
);
// In IE9+, we have access to composition events, but the data supplied
// by the native compositionend event may be incorrect. In Korean, for example,
// the compositionend event contains only one character regardless of
// how many characters have been composed since compositionstart.
// We therefore use the fallback data while still using the native
// events as triggers.
var useFallbackData = (
!useCompositionEvent ||
(
'documentMode' in document &&
document.documentMode > 8 &&
document.documentMode <= 11
)
);
var topLevelTypes = EventConstants.topLevelTypes;
var currentComposition = null;
// Events and their corresponding property names.
var eventTypes = {
compositionEnd: {
phasedRegistrationNames: {
bubbled: keyOf({onCompositionEnd: null}),
captured: keyOf({onCompositionEndCapture: null})
},
dependencies: [
topLevelTypes.topBlur,
topLevelTypes.topCompositionEnd,
topLevelTypes.topKeyDown,
topLevelTypes.topKeyPress,
topLevelTypes.topKeyUp,
topLevelTypes.topMouseDown
]
},
compositionStart: {
phasedRegistrationNames: {
bubbled: keyOf({onCompositionStart: null}),
captured: keyOf({onCompositionStartCapture: null})
},
dependencies: [
topLevelTypes.topBlur,
topLevelTypes.topCompositionStart,
topLevelTypes.topKeyDown,
topLevelTypes.topKeyPress,
topLevelTypes.topKeyUp,
topLevelTypes.topMouseDown
]
},
compositionUpdate: {
phasedRegistrationNames: {
bubbled: keyOf({onCompositionUpdate: null}),
captured: keyOf({onCompositionUpdateCapture: null})
},
dependencies: [
topLevelTypes.topBlur,
topLevelTypes.topCompositionUpdate,
topLevelTypes.topKeyDown,
topLevelTypes.topKeyPress,
topLevelTypes.topKeyUp,
topLevelTypes.topMouseDown
]
}
};
/**
* Translate native top level events into event types.
*
* @param {string} topLevelType
* @return {object}
*/
function getCompositionEventType(topLevelType) {
switch (topLevelType) {
case topLevelTypes.topCompositionStart:
return eventTypes.compositionStart;
case topLevelTypes.topCompositionEnd:
return eventTypes.compositionEnd;
case topLevelTypes.topCompositionUpdate:
return eventTypes.compositionUpdate;
}
}
/**
* Does our fallback best-guess model think this event signifies that
* composition has begun?
*
* @param {string} topLevelType
* @param {object} nativeEvent
* @return {boolean}
*/
function isFallbackStart(topLevelType, nativeEvent) {
return (
topLevelType === topLevelTypes.topKeyDown &&
nativeEvent.keyCode === START_KEYCODE
);
}
/**
* Does our fallback mode think that this event is the end of composition?
*
* @param {string} topLevelType
* @param {object} nativeEvent
* @return {boolean}
*/
function isFallbackEnd(topLevelType, nativeEvent) {
switch (topLevelType) {
case topLevelTypes.topKeyUp:
// Command keys insert or clear IME input.
return (END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1);
case topLevelTypes.topKeyDown:
// Expect IME keyCode on each keydown. If we get any other
// code we must have exited earlier.
return (nativeEvent.keyCode !== START_KEYCODE);
case topLevelTypes.topKeyPress:
case topLevelTypes.topMouseDown:
case topLevelTypes.topBlur:
// Events are not possible without cancelling IME.
return true;
default:
return false;
}
}
/**
* Helper class stores information about selection and document state
* so we can figure out what changed at a later date.
*
* @param {DOMEventTarget} root
*/
function FallbackCompositionState(root) {
this.root = root;
this.startSelection = ReactInputSelection.getSelection(root);
this.startValue = this.getText();
}
/**
* Get current text of input.
*
* @return {string}
*/
FallbackCompositionState.prototype.getText = function() {
return this.root.value || this.root[getTextContentAccessor()];
};
/**
* Text that has changed since the start of composition.
*
* @return {string}
*/
FallbackCompositionState.prototype.getData = function() {
var endValue = this.getText();
var prefixLength = this.startSelection.start;
var suffixLength = this.startValue.length - this.startSelection.end;
return endValue.substr(
prefixLength,
endValue.length - suffixLength - prefixLength
);
};
/**
* This plugin creates `onCompositionStart`, `onCompositionUpdate` and
* `onCompositionEnd` events on inputs, textareas and contentEditable
* nodes.
*/
var CompositionEventPlugin = {
eventTypes: eventTypes,
/**
* @param {string} topLevelType Record from `EventConstants`.
* @param {DOMEventTarget} topLevelTarget The listening component root node.
* @param {string} topLevelTargetID ID of `topLevelTarget`.
* @param {object} nativeEvent Native browser event.
* @return {*} An accumulation of synthetic events.
* @see {EventPluginHub.extractEvents}
*/
extractEvents: function(
topLevelType,
topLevelTarget,
topLevelTargetID,
nativeEvent) {
var eventType;
var data;
if (useCompositionEvent) {
eventType = getCompositionEventType(topLevelType);
} else if (!currentComposition) {
if (isFallbackStart(topLevelType, nativeEvent)) {
eventType = eventTypes.compositionStart;
}
} else if (isFallbackEnd(topLevelType, nativeEvent)) {
eventType = eventTypes.compositionEnd;
}
if (useFallbackData) {
// The current composition is stored statically and must not be
// overwritten while composition continues.
if (!currentComposition && eventType === eventTypes.compositionStart) {
currentComposition = new FallbackCompositionState(topLevelTarget);
} else if (eventType === eventTypes.compositionEnd) {
if (currentComposition) {
data = currentComposition.getData();
currentComposition = null;
}
}
}
if (eventType) {
var event = SyntheticCompositionEvent.getPooled(
eventType,
topLevelTargetID,
nativeEvent
);
if (data) {
// Inject data generated from fallback path into the synthetic event.
// This matches the property of native CompositionEventInterface.
event.data = data;
}
EventPropagators.accumulateTwoPhaseDispatches(event);
return event;
}
}
};
module.exports = CompositionEventPlugin;
},{"./EventConstants":17,"./EventPropagators":22,"./ExecutionEnvironment":23,"./ReactInputSelection":65,"./SyntheticCompositionEvent":97,"./getTextContentAccessor":135,"./keyOf":147}],11:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule DOMChildrenOperations
* @typechecks static-only
*/
"use strict";
var Danger = _dereq_("./Danger");
var ReactMultiChildUpdateTypes = _dereq_("./ReactMultiChildUpdateTypes");
var getTextContentAccessor = _dereq_("./getTextContentAccessor");
var invariant = _dereq_("./invariant");
/**
* The DOM property to use when setting text content.
*
* @type {string}
* @private
*/
var textContentAccessor = getTextContentAccessor();
/**
* Inserts `childNode` as a child of `parentNode` at the `index`.
*
* @param {DOMElement} parentNode Parent node in which to insert.
* @param {DOMElement} childNode Child node to insert.
* @param {number} index Index at which to insert the child.
* @internal
*/
function insertChildAt(parentNode, childNode, index) {
// By exploiting arrays returning `undefined` for an undefined index, we can
// rely exclusively on `insertBefore(node, null)` instead of also using
// `appendChild(node)`. However, using `undefined` is not allowed by all
// browsers so we must replace it with `null`.
parentNode.insertBefore(
childNode,
parentNode.childNodes[index] || null
);
}
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
*/
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
while (node.firstChild) {
node.removeChild(node.firstChild);
}
if (text) {
var doc = node.ownerDocument || document;
node.appendChild(doc.createTextNode(text));
}
};
}
/**
* Operations for updating with DOM children.
*/
var DOMChildrenOperations = {
dangerouslyReplaceNodeWithMarkup: Danger.dangerouslyReplaceNodeWithMarkup,
updateTextContent: updateTextContent,
/**
* Updates a component's children by processing a series of updates. The
* update configurations are each expected to have a `parentNode` property.
*
* @param {array<object>} updates List of update configurations.
* @param {array<string>} markupList List of markup strings.
* @internal
*/
processUpdates: function(updates, markupList) {
var update;
// Mapping from parent IDs to initial child orderings.
var initialChildren = null;
// List of children that will be moved or removed.
var updatedChildren = null;
for (var i = 0; update = updates[i]; i++) {
if (update.type === ReactMultiChildUpdateTypes.MOVE_EXISTING ||
update.type === ReactMultiChildUpdateTypes.REMOVE_NODE) {
var updatedIndex = update.fromIndex;
var updatedChild = update.parentNode.childNodes[updatedIndex];
var parentID = update.parentID;
("production" !== "development" ? invariant(
updatedChild,
'processUpdates(): Unable to find child %s of element. This ' +
'probably means the DOM was unexpectedly mutated (e.g., by the ' +
'browser), usually due to forgetting a <tbody> when using tables, ' +
'nesting tags like <form>,
;
* }
* });
*
* Note: This only checks shallow equality for props and state. If these contain
* complex data structures this mixin may have false-negatives for deeper
* differences. Only mixin to components which have simple props and state, or
* use `forceUpdate()` when you know deep data structures have changed.
*/
var ReactComponentWithPureRenderMixin = {
shouldComponentUpdate: function(nextProps, nextState) {
return !shallowEqual(this.props, nextProps) ||
!shallowEqual(this.state, nextState);
}
};
module.exports = ReactComponentWithPureRenderMixin;
},{"./shallowEqual":155}],40:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactCompositeComponent
*/
"use strict";
var ReactComponent = _dereq_("./ReactComponent");
var ReactContext = _dereq_("./ReactContext");
var ReactCurrentOwner = _dereq_("./ReactCurrentOwner");
var ReactElement = _dereq_("./ReactElement");
var ReactElementValidator = _dereq_("./ReactElementValidator");
var ReactEmptyComponent = _dereq_("./ReactEmptyComponent");
var ReactErrorUtils = _dereq_("./ReactErrorUtils");
var ReactLegacyElement = _dereq_("./ReactLegacyElement");
var ReactOwner = _dereq_("./ReactOwner");
var ReactPerf = _dereq_("./ReactPerf");
var ReactPropTransferer = _dereq_("./ReactPropTransferer");
var ReactPropTypeLocations = _dereq_("./ReactPropTypeLocations");
var ReactPropTypeLocationNames = _dereq_("./ReactPropTypeLocationNames");
var ReactUpdates = _dereq_("./ReactUpdates");
var assign = _dereq_("./Object.assign");
var instantiateReactComponent = _dereq_("./instantiateReactComponent");
var invariant = _dereq_("./invariant");
var keyMirror = _dereq_("./keyMirror");
var keyOf = _dereq_("./keyOf");
var monitorCodeUse = _dereq_("./monitorCodeUse");
var mapObject = _dereq_("./mapObject");
var shouldUpdateReactComponent = _dereq_("./shouldUpdateReactComponent");
var warning = _dereq_("./warning");
var MIXINS_KEY = keyOf({mixins: null});
/**
* Policies that describe methods in `ReactCompositeComponentInterface`.
*/
var SpecPolicy = keyMirror({
/**
* These methods may be defined only once by the class specification or mixin.
*/
DEFINE_ONCE: null,
/**
* These methods may be defined by both the class specification and mixins.
* Subsequent definitions will be chained. These methods must return void.
*/
DEFINE_MANY: null,
/**
* These methods are overriding the base ReactCompositeComponent class.
*/
OVERRIDE_BASE: null,
/**
* These methods are similar to DEFINE_MANY, except we assume they return
* objects. We try to merge the keys of the return values of all the mixed in
* functions. If there is a key conflict we throw.
*/
DEFINE_MANY_MERGED: null
});
var injectedMixins = [];
/**
* Composite components are higher-level components that compose other composite
* or native components.
*
* To create a new type of `ReactCompositeComponent`, pass a specification of
* your new class to `React.createClass`. The only requirement of your class
* specification is that you implement a `render` method.
*
* var MyComponent = React.createClass({
* render: function() {
* return <div>Hello World;
* }
* });
*
* The class specification supports a specific protocol of methods that have
* special meaning (e.g. `render`). See `ReactCompositeComponentInterface` for
* more the comprehensive protocol. Any other properties and methods in the
* class specification will available on the prototype.
*
* @interface ReactCompositeComponentInterface
* @internal
*/
var ReactCompositeComponentInterface = {
/**
* An array of Mixin objects to include when defining your component.
*
* @type {array}
* @optional
*/
mixins: SpecPolicy.DEFINE_MANY,
/**
* An object containing properties and methods that should be defined on
* the component's constructor instead of its prototype (static methods).
*
* @type {object}
* @optional
*/
statics: SpecPolicy.DEFINE_MANY,
/**
* Definition of prop types for this component.
*
* @type {object}
* @optional
*/
propTypes: SpecPolicy.DEFINE_MANY,
/**
* Definition of context types for this component.
*
* @type {object}
* @optional
*/
contextTypes: SpecPolicy.DEFINE_MANY,
/**
* Definition of context types this component sets for its children.
*
* @type {object}
* @optional
*/
childContextTypes: SpecPolicy.DEFINE_MANY,
// ==== Definition methods ====
/**
* Invoked when the component is mounted. Values in the mapping will be set on
* `this.props` if that prop is not specified (i.e. using an `in` check).
*
* This method is invoked before `getInitialState` and therefore cannot rely
* on `this.state` or use `this.setState`.
*
* @return {object}
* @optional
*/
getDefaultProps: SpecPolicy.DEFINE_MANY_MERGED,
/**
* Invoked once before the component is mounted. The return value will be used
* as the initial value of `this.state`.
*
* getInitialState: function() {
* return {
* isOn: false,
* fooBaz: new BazFoo()
* }
* }
*
* @return {object}
* @optional
*/
getInitialState: SpecPolicy.DEFINE_MANY_MERGED,
/**
* @return {object}
* @optional
*/
getChildContext: SpecPolicy.DEFINE_MANY_MERGED,
/**
* Uses props from `this.props` and state from `this.state` to render the
* structure of the component.
*
* No guarantees are made about when or how often this method is invoked, so
* it must not have side effects.
*
* render: function() {
* var name = this.props.name;
* return <div>Hello, {name}!;
* }
*
* @return {ReactComponent}
* @nosideeffects
* @required
*/
render: SpecPolicy.DEFINE_ONCE,
// ==== Delegate methods ====
/**
* Invoked when the component is initially created and about to be mounted.
* This may have side effects, but any external subscriptions or data created
* by this method must be cleaned up in `componentWillUnmount`.
*
* @optional
*/
componentWillMount: SpecPolicy.DEFINE_MANY,
/**
* Invoked when the component has been mounted and has a DOM representation.
* However, there is no guarantee that the DOM node is in the document.
*
* Use this as an opportunity to operate on the DOM when the component has
* been mounted (initialized and rendered) for the first time.
*
* @param {DOMElement} rootNode DOM element representing the component.
* @optional
*/
componentDidMount: SpecPolicy.DEFINE_MANY,
/**
* Invoked before the component receives new props.
*
* Use this as an opportunity to react to a prop transition by updating the
* state using `this.setState`. Current props are accessed via `this.props`.
*
* componentWillReceiveProps: function(nextProps, nextContext) {
* this.setState({
* likesIncreasing: nextProps.likeCount > this.props.likeCount
* });
* }
*
* NOTE: There is no equivalent `componentWillReceiveState`. An incoming prop
* transition may cause a state change, but the opposite is not true. If you
* need it, you are probably looking for `componentWillUpdate`.
*
* @param {object} nextProps
* @optional
*/
componentWillReceiveProps: SpecPolicy.DEFINE_MANY,
/**
* Invoked while deciding if the component should be updated as a result of
* receiving new props, state and/or context.
*
* Use this as an opportunity to `return false` when you're certain that the
* transition to the new props/state/context will not require a component
* update.
*
* shouldComponentUpdate: function(nextProps, nextState, nextContext) {
* return !equal(nextProps, this.props) ||
* !equal(nextState, this.state) ||
* !equal(nextContext, this.context);
* }
*
* @param {object} nextProps
* @param {?object} nextState
* @param {?object} nextContext
* @return {boolean} True if the component should update.
* @optional
*/
shouldComponentUpdate: SpecPolicy.DEFINE_ONCE,
/**
* Invoked when the component is about to update due to a transition from
* `this.props`, `this.state` and `this.context` to `nextProps`, `nextState`
* and `nextContext`.
*
* Use this as an opportunity to perform preparation before an update occurs.
*
* NOTE: You **cannot** use `this.setState()` in this method.
*
* @param {object} nextProps
* @param {?object} nextState
* @param {?object} nextContext
* @param {ReactReconcileTransaction} transaction
* @optional
*/
componentWillUpdate: SpecPolicy.DEFINE_MANY,
/**
* Invoked when the component's DOM representation has been updated.
*
* Use this as an opportunity to operate on the DOM when the component has
* been updated.
*
* @param {object} prevProps
* @param {?object} prevState
* @param {?object} prevContext
* @param {DOMElement} rootNode DOM element representing the component.
* @optional
*/
componentDidUpdate: SpecPolicy.DEFINE_MANY,
/**
* Invoked when the component is about to be removed from its parent and have
* its DOM representation destroyed.
*
* Use this as an opportunity to deallocate any external resources.
*
* NOTE: There is no `componentDidUnmount` since your component will have been
* destroyed by that point.
*
* @optional
*/
componentWillUnmount: SpecPolicy.DEFINE_MANY,
// ==== Advanced methods ====
/**
* Updates the component's currently mounted DOM representation.
*
* By default, this implements React's rendering and reconciliation algorithm.
* Sophisticated clients may wish to override this.
*
* @param {ReactReconcileTransaction} transaction
* @internal
* @overridable
*/
updateComponent: SpecPolicy.OVERRIDE_BASE
};
/**
* Mapping from class specification keys to special processing functions.
*
* Although these are declared like instance properties in the specification
* when defining classes using `React.createClass`, they are actually static
* and are accessible on the constructor instead of the prototype. Despite
* being static, they must be defined outside of the "statics" key under
* which all other static methods are defined.
*/
var RESERVED_SPEC_KEYS = {
displayName: function(Constructor, displayName) {
Constructor.displayName = displayName;
},
mixins: function(Constructor, mixins) {
if (mixins) {
for (var i = 0; i < mixins.length; i++) {
mixSpecIntoComponent(Constructor, mixins[i]);
}
}
},
childContextTypes: function(Constructor, childContextTypes) {
validateTypeDef(
Constructor,
childContextTypes,
ReactPropTypeLocations.childContext
);
Constructor.childContextTypes = assign(
{},
Constructor.childContextTypes,
childContextTypes
);
},
contextTypes: function(Constructor, contextTypes) {
validateTypeDef(
Constructor,
contextTypes,
ReactPropTypeLocations.context
);
Constructor.contextTypes = assign(
{},
Constructor.contextTypes,
contextTypes
);
},
/**
* Special case getDefaultProps which should move into statics but requires
* automatic merging.
*/
getDefaultProps: function(Constructor, getDefaultProps) {
if (Constructor.getDefaultProps) {
Constructor.getDefaultProps = createMergedResultFunction(
Constructor.getDefaultProps,
getDefaultProps
);
} else {
Constructor.getDefaultProps = getDefaultProps;
}
},
propTypes: function(Constructor, propTypes) {
validateTypeDef(
Constructor,
propTypes,
ReactPropTypeLocations.prop
);
Constructor.propTypes = assign(
{},
Constructor.propTypes,
propTypes
);
},
statics: function(Constructor, statics) {
mixStaticSpecIntoComponent(Constructor, statics);
}
};
function getDeclarationErrorAddendum(component) {
var owner = component._owner || null;
if (owner && owner.constructor && owner.constructor.displayName) {
return ' Check the render method of `' + owner.constructor.displayName +
'`.';
}
return '';
}
function validateTypeDef(Constructor, typeDef, location) {
for (var propName in typeDef) {
if (typeDef.hasOwnProperty(propName)) {
("production" !== "development" ? invariant(
typeof typeDef[propName] == 'function',
'%s: %s type `%s` is invalid; it must be a function, usually from ' +
'React.PropTypes.',
Constructor.displayName || 'ReactCompositeComponent',
ReactPropTypeLocationNames[location],
propName
) : invariant(typeof typeDef[propName] == 'function'));
}
}
}
function validateMethodOverride(proto, name) {
var specPolicy = ReactCompositeComponentInterface.hasOwnProperty(name) ?
ReactCompositeComponentInterface[name] :
null;
// Disallow overriding of base class methods unless explicitly allowed.
if (ReactCompositeComponentMixin.hasOwnProperty(name)) {
("production" !== "development" ? invariant(
specPolicy === SpecPolicy.OVERRIDE_BASE,
'ReactCompositeComponentInterface: You are attempting to override ' +
'`%s` from your class specification. Ensure that your method names ' +
'do not overlap with React methods.',
name
) : invariant(specPolicy === SpecPolicy.OVERRIDE_BASE));
}
// Disallow defining methods more than once unless explicitly allowed.
if (proto.hasOwnProperty(name)) {
("production" !== "development" ? invariant(
specPolicy === SpecPolicy.DEFINE_MANY ||
specPolicy === SpecPolicy.DEFINE_MANY_MERGED,
'ReactCompositeComponentInterface: You are attempting to define ' +
'`%s` on your component more than once. This conflict may be due ' +
'to a mixin.',
name
) : invariant(specPolicy === SpecPolicy.DEFINE_MANY ||
specPolicy === SpecPolicy.DEFINE_MANY_MERGED));
}
}
function validateLifeCycleOnReplaceState(instance) {
var compositeLifeCycleState = instance._compositeLifeCycleState;
("production" !== "development" ? invariant(
instance.isMounted() ||
compositeLifeCycleState === CompositeLifeCycle.MOUNTING,
'replaceState(...): Can only update a mounted or mounting component.'
) : invariant(instance.isMounted() ||
compositeLifeCycleState === CompositeLifeCycle.MOUNTING));
("production" !== "development" ? invariant(
ReactCurrentOwner.current == null,
'replaceState(...): Cannot update during an existing state transition ' +
'(such as within `render`). Render methods should be a pure function ' +
'of props and state.'
) : invariant(ReactCurrentOwner.current == null));
("production" !== "development" ? invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING,
'replaceState(...): Cannot update while unmounting component. This ' +
'usually means you called setState() on an unmounted component.'
) : invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING));
}
/**
* Mixin helper which handles policy validation and reserved
* specification keys when building `ReactCompositeComponent` classses.
*/
function mixSpecIntoComponent(Constructor, spec) {
if (!spec) {
return;
}
("production" !== "development" ? invariant(
!ReactLegacyElement.isValidFactory(spec),
'ReactCompositeComponent: You\'re attempting to ' +
'use a component class as a mixin. Instead, just use a regular object.'
) : invariant(!ReactLegacyElement.isValidFactory(spec)));
("production" !== "development" ? invariant(
!ReactElement.isValidElement(spec),
'ReactCompositeComponent: You\'re attempting to ' +
'use a component as a mixin. Instead, just use a regular object.'
) : invariant(!ReactElement.isValidElement(spec)));
var proto = Constructor.prototype;
// By handling mixins before any other properties, we ensure the same
// chaining order is applied to methods with DEFINE_MANY policy, whether
// mixins are listed before or after these methods in the spec.
if (spec.hasOwnProperty(MIXINS_KEY)) {
RESERVED_SPEC_KEYS.mixins(Constructor, spec.mixins);
}
for (var name in spec) {
if (!spec.hasOwnProperty(name)) {
continue;
}
if (name === MIXINS_KEY) {
// We have already handled mixins in a special case above
continue;
}
var property = spec[name];
validateMethodOverride(proto, name);
if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {
RESERVED_SPEC_KEYS[name](Constructor, property);
} else {
// Setup methods on prototype:
// The following member methods should not be automatically bound:
// 1. Expected ReactCompositeComponent methods (in the "interface").
// 2. Overridden methods (that were mixed in).
var isCompositeComponentMethod =
ReactCompositeComponentInterface.hasOwnProperty(name);
var isAlreadyDefined = proto.hasOwnProperty(name);
var markedDontBind = property && property.__reactDontBind;
var isFunction = typeof property === 'function';
var shouldAutoBind =
isFunction &&
!isCompositeComponentMethod &&
!isAlreadyDefined &&
!markedDontBind;
if (shouldAutoBind) {
if (!proto.__reactAutoBindMap) {
proto.__reactAutoBindMap = {};
}
proto.__reactAutoBindMap[name] = property;
proto[name] = property;
} else {
if (isAlreadyDefined) {
var specPolicy = ReactCompositeComponentInterface[name];
// These cases should already be caught by validateMethodOverride
("production" !== "development" ? invariant(
isCompositeComponentMethod && (
specPolicy === SpecPolicy.DEFINE_MANY_MERGED ||
specPolicy === SpecPolicy.DEFINE_MANY
),
'ReactCompositeComponent: Unexpected spec policy %s for key %s ' +
'when mixing in component specs.',
specPolicy,
name
) : invariant(isCompositeComponentMethod && (
specPolicy === SpecPolicy.DEFINE_MANY_MERGED ||
specPolicy === SpecPolicy.DEFINE_MANY
)));
// For methods which are defined more than once, call the existing
// methods before calling the new property, merging if appropriate.
if (specPolicy === SpecPolicy.DEFINE_MANY_MERGED) {
proto[name] = createMergedResultFunction(proto[name], property);
} else if (specPolicy === SpecPolicy.DEFINE_MANY) {
proto[name] = createChainedFunction(proto[name], property);
}
} else {
proto[name] = property;
if ("production" !== "development") {
// Add verbose displayName to the function, which helps when looking
// at profiling tools.
if (typeof property === 'function' && spec.displayName) {
proto[name].displayName = spec.displayName + '_' + name;
}
}
}
}
}
}
}
function mixStaticSpecIntoComponent(Constructor, statics) {
if (!statics) {
return;
}
for (var name in statics) {
var property = statics[name];
if (!statics.hasOwnProperty(name)) {
continue;
}
var isReserved = name in RESERVED_SPEC_KEYS;
("production" !== "development" ? invariant(
!isReserved,
'ReactCompositeComponent: You are attempting to define a reserved ' +
'property, `%s`, that shouldn\'t be on the "statics" key. Define it ' +
'as an instance property instead; it will still be accessible on the ' +
'constructor.',
name
) : invariant(!isReserved));
var isInherited = name in Constructor;
("production" !== "development" ? invariant(
!isInherited,
'ReactCompositeComponent: You are attempting to define ' +
'`%s` on your component more than once. This conflict may be ' +
'due to a mixin.',
name
) : invariant(!isInherited));
Constructor[name] = property;
}
}
/**
* Merge two objects, but throw if both contain the same key.
*
* @param {object} one The first object, which is mutated.
* @param {object} two The second object
* @return {object} one after it has been mutated to contain everything in two.
*/
function mergeObjectsWithNoDuplicateKeys(one, two) {
("production" !== "development" ? invariant(
one && two && typeof one === 'object' && typeof two === 'object',
'mergeObjectsWithNoDuplicateKeys(): Cannot merge non-objects'
) : invariant(one && two && typeof one === 'object' && typeof two === 'object'));
mapObject(two, function(value, key) {
("production" !== "development" ? invariant(
one[key] === undefined,
'mergeObjectsWithNoDuplicateKeys(): ' +
'Tried to merge two objects with the same key: `%s`. This conflict ' +
'may be due to a mixin; in particular, this may be caused by two ' +
'getInitialState() or getDefaultProps() methods returning objects ' +
'with clashing keys.',
key
) : invariant(one[key] === undefined));
one[key] = value;
});
return one;
}
/**
* Creates a function that invokes two functions and merges their return values.
*
* @param {function} one Function to invoke first.
* @param {function} two Function to invoke second.
* @return {function} Function that invokes the two argument functions.
* @private
*/
function createMergedResultFunction(one, two) {
return function mergedResult() {
var a = one.apply(this, arguments);
var b = two.apply(this, arguments);
if (a == null) {
return b;
} else if (b == null) {
return a;
}
return mergeObjectsWithNoDuplicateKeys(a, b);
};
}
/**
* Creates a function that invokes two functions and ignores their return vales.
*
* @param {function} one Function to invoke first.
* @param {function} two Function to invoke second.
* @return {function} Function that invokes the two argument functions.
* @private
*/
function createChainedFunction(one, two) {
return function chainedFunction() {
one.apply(this, arguments);
two.apply(this, arguments);
};
}
/**
* `ReactCompositeComponent` maintains an auxiliary life cycle state in
* `this._compositeLifeCycleState` (which can be null).
*
* This is different from the life cycle state maintained by `ReactComponent` in
* `this._lifeCycleState`. The following diagram shows how the states overlap in
* time. There are times when the CompositeLifeCycle is null - at those times it
* is only meaningful to look at ComponentLifeCycle alone.
*
* Top Row: ReactComponent.ComponentLifeCycle
* Low Row: ReactComponent.CompositeLifeCycle
*
* +-------+---------------------------------+--------+
* | UN | MOUNTED | UN |
* |MOUNTED| | MOUNTED|
* +-------+---------------------------------+--------+
* | ^--------+ +-------+ +--------^ |
* | | | | | | | |
* | 0--|MOUNTING|-0-|RECEIVE|-0-| UN |--->0 |
* | | | |PROPS | |MOUNTING| |
* | | | | | | | |
* | | | | | | | |
* | +--------+ +-------+ +--------+ |
* | | | |
* +-------+---------------------------------+--------+
*/
var CompositeLifeCycle = keyMirror({
/**
* Components in the process of being mounted respond to state changes
* differently.
*/
MOUNTING: null,
/**
* Components in the process of being unmounted are guarded against state
* changes.
*/
UNMOUNTING: null,
/**
* Components that are mounted and receiving new props respond to state
* changes differently.
*/
RECEIVING_PROPS: null
});
/**
* @lends {ReactCompositeComponent.prototype}
*/
var ReactCompositeComponentMixin = {
/**
* Base constructor for all composite component.
*
* @param {ReactElement} element
* @final
* @internal
*/
construct: function(element) {
// Children can be either an array or more than one argument
ReactComponent.Mixin.construct.apply(this, arguments);
ReactOwner.Mixin.construct.apply(this, arguments);
this.state = null;
this._pendingState = null;
// This is the public post-processed context. The real context and pending
// context lives on the element.
this.context = null;
this._compositeLifeCycleState = null;
},
/**
* Checks whether or not this composite component is mounted.
* @return {boolean} True if mounted, false otherwise.
* @protected
* @final
*/
isMounted: function() {
return ReactComponent.Mixin.isMounted.call(this) &&
this._compositeLifeCycleState !== CompositeLifeCycle.MOUNTING;
},
/**
* Initializes the component, renders markup, and registers event listeners.
*
* @param {string} rootID DOM ID of the root node.
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
* @param {number} mountDepth number of components in the owner hierarchy
* @return {?string} Rendered markup to be inserted into the DOM.
* @final
* @internal
*/
mountComponent: ReactPerf.measure(
'ReactCompositeComponent',
'mountComponent',
function(rootID, transaction, mountDepth) {
ReactComponent.Mixin.mountComponent.call(
this,
rootID,
transaction,
mountDepth
);
this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING;
if (this.__reactAutoBindMap) {
this._bindAutoBindMethods();
}
this.context = this._processContext(this._currentElement._context);
this.props = this._processProps(this.props);
this.state = this.getInitialState ? this.getInitialState() : null;
("production" !== "development" ? invariant(
typeof this.state === 'object' && !Array.isArray(this.state),
'%s.getInitialState(): must return an object or null',
this.constructor.displayName || 'ReactCompositeComponent'
) : invariant(typeof this.state === 'object' && !Array.isArray(this.state)));
this._pendingState = null;
this._pendingForceUpdate = false;
if (this.componentWillMount) {
this.componentWillMount();
// When mounting, calls to `setState` by `componentWillMount` will set
// `this._pendingState` without triggering a re-render.
if (this._pendingState) {
this.state = this._pendingState;
this._pendingState = null;
}
}
this._renderedComponent = instantiateReactComponent(
this._renderValidatedComponent(),
this._currentElement.type // The wrapping type
);
// Done with mounting, `setState` will now trigger UI changes.
this._compositeLifeCycleState = null;
var markup = this._renderedComponent.mountComponent(
rootID,
transaction,
mountDepth + 1
);
if (this.componentDidMount) {
transaction.getReactMountReady().enqueue(this.componentDidMount, this);
}
return markup;
}
),
/**
* Releases any resources allocated by `mountComponent`.
*
* @final
* @internal
*/
unmountComponent: function() {
this._compositeLifeCycleState = CompositeLifeCycle.UNMOUNTING;
if (this.componentWillUnmount) {
this.componentWillUnmount();
}
this._compositeLifeCycleState = null;
this._renderedComponent.unmountComponent();
this._renderedComponent = null;
ReactComponent.Mixin.unmountComponent.call(this);
// Some existing components rely on this.props even after they've been
// destroyed (in event handlers).
// TODO: this.props = null;
// TODO: this.state = null;
},
/**
* Sets a subset of the state. Always use this or `replaceState` to mutate
* state. You should treat `this.state` as immutable.
*
* There is no guarantee that `this.state` will be immediately updated, so
* accessing `this.state` after calling this method may return the old value.
*
* There is no guarantee that calls to `setState` will run synchronously,
* as they may eventually be batched together. You can provide an optional
* callback that will be executed when the call to setState is actually
* completed.
*
* @param {object} partialState Next partial state to be merged with state.
* @param {?function} callback Called after state is updated.
* @final
* @protected
*/
setState: function(partialState, callback) {
("production" !== "development" ? invariant(
typeof partialState === 'object' || partialState == null,
'setState(...): takes an object of state variables to update.'
) : invariant(typeof partialState === 'object' || partialState == null));
if ("production" !== "development"){
("production" !== "development" ? warning(
partialState != null,
'setState(...): You passed an undefined or null state object; ' +
'instead, use forceUpdate().'
) : null);
}
// Merge with `_pendingState` if it exists, otherwise with existing state.
this.replaceState(
assign({}, this._pendingState || this.state, partialState),
callback
);
},
/**
* Replaces all of the state. Always use this or `setState` to mutate state.
* You should treat `this.state` as immutable.
*
* There is no guarantee that `this.state` will be immediately updated, so
* accessing `this.state` after calling this method may return the old value.
*
* @param {object} completeState Next state.
* @param {?function} callback Called after state is updated.
* @final
* @protected
*/
replaceState: function(completeState, callback) {
validateLifeCycleOnReplaceState(this);
this._pendingState = completeState;
if (this._compositeLifeCycleState !== CompositeLifeCycle.MOUNTING) {
// If we're in a componentWillMount handler, don't enqueue a rerender
// because ReactUpdates assumes we're in a browser context (which is wrong
// for server rendering) and we're about to do a render anyway.
// TODO: The callback here is ignored when setState is called from
// componentWillMount. Either fix it or disallow doing so completely in
// favor of getInitialState.
ReactUpdates.enqueueUpdate(this, callback);
}
},
/**
* Filters the context object to only contain keys specified in
* `contextTypes`, and asserts that they are valid.
*
* @param {object} context
* @return {?object}
* @private
*/
_processContext: function(context) {
var maskedContext = null;
var contextTypes = this.constructor.contextTypes;
if (contextTypes) {
maskedContext = {};
for (var contextName in contextTypes) {
maskedContext[contextName] = context[contextName];
}
if ("production" !== "development") {
this._checkPropTypes(
contextTypes,
maskedContext,
ReactPropTypeLocations.context
);
}
}
return maskedContext;
},
/**
* @param {object} currentContext
* @return {object}
* @private
*/
_processChildContext: function(currentContext) {
var childContext = this.getChildContext && this.getChildContext();
var displayName = this.constructor.displayName || 'ReactCompositeComponent';
if (childContext) {
("production" !== "development" ? invariant(
typeof this.constructor.childContextTypes === 'object',
'%s.getChildContext(): childContextTypes must be defined in order to ' +
'use getChildContext().',
displayName
) : invariant(typeof this.constructor.childContextTypes === 'object'));
if ("production" !== "development") {
this._checkPropTypes(
this.constructor.childContextTypes,
childContext,
ReactPropTypeLocations.childContext
);
}
for (var name in childContext) {
("production" !== "development" ? invariant(
name in this.constructor.childContextTypes,
'%s.getChildContext(): key "%s" is not defined in childContextTypes.',
displayName,
name
) : invariant(name in this.constructor.childContextTypes));
}
return assign({}, currentContext, childContext);
}
return currentContext;
},
/**
* Processes props by setting default values for unspecified props and
* asserting that the props are valid. Does not mutate its argument; returns
* a new props object with defaults merged in.
*
* @param {object} newProps
* @return {object}
* @private
*/
_processProps: function(newProps) {
if ("production" !== "development") {
var propTypes = this.constructor.propTypes;
if (propTypes) {
this._checkPropTypes(propTypes, newProps, ReactPropTypeLocations.prop);
}
}
return newProps;
},
/**
* Assert that the props are valid
*
* @param {object} propTypes Map of prop name to a ReactPropType
* @param {object} props
* @param {string} location e.g. "prop", "context", "child context"
* @private
*/
_checkPropTypes: function(propTypes, props, location) {
// TODO: Stop validating prop types here and only use the element
// validation.
var componentName = this.constructor.displayName;
for (var propName in propTypes) {
if (propTypes.hasOwnProperty(propName)) {
var error =
propTypes[propName](props, propName, componentName, location);
if (error instanceof Error) {
// We may want to extend this logic for similar errors in
// renderComponent calls, so I'm abstracting it away into
// a function to minimize refactoring in the future
var addendum = getDeclarationErrorAddendum(this);
("production" !== "development" ? warning(false, error.message + addendum) : null);
}
}
}
},
/**
* If any of `_pendingElement`, `_pendingState`, or `_pendingForceUpdate`
* is set, update the component.
*
* @param {ReactReconcileTransaction} transaction
* @internal
*/
performUpdateIfNecessary: function(transaction) {
var compositeLifeCycleState = this._compositeLifeCycleState;
// Do not trigger a state transition if we are in the middle of mounting or
// receiving props because both of those will already be doing this.
if (compositeLifeCycleState === CompositeLifeCycle.MOUNTING ||
compositeLifeCycleState === CompositeLifeCycle.RECEIVING_PROPS) {
return;
}
if (this._pendingElement == null &&
this._pendingState == null &&
!this._pendingForceUpdate) {
return;
}
var nextContext = this.context;
var nextProps = this.props;
var nextElement = this._currentElement;
if (this._pendingElement != null) {
nextElement = this._pendingElement;
nextContext = this._processContext(nextElement._context);
nextProps = this._processProps(nextElement.props);
this._pendingElement = null;
this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS;
if (this.componentWillReceiveProps) {
this.componentWillReceiveProps(nextProps, nextContext);
}
}
this._compositeLifeCycleState = null;
var nextState = this._pendingState || this.state;
this._pendingState = null;
var shouldUpdate =
this._pendingForceUpdate ||
!this.shouldComponentUpdate ||
this.shouldComponentUpdate(nextProps, nextState, nextContext);
if ("production" !== "development") {
if (typeof shouldUpdate === "undefined") {
console.warn(
(this.constructor.displayName || 'ReactCompositeComponent') +
'.shouldComponentUpdate(): Returned undefined instead of a ' +
'boolean value. Make sure to return true or false.'
);
}
}
if (shouldUpdate) {
this._pendingForceUpdate = false;
// Will set `this.props`, `this.state` and `this.context`.
this._performComponentUpdate(
nextElement,
nextProps,
nextState,
nextContext,
transaction
);
} else {
// If it's determined that a component should not update, we still want
// to set props and state.
this._currentElement = nextElement;
this.props = nextProps;
this.state = nextState;
this.context = nextContext;
// Owner cannot change because shouldUpdateReactComponent doesn't allow
// it. TODO: Remove this._owner completely.
this._owner = nextElement._owner;
}
},
/**
* Merges new props and state, notifies delegate methods of update and
* performs update.
*
* @param {ReactElement} nextElement Next element
* @param {object} nextProps Next public object to set as properties.
* @param {?object} nextState Next object to set as state.
* @param {?object} nextContext Next public object to set as context.
* @param {ReactReconcileTransaction} transaction
* @private
*/
_performComponentUpdate: function(
nextElement,
nextProps,
nextState,
nextContext,
transaction
) {
var prevElement = this._currentElement;
var prevProps = this.props;
var prevState = this.state;
var prevContext = this.context;
if (this.componentWillUpdate) {
this.componentWillUpdate(nextProps, nextState, nextContext);
}
this._currentElement = nextElement;
this.props = nextProps;
this.state = nextState;
this.context = nextContext;
// Owner cannot change because shouldUpdateReactComponent doesn't allow
// it. TODO: Remove this._owner completely.
this._owner = nextElement._owner;
this.updateComponent(
transaction,
prevElement
);
if (this.componentDidUpdate) {
transaction.getReactMountReady().enqueue(
this.componentDidUpdate.bind(this, prevProps, prevState, prevContext),
this
);
}
},
receiveComponent: function(nextElement, transaction) {
if (nextElement === this._currentElement &&
nextElement._owner != null) {
// Since elements are immutable after the owner is rendered,
// we can do a cheap identity compare here to determine if this is a
// superfluous reconcile. It's possible for state to be mutable but such
// change should trigger an update of the owner which would recreate
// the element. We explicitly check for the existence of an owner since
// it's possible for a element created outside a composite to be
// deeply mutated and reused.
return;
}
ReactComponent.Mixin.receiveComponent.call(
this,
nextElement,
transaction
);
},
/**
* Updates the component's currently mounted DOM representation.
*
* By default, this implements React's rendering and reconciliation algorithm.
* Sophisticated clients may wish to override this.
*
* @param {ReactReconcileTransaction} transaction
* @param {ReactElement} prevElement
* @internal
* @overridable
*/
updateComponent: ReactPerf.measure(
'ReactCompositeComponent',
'updateComponent',
function(transaction, prevParentElement) {
ReactComponent.Mixin.updateComponent.call(
this,
transaction,
prevParentElement
);
var prevComponentInstance = this._renderedComponent;
var prevElement = prevComponentInstance._currentElement;
var nextElement = this._renderValidatedComponent();
if (shouldUpdateReactComponent(prevElement, nextElement)) {
prevComponentInstance.receiveComponent(nextElement, transaction);
} else {
// These two IDs are actually the same! But nothing should rely on that.
var thisID = this._rootNodeID;
var prevComponentID = prevComponentInstance._rootNodeID;
prevComponentInstance.unmountComponent();
this._renderedComponent = instantiateReactComponent(
nextElement,
this._currentElement.type
);
var nextMarkup = this._renderedComponent.mountComponent(
thisID,
transaction,
this._mountDepth + 1
);
ReactComponent.BackendIDOperations.dangerouslyReplaceNodeWithMarkupByID(
prevComponentID,
nextMarkup
);
}
}
),
/**
* Forces an update. This should only be invoked when it is known with
* certainty that we are **not** in a DOM transaction.
*
* You may want to call this when you know that some deeper aspect of the
* component's state has changed but `setState` was not called.
*
* This will not invoke `shouldUpdateComponent`, but it will invoke
* `componentWillUpdate` and `componentDidUpdate`.
*
* @param {?function} callback Called after update is complete.
* @final
* @protected
*/
forceUpdate: function(callback) {
var compositeLifeCycleState = this._compositeLifeCycleState;
("production" !== "development" ? invariant(
this.isMounted() ||
compositeLifeCycleState === CompositeLifeCycle.MOUNTING,
'forceUpdate(...): Can only force an update on mounted or mounting ' +
'components.'
) : invariant(this.isMounted() ||
compositeLifeCycleState === CompositeLifeCycle.MOUNTING));
("production" !== "development" ? invariant(
compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING &&
ReactCurrentOwner.current == null,
'forceUpdate(...): Cannot force an update while unmounting component ' +
'or within a `render` function.'
) : invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING &&
ReactCurrentOwner.current == null));
this._pendingForceUpdate = true;
ReactUpdates.enqueueUpdate(this, callback);
},
/**
* @private
*/
_renderValidatedComponent: ReactPerf.measure(
'ReactCompositeComponent',
'_renderValidatedComponent',
function() {
var renderedComponent;
var previousContext = ReactContext.current;
ReactContext.current = this._processChildContext(
this._currentElement._context
);
ReactCurrentOwner.current = this;
try {
renderedComponent = this.render();
if (renderedComponent === null || renderedComponent === false) {
renderedComponent = ReactEmptyComponent.getEmptyComponent();
ReactEmptyComponent.registerNullComponentID(this._rootNodeID);
} else {
ReactEmptyComponent.deregisterNullComponentID(this._rootNodeID);
}
} finally {
ReactContext.current = previousContext;
ReactCurrentOwner.current = null;
}
("production" !== "development" ? invariant(
ReactElement.isValidElement(renderedComponent),
'%s.render(): A valid ReactComponent must be returned. You may have ' +
'returned undefined, an array or some other invalid object.',
this.constructor.displayName || 'ReactCompositeComponent'
) : invariant(ReactElement.isValidElement(renderedComponent)));
return renderedComponent;
}
),
/**
* @private
*/
_bindAutoBindMethods: function() {
for (var autoBindKey in this.__reactAutoBindMap) {
if (!this.__reactAutoBindMap.hasOwnProperty(autoBindKey)) {
continue;
}
var method = this.__reactAutoBindMap[autoBindKey];
this[autoBindKey] = this._bindAutoBindMethod(ReactErrorUtils.guard(
method,
this.constructor.displayName + '.' + autoBindKey
));
}
},
/**
* Binds a method to the component.
*
* @param {function} method Method to be bound.
* @private
*/
_bindAutoBindMethod: function(method) {
var component = this;
var boundMethod = method.bind(component);
if ("production" !== "development") {
boundMethod.__reactBoundContext = component;
boundMethod.__reactBoundMethod = method;
boundMethod.__reactBoundArguments = null;
var componentName = component.constructor.displayName;
var _bind = boundMethod.bind;
boundMethod.bind = function(newThis ) {for (var args=[],$__0=1,$__1=arguments.length;$__0<$__1;$__0++) args.push(arguments[$__0]);
// User is trying to bind() an autobound method; we effectively will
// ignore the value of "this" that the user is trying to use, so
// let's warn.
if (newThis !== component && newThis !== null) {
monitorCodeUse('react_bind_warning', { component: componentName });
console.warn(
'bind(): React component methods may only be bound to the ' +
'component instance. See ' + componentName
);
} else if (!args.length) {
monitorCodeUse('react_bind_warning', { component: componentName });
console.warn(
'bind(): You are binding a component method to the component. ' +
'React does this for you automatically in a high-performance ' +
'way, so you can safely remove this call. See ' + componentName
);
return boundMethod;
}
var reboundMethod = _bind.apply(boundMethod, arguments);
reboundMethod.__reactBoundContext = component;
reboundMethod.__reactBoundMethod = method;
reboundMethod.__reactBoundArguments = args;
return reboundMethod;
};
}
return boundMethod;
}
};
var ReactCompositeComponentBase = function() {};
assign(
ReactCompositeComponentBase.prototype,
ReactComponent.Mixin,
ReactOwner.Mixin,
ReactPropTransferer.Mixin,
ReactCompositeComponentMixin
);
/**
* Module for creating composite components.
*
* @class ReactCompositeComponent
* @extends ReactComponent
* @extends ReactOwner
* @extends ReactPropTransferer
*/
var ReactCompositeComponent = {
LifeCycle: CompositeLifeCycle,
Base: ReactCompositeComponentBase,
/**
* Creates a composite component class given a class specification.
*
* @param {object} spec Class specification (which must define `render`).
* @return {function} Component constructor function.
* @public
*/
createClass: function(spec) {
var Constructor = function(props) {
// This constructor is overridden by mocks. The argument is used
// by mocks to assert on what gets mounted. This will later be used
// by the stand-alone class implementation.
};
Constructor.prototype = new ReactCompositeComponentBase();
Constructor.prototype.constructor = Constructor;
injectedMixins.forEach(
mixSpecIntoComponent.bind(null, Constructor)
);
mixSpecIntoComponent(Constructor, spec);
// Initialize the defaultProps property after all mixins have been merged
if (Constructor.getDefaultProps) {
Constructor.defaultProps = Constructor.getDefaultProps();
}
("production" !== "development" ? invariant(
Constructor.prototype.render,
'createClass(...): Class specification must implement a `render` method.'
) : invariant(Constructor.prototype.render));
if ("production" !== "development") {
if (Constructor.prototype.componentShouldUpdate) {
monitorCodeUse(
'react_component_should_update_warning',
{ component: spec.displayName }
);
console.warn(
(spec.displayName || 'A component') + ' has a method called ' +
'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' +
'The name is phrased as a question because the function is ' +
'expected to return a value.'
);
}
}
// Reduce time spent doing lookups by setting these on the prototype.
for (var methodName in ReactCompositeComponentInterface) {
if (!Constructor.prototype[methodName]) {
Constructor.prototype[methodName] = null;
}
}
if ("production" !== "development") {
return ReactLegacyElement.wrapFactory(
ReactElementValidator.createFactory(Constructor)
);
}
return ReactLegacyElement.wrapFactory(
ReactElement.createFactory(Constructor)
);
},
injection: {
injectMixin: function(mixin) {
injectedMixins.push(mixin);
}
}
};
module.exports = ReactCompositeComponent;
},{"./Object.assign":29,"./ReactComponent":37,"./ReactContext":41,"./ReactCurrentOwner":42,"./ReactElement":58,"./ReactElementValidator":59,"./ReactEmptyComponent":60,"./ReactErrorUtils":61,"./ReactLegacyElement":67,"./ReactOwner":74,"./ReactPerf":75,"./ReactPropTransferer":76,"./ReactPropTypeLocationNames":77,"./ReactPropTypeLocations":78,"./ReactUpdates":91,"./instantiateReactComponent":139,"./invariant":140,"./keyMirror":146,"./keyOf":147,"./mapObject":148,"./monitorCodeUse":150,"./shouldUpdateReactComponent":156,"./warning":160}],41:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactContext
*/
"use strict";
var assign = _dereq_("./Object.assign");
/**
* Keeps track of the current context.
*
* The context is automatically passed down the component ownership hierarchy
* and is accessible via `this.context` on ReactCompositeComponents.
*/
var ReactContext = {
/**
* @internal
* @type {object}
*/
current: {},
/**
* Temporarily extends the current context while executing scopedCallback.
*
* A typical use case might look like
*
* render: function() {
* var children = ReactContext.withContext({foo: 'foo'}, () => (
*
* ));
* return <div>{children};
* }
*
* @param {object} newContext New context to merge into the existing context
* @param {function} scopedCallback Callback to run with the new context
* @return {ReactComponent|array<ReactComponent>}
*/
withContext: function(newContext, scopedCallback) {
var result;
var previousContext = ReactContext.current;
ReactContext.current = assign({}, previousContext, newContext);
try {
result = scopedCallback();
} finally {
ReactContext.current = previousContext;
}
return result;
}
};
module.exports = ReactContext;
},{"./Object.assign":29}],42:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactCurrentOwner
*/
"use strict";
/**
* Keeps track of the current owner.
*
* The current owner is the component who should own any components that are
* currently being constructed.
*
* The depth indicate how many composite components are above this render level.
*/
var ReactCurrentOwner = {
/**
* @internal
* @type {ReactComponent}
*/
current: null
};
module.exports = ReactCurrentOwner;
},{}],43:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDOM
* @typechecks static-only
*/
"use strict";
var ReactElement = _dereq_("./ReactElement");
var ReactElementValidator = _dereq_("./ReactElementValidator");
var ReactLegacyElement = _dereq_("./ReactLegacyElement");
var mapObject = _dereq_("./mapObject");
/**
* Create a factory that creates HTML tag elements.
*
* @param {string} tag Tag name (e.g. `div`).
* @private
*/
function createDOMFactory(tag) {
if ("production" !== "development") {
return ReactLegacyElement.markNonLegacyFactory(
ReactElementValidator.createFactory(tag)
);
}
return ReactLegacyElement.markNonLegacyFactory(
ReactElement.createFactory(tag)
);
}
/**
* Creates a mapping from supported HTML tags to `ReactDOMComponent` classes.
* This is also accessible via `React.DOM`.
*
* @public
*/
var ReactDOM = mapObject({
a: 'a',
abbr: 'abbr',
address: 'address',
area: 'area',
article: 'article',
aside: 'aside',
audio: 'audio',
b: 'b',
base: 'base',
bdi: 'bdi',
bdo: 'bdo',
big: 'big',
blockquote: 'blockquote',
body: 'body',
br: 'br',
button: 'button',
canvas: 'canvas',
caption: 'caption',
cite: 'cite',
code: 'code',
col: 'col',
colgroup: 'colgroup',
data: 'data',
datalist: 'datalist',
dd: 'dd',
del: 'del',
details: 'details',
dfn: 'dfn',
dialog: 'dialog',
div: 'div',
dl: 'dl',
dt: 'dt',
em: 'em',
embed: 'embed',
fieldset: 'fieldset',
figcaption: 'figcaption',
figure: 'figure',
footer: 'footer',
form: 'form',
h1: 'h1',
h2: 'h2',
h3: 'h3',
h4: 'h4',
h5: 'h5',
h6: 'h6',
head: 'head',
header: 'header',
hr: 'hr',
html: 'html',
i: 'i',
iframe: 'iframe',
img: 'img',
input: 'input',
ins: 'ins',
kbd: 'kbd',
keygen: 'keygen',
label: 'label',
legend: 'legend',
li: 'li',
link: 'link',
main: 'main',
map: 'map',
mark: 'mark',
menu: 'menu',
menuitem: 'menuitem',
meta: 'meta',
meter: 'meter',
nav: 'nav',
noscript: 'noscript',
object: 'object',
ol: 'ol',
optgroup: 'optgroup',
option: 'option',
output: 'output',
p: 'p',
param: 'param',
picture: 'picture',
pre: 'pre',
progress: 'progress',
q: 'q',
rp: 'rp',
rt: 'rt',
ruby: 'ruby',
s: 's',
samp: 'samp',
script: 'script',
section: 'section',
select: 'select',
small: 'small',
source: 'source',
span: 'span',
strong: 'strong',
style: 'style',
sub: 'sub',
summary: 'summary',
sup: 'sup',
table: 'table',
tbody: 'tbody',
td: 'td',
textarea: 'textarea',
tfoot: 'tfoot',
th: 'th',
thead: 'thead',
time: 'time',
title: 'title',
tr: 'tr',
track: 'track',
u: 'u',
ul: 'ul',
'var': 'var',
video: 'video',
wbr: 'wbr',
// SVG
circle: 'circle',
defs: 'defs',
ellipse: 'ellipse',
g: 'g',
line: 'line',
linearGradient: 'linearGradient',
mask: 'mask',
path: 'path',
pattern: 'pattern',
polygon: 'polygon',
polyline: 'polyline',
radialGradient: 'radialGradient',
rect: 'rect',
stop: 'stop',
svg: 'svg',
text: 'text',
tspan: 'tspan'
}, createDOMFactory);
module.exports = ReactDOM;
},{"./ReactElement":58,"./ReactElementValidator":59,"./ReactLegacyElement":67,"./mapObject":148}],44:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDOMButton
*/
"use strict";
var AutoFocusMixin = _dereq_("./AutoFocusMixin");
var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin");
var ReactCompositeComponent = _dereq_("./ReactCompositeComponent");
var ReactElement = _dereq_("./ReactElement");
var ReactDOM = _dereq_("./ReactDOM");
var keyMirror = _dereq_("./keyMirror");
// Store a reference to the <button> `ReactDOMComponent`. TODO: use string
var button = ReactElement.createFactory(ReactDOM.button.type);
var mouseListenerNames = keyMirror({
onClick: true,
onDoubleClick: true,
onMouseDown: true,
onMouseMove: true,
onMouseUp: true,
onClickCapture: true,
onDoubleClickCapture: true,
onMouseDownCapture: true,
onMouseMoveCapture: true,
onMouseUpCapture: true
});
/**
* Implements a <button> native component that does not receive mouse events
* when `disabled` is set.
*/
var ReactDOMButton = ReactCompositeComponent.createClass({
displayName: 'ReactDOMButton',
mixins: [AutoFocusMixin, ReactBrowserComponentMixin],
render: function() {
var props = {};
// Copy the props; except the mouse listeners if we're disabled
for (var key in this.props) {
if (this.props.hasOwnProperty(key) &&
(!this.props.disabled || !mouseListenerNames[key])) {
props[key] = this.props[key];
}
}
return button(props, this.props.children);
}
});
module.exports = ReactDOMButton;
},{"./AutoFocusMixin":2,"./ReactBrowserComponentMixin":32,"./ReactCompositeComponent":40,"./ReactDOM":43,"./ReactElement":58,"./keyMirror":146}],45:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDOMComponent
* @typechecks static-only
*/
"use strict";
var CSSPropertyOperations = _dereq_("./CSSPropertyOperations");
var DOMProperty = _dereq_("./DOMProperty");
var DOMPropertyOperations = _dereq_("./DOMPropertyOperations");
var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin");
var ReactComponent = _dereq_("./ReactComponent");
var ReactBrowserEventEmitter = _dereq_("./ReactBrowserEventEmitter");
var ReactMount = _dereq_("./ReactMount");
var ReactMultiChild = _dereq_("./ReactMultiChild");
var ReactPerf = _dereq_("./ReactPerf");
var assign = _dereq_("./Object.assign");
var escapeTextForBrowser = _dereq_("./escapeTextForBrowser");
var invariant = _dereq_("./invariant");
var isEventSupported = _dereq_("./isEventSupported");
var keyOf = _dereq_("./keyOf");
var monitorCodeUse = _dereq_("./monitorCodeUse");
var deleteListener = ReactBrowserEventEmitter.deleteListener;
var listenTo = ReactBrowserEventEmitter.listenTo;
var registrationNameModules = ReactBrowserEventEmitter.registrationNameModules;
// For quickly matching children type, to test if can be treated as content.
var CONTENT_TYPES = {'string': true, 'number': true};
var STYLE = keyOf({style: null});
var ELEMENT_NODE_TYPE = 1;
/**
* @param {?object} props
*/
function assertValidProps(props) {
if (!props) {
return;
}
// Note the use of `==` which checks for null or undefined.
("production" !== "development" ? invariant(
props.children == null || props.dangerouslySetInnerHTML == null,
'Can only set one of `children` or `props.dangerouslySetInnerHTML`.'
) : invariant(props.children == null || props.dangerouslySetInnerHTML == null));
if ("production" !== "development") {
if (props.contentEditable && props.children != null) {
console.warn(
'A component is `contentEditable` and contains `children` managed by ' +
'React. It is now your responsibility to guarantee that none of those '+
'nodes are unexpectedly modified or duplicated. This is probably not ' +
'intentional.'
);
}
}
("production" !== "development" ? invariant(
props.style == null || typeof props.style === 'object',
'The `style` prop expects a mapping from style properties to values, ' +
'not a string.'
) : invariant(props.style == null || typeof props.style === 'object'));
}
function putListener(id, registrationName, listener, transaction) {
if ("production" !== "development") {
// IE8 has no API for event capturing and the `onScroll` event doesn't
// bubble.
if (registrationName === 'onScroll' &&
!isEventSupported('scroll', true)) {
monitorCodeUse('react_no_scroll_event');
console.warn('This browser doesn\'t support the `onScroll` event');
}
}
var container = ReactMount.findReactContainerForID(id);
if (container) {
var doc = container.nodeType === ELEMENT_NODE_TYPE ?
container.ownerDocument :
container;
listenTo(registrationName, doc);
}
transaction.getPutListenerQueue().enqueuePutListener(
id,
registrationName,
listener
);
}
// For HTML, certain tags should omit their close tag. We keep a whitelist for
// those special cased tags.
var omittedCloseTags = {
'area': true,
'base': true,
'br': true,
'col': true,
'embed': true,
'hr': true,
'img': true,
'input': true,
'keygen': true,
'link': true,
'meta': true,
'param': true,
'source': true,
'track': true,
'wbr': true
// NOTE: menuitem's close tag should be omitted, but that causes problems.
};
// We accept any tag to be rendered but since this gets injected into abitrary
// HTML, we want to make sure that it's a safe tag.
// http://www.w3.org/TR/REC-xml/#NT-Name
var VALID_TAG_REGEX = /^[a-zA-Z][a-zA-Z:_\.\-\d]*$/; // Simplified subset
var validatedTagCache = {};
var hasOwnProperty = {}.hasOwnProperty;
function validateDangerousTag(tag) {
if (!hasOwnProperty.call(validatedTagCache, tag)) {
("production" !== "development" ? invariant(VALID_TAG_REGEX.test(tag), 'Invalid tag: %s', tag) : invariant(VALID_TAG_REGEX.test(tag)));
validatedTagCache[tag] = true;
}
}
/**
* Creates a new React class that is idempotent and capable of containing other
* React components. It accepts event listeners and DOM properties that are
* valid according to `DOMProperty`.
*
* - Event listeners: `onClick`, `onMouseDown`, etc.
* - DOM properties: `className`, `name`, `title`, etc.
*
* The `style` property functions differently from the DOM API. It accepts an
* object mapping of style properties to values.
*
* @constructor ReactDOMComponent
* @extends ReactComponent
* @extends ReactMultiChild
*/
function ReactDOMComponent(tag) {
validateDangerousTag(tag);
this._tag = tag;
this.tagName = tag.toUpperCase();
}
ReactDOMComponent.displayName = 'ReactDOMComponent';
ReactDOMComponent.Mixin = {
/**
* Generates root tag markup then recurses. This method has side effects and
* is not idempotent.
*
* @internal
* @param {string} rootID The root DOM ID for this node.
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
* @param {number} mountDepth number of components in the owner hierarchy
* @return {string} The computed markup.
*/
mountComponent: ReactPerf.measure(
'ReactDOMComponent',
'mountComponent',
function(rootID, transaction, mountDepth) {
ReactComponent.Mixin.mountComponent.call(
this,
rootID,
transaction,
mountDepth
);
assertValidProps(this.props);
var closeTag = omittedCloseTags[this._tag] ? '' : '</' + this._tag + '>';
return (
this._createOpenTagMarkupAndPutListeners(transaction) +
this._createContentMarkup(transaction) +
closeTag
);
}
),
/**
* Creates markup for the open tag and all attributes.
*
* This method has side effects because events get registered.
*
* Iterating over object properties is faster than iterating over arrays.
* @see http://jsperf.com/obj-vs-arr-iteration
*
* @private
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
* @return {string} Markup of opening tag.
*/
_createOpenTagMarkupAndPutListeners: function(transaction) {
var props = this.props;
var ret = '<' + this._tag;
for (var propKey in props) {
if (!props.hasOwnProperty(propKey)) {
continue;
}
var propValue = props[propKey];
if (propValue == null) {
continue;
}
if (registrationNameModules.hasOwnProperty(propKey)) {
putListener(this._rootNodeID, propKey, propValue, transaction);
} else {
if (propKey === STYLE) {
if (propValue) {
propValue = props.style = assign({}, props.style);
}
propValue = CSSPropertyOperations.createMarkupForStyles(propValue);
}
var markup =
DOMPropertyOperations.createMarkupForProperty(propKey, propValue);
if (markup) {
ret += ' ' + markup;
}
}
}
// For static pages, no need to put React ID and checksum. Saves lots of
// bytes.
if (transaction.renderToStaticMarkup) {
return ret + '>';
}
var markupForID = DOMPropertyOperations.createMarkupForID(this._rootNodeID);
return ret + ' ' + markupForID + '>';
},
/**
* Creates markup for the content between the tags.
*
* @private
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
* @return {string} Content markup.
*/
_createContentMarkup: function(transaction) {
// Intentional use of != to avoid catching zero/false.
var innerHTML = this.props.dangerouslySetInnerHTML;
if (innerHTML != null) {
if (innerHTML.__html != null) {
return innerHTML.__html;
}
} else {
var contentToUse =
CONTENT_TYPES[typeof this.props.children] ? this.props.children : null;
var childrenToUse = contentToUse != null ? null : this.props.children;
if (contentToUse != null) {
return escapeTextForBrowser(contentToUse);
} else if (childrenToUse != null) {
var mountImages = this.mountChildren(
childrenToUse,
transaction
);
return mountImages.join('');
}
}
return '';
},
receiveComponent: function(nextElement, transaction) {
if (nextElement === this._currentElement &&
nextElement._owner != null) {
// Since elements are immutable after the owner is rendered,
// we can do a cheap identity compare here to determine if this is a
// superfluous reconcile. It's possible for state to be mutable but such
// change should trigger an update of the owner which would recreate
// the element. We explicitly check for the existence of an owner since
// it's possible for a element created outside a composite to be
// deeply mutated and reused.
return;
}
ReactComponent.Mixin.receiveComponent.call(
this,
nextElement,
transaction
);
},
/**
* Updates a native DOM component after it has already been allocated and
* attached to the DOM. Reconciles the root DOM node, then recurses.
*
* @param {ReactReconcileTransaction} transaction
* @param {ReactElement} prevElement
* @internal
* @overridable
*/
updateComponent: ReactPerf.measure(
'ReactDOMComponent',
'updateComponent',
function(transaction, prevElement) {
assertValidProps(this._currentElement.props);
ReactComponent.Mixin.updateComponent.call(
this,
transaction,
prevElement
);
this._updateDOMProperties(prevElement.props, transaction);
this._updateDOMChildren(prevElement.props, transaction);
}
),
/**
* Reconciles the properties by detecting differences in property values and
* updating the DOM as necessary. This function is probably the single most
* critical path for performance optimization.
*
* TODO: Benchmark whether checking for changed values in memory actually
* improves performance (especially statically positioned elements).
* TODO: Benchmark the effects of putting this at the top since 99% of props
* do not change for a given reconciliation.
* TODO: Benchmark areas that can be improved with caching.
*
* @private
* @param {object} lastProps
* @param {ReactReconcileTransaction} transaction
*/
_updateDOMProperties: function(lastProps, transaction) {
var nextProps = this.props;
var propKey;
var styleName;
var styleUpdates;
for (propKey in lastProps) {
if (nextProps.hasOwnProperty(propKey) ||
!lastProps.hasOwnProperty(propKey)) {
continue;
}
if (propKey === STYLE) {
var lastStyle = lastProps[propKey];
for (styleName in lastStyle) {
if (lastStyle.hasOwnProperty(styleName)) {
styleUpdates = styleUpdates || {};
styleUpdates[styleName] = '';
}
}
} else if (registrationNameModules.hasOwnProperty(propKey)) {
deleteListener(this._rootNodeID, propKey);
} else if (
DOMProperty.isStandardName[propKey] ||
DOMProperty.isCustomAttribute(propKey)) {
ReactComponent.BackendIDOperations.deletePropertyByID(
this._rootNodeID,
propKey
);
}
}
for (propKey in nextProps) {
var nextProp = nextProps[propKey];
var lastProp = lastProps[propKey];
if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp) {
continue;
}
if (propKey === STYLE) {
if (nextProp) {
nextProp = nextProps.style = assign({}, nextProp);
}
if (lastProp) {
// Unset styles on `lastProp` but not on `nextProp`.
for (styleName in lastProp) {
if (lastProp.hasOwnProperty(styleName) &&
(!nextProp || !nextProp.hasOwnProperty(styleName))) {
styleUpdates = styleUpdates || {};
styleUpdates[styleName] = '';
}
}
// Update styles that changed since `lastProp`.
for (styleName in nextProp) {
if (nextProp.hasOwnProperty(styleName) &&
lastProp[styleName] !== nextProp[styleName]) {
styleUpdates = styleUpdates || {};
styleUpdates[styleName] = nextProp[styleName];
}
}
} else {
// Relies on `updateStylesByID` not mutating `styleUpdates`.
styleUpdates = nextProp;
}
} else if (registrationNameModules.hasOwnProperty(propKey)) {
putListener(this._rootNodeID, propKey, nextProp, transaction);
} else if (
DOMProperty.isStandardName[propKey] ||
DOMProperty.isCustomAttribute(propKey)) {
ReactComponent.BackendIDOperations.updatePropertyByID(
this._rootNodeID,
propKey,
nextProp
);
}
}
if (styleUpdates) {
ReactComponent.BackendIDOperations.updateStylesByID(
this._rootNodeID,
styleUpdates
);
}
},
/**
* Reconciles the children with the various properties that affect the
* children content.
*
* @param {object} lastProps
* @param {ReactReconcileTransaction} transaction
*/
_updateDOMChildren: function(lastProps, transaction) {
var nextProps = this.props;
var lastContent =
CONTENT_TYPES[typeof lastProps.children] ? lastProps.children : null;
var nextContent =
CONTENT_TYPES[typeof nextProps.children] ? nextProps.children : null;
var lastHtml =
lastProps.dangerouslySetInnerHTML &&
lastProps.dangerouslySetInnerHTML.__html;
var nextHtml =
nextProps.dangerouslySetInnerHTML &&
nextProps.dangerouslySetInnerHTML.__html;
// Note the use of `!=` which checks for null or undefined.
var lastChildren = lastContent != null ? null : lastProps.children;
var nextChildren = nextContent != null ? null : nextProps.children;
// If we're switching from children to content/html or vice versa, remove
// the old content
var lastHasContentOrHtml = lastContent != null || lastHtml != null;
var nextHasContentOrHtml = nextContent != null || nextHtml != null;
if (lastChildren != null && nextChildren == null) {
this.updateChildren(null, transaction);
} else if (lastHasContentOrHtml && !nextHasContentOrHtml) {
this.updateTextContent('');
}
if (nextContent != null) {
if (lastContent !== nextContent) {
this.updateTextContent('' + nextContent);
}
} else if (nextHtml != null) {
if (lastHtml !== nextHtml) {
ReactComponent.BackendIDOperations.updateInnerHTMLByID(
this._rootNodeID,
nextHtml
);
}
} else if (nextChildren != null) {
this.updateChildren(nextChildren, transaction);
}
},
/**
* Destroys all event registrations for this instance. Does not remove from
* the DOM. That must be done by the parent.
*
* @internal
*/
unmountComponent: function() {
this.unmountChildren();
ReactBrowserEventEmitter.deleteAllListeners(this._rootNodeID);
ReactComponent.Mixin.unmountComponent.call(this);
}
};
assign(
ReactDOMComponent.prototype,
ReactComponent.Mixin,
ReactDOMComponent.Mixin,
ReactMultiChild.Mixin,
ReactBrowserComponentMixin
);
module.exports = ReactDOMComponent;
},{"./CSSPropertyOperations":6,"./DOMProperty":12,"./DOMPropertyOperations":13,"./Object.assign":29,"./ReactBrowserComponentMixin":32,"./ReactBrowserEventEmitter":33,"./ReactComponent":37,"./ReactMount":70,"./ReactMultiChild":71,"./ReactPerf":75,"./escapeTextForBrowser":123,"./invariant":140,"./isEventSupported":141,"./keyOf":147,"./monitorCodeUse":150}],46:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDOMForm
*/
"use strict";
var EventConstants = _dereq_("./EventConstants");
var LocalEventTrapMixin = _dereq_("./LocalEventTrapMixin");
var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin");
var ReactCompositeComponent = _dereq_("./ReactCompositeComponent");
var ReactElement = _dereq_("./ReactElement");
var ReactDOM = _dereq_("./ReactDOM");
// Store a reference to the <form> `ReactDOMComponent`. TODO: use string
var form = ReactElement.createFactory(ReactDOM.form.type);
/**
* Since onSubmit doesn't bubble OR capture on the top level in IE8, we need
* to capture it on the <form> element itself. There are lots of hacks we could
* do to accomplish this, but the most reliable is to make <form> a
* composite component and use `componentDidMount` to attach the event handlers.
*/
var ReactDOMForm = ReactCompositeComponent.createClass({
displayName: 'ReactDOMForm',
mixins: [ReactBrowserComponentMixin, LocalEventTrapMixin],
render: function() {
// TODO: Instead of using `ReactDOM` directly, we should use JSX. However,
// `jshint` fails to parse JSX so in order for linting to work in the open
// source repo, we need to just use `ReactDOM.form`.
return form(this.props);
},
componentDidMount: function() {
this.trapBubbledEvent(EventConstants.topLevelTypes.topReset, 'reset');
this.trapBubbledEvent(EventConstants.topLevelTypes.topSubmit, 'submit');
}
});
module.exports = ReactDOMForm;
},{"./EventConstants":17,"./LocalEventTrapMixin":27,"./ReactBrowserComponentMixin":32,"./ReactCompositeComponent":40,"./ReactDOM":43,"./ReactElement":58}],47:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDOMIDOperations
* @typechecks static-only
*/
/*jslint evil: true */
"use strict";
var CSSPropertyOperations = _dereq_("./CSSPropertyOperations");
var DOMChildrenOperations = _dereq_("./DOMChildrenOperations");
var DOMPropertyOperations = _dereq_("./DOMPropertyOperations");
var ReactMount = _dereq_("./ReactMount");
var ReactPerf = _dereq_("./ReactPerf");
var invariant = _dereq_("./invariant");
var setInnerHTML = _dereq_("./setInnerHTML");
/**
* Errors for properties that should not be updated with `updatePropertyById()`.
*
* @type {object}
* @private
*/
var INVALID_PROPERTY_ERRORS = {
dangerouslySetInnerHTML:
'`dangerouslySetInnerHTML` must be set using `updateInnerHTMLByID()`.',
style: '`style` must be set using `updateStylesByID()`.'
};
/**
* Operations used to process updates to DOM nodes. This is made injectable via
* `ReactComponent.BackendIDOperations`.
*/
var ReactDOMIDOperations = {
/**
* Updates a DOM node with new property values. This should only be used to
* update DOM properties in `DOMProperty`.
*
* @param {string} id ID of the node to update.
* @param {string} name A valid property name, see `DOMProperty`.
* @param {*} value New value of the property.
* @internal
*/
updatePropertyByID: ReactPerf.measure(
'ReactDOMIDOperations',
'updatePropertyByID',
function(id, name, value) {
var node = ReactMount.getNode(id);
("production" !== "development" ? invariant(
!INVALID_PROPERTY_ERRORS.hasOwnProperty(name),
'updatePropertyByID(...): %s',
INVALID_PROPERTY_ERRORS[name]
) : invariant(!INVALID_PROPERTY_ERRORS.hasOwnProperty(name)));
// If we're updating to null or undefined, we should remove the property
// from the DOM node instead of inadvertantly setting to a string. This
// brings us in line with the same behavior we have on initial render.
if (value != null) {
DOMPropertyOperations.setValueForProperty(node, name, value);
} else {
DOMPropertyOperations.deleteValueForProperty(node, name);
}
}
),
/**
* Updates a DOM node to remove a property. This should only be used to remove
* DOM properties in `DOMProperty`.
*
* @param {string} id ID of the node to update.
* @param {string} name A property name to remove, see `DOMProperty`.
* @internal
*/
deletePropertyByID: ReactPerf.measure(
'ReactDOMIDOperations',
'deletePropertyByID',
function(id, name, value) {
var node = ReactMount.getNode(id);
("production" !== "development" ? invariant(
!INVALID_PROPERTY_ERRORS.hasOwnProperty(name),
'updatePropertyByID(...): %s',
INVALID_PROPERTY_ERRORS[name]
) : invariant(!INVALID_PROPERTY_ERRORS.hasOwnProperty(name)));
DOMPropertyOperations.deleteValueForProperty(node, name, value);
}
),
/**
* Updates a DOM node with new style values. If a value is specified as '',
* the corresponding style property will be unset.
*
* @param {string} id ID of the node to update.
* @param {object} styles Mapping from styles to values.
* @internal
*/
updateStylesByID: ReactPerf.measure(
'ReactDOMIDOperations',
'updateStylesByID',
function(id, styles) {
var node = ReactMount.getNode(id);
CSSPropertyOperations.setValueForStyles(node, styles);
}
),
/**
* Updates a DOM node's innerHTML.
*
* @param {string} id ID of the node to update.
* @param {string} html An HTML string.
* @internal
*/
updateInnerHTMLByID: ReactPerf.measure(
'ReactDOMIDOperations',
'updateInnerHTMLByID',
function(id, html) {
var node = ReactMount.getNode(id);
setInnerHTML(node, html);
}
),
/**
* Updates a DOM node's text content set by `props.content`.
*
* @param {string} id ID of the node to update.
* @param {string} content Text content.
* @internal
*/
updateTextContentByID: ReactPerf.measure(
'ReactDOMIDOperations',
'updateTextContentByID',
function(id, content) {
var node = ReactMount.getNode(id);
DOMChildrenOperations.updateTextContent(node, content);
}
),
/**
* Replaces a DOM node that exists in the document with markup.
*
* @param {string} id ID of child to be replaced.
* @param {string} markup Dangerous markup to inject in place of child.
* @internal
* @see {Danger.dangerouslyReplaceNodeWithMarkup}
*/
dangerouslyReplaceNodeWithMarkupByID: ReactPerf.measure(
'ReactDOMIDOperations',
'dangerouslyReplaceNodeWithMarkupByID',
function(id, markup) {
var node = ReactMount.getNode(id);
DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup(node, markup);
}
),
/**
* Updates a component's children by processing a series of updates.
*
* @param {array<object>} updates List of update configurations.
* @param {array<string>} markup List of markup strings.
* @internal
*/
dangerouslyProcessChildrenUpdates: ReactPerf.measure(
'ReactDOMIDOperations',
'dangerouslyProcessChildrenUpdates',
function(updates, markup) {
for (var i = 0; i < updates.length; i++) {
updates[i].parentNode = ReactMount.getNode(updates[i].parentID);
}
DOMChildrenOperations.processUpdates(updates, markup);
}
)
};
module.exports = ReactDOMIDOperations;
},{"./CSSPropertyOperations":6,"./DOMChildrenOperations":11,"./DOMPropertyOperations":13,"./ReactMount":70,"./ReactPerf":75,"./invariant":140,"./setInnerHTML":154}],48:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDOMImg
*/
"use strict";
var EventConstants = _dereq_("./EventConstants");
var LocalEventTrapMixin = _dereq_("./LocalEventTrapMixin");
var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin");
var ReactCompositeComponent = _dereq_("./ReactCompositeComponent");
var ReactElement = _dereq_("./ReactElement");
var ReactDOM = _dereq_("./ReactDOM");
// Store a reference to the <img> `ReactDOMComponent`. TODO: use string
var img = ReactElement.createFactory(ReactDOM.img.type);
/**
* Since onLoad doesn't bubble OR capture on the top level in IE8, we need to
* capture it on the <img> element itself. There are lots of hacks we could do
* to accomplish this, but the most reliable is to make <img> a composite
* component and use `componentDidMount` to attach the event handlers.
*/
var ReactDOMImg = ReactCompositeComponent.createClass({
displayName: 'ReactDOMImg',
tagName: 'IMG',
mixins: [ReactBrowserComponentMixin, LocalEventTrapMixin],
render: function() {
return img(this.props);
},
componentDidMount: function() {
this.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load');
this.trapBubbledEvent(EventConstants.topLevelTypes.topError, 'error');
}
});
module.exports = ReactDOMImg;
},{"./EventConstants":17,"./LocalEventTrapMixin":27,"./ReactBrowserComponentMixin":32,"./ReactCompositeComponent":40,"./ReactDOM":43,"./ReactElement":58}],49:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDOMInput
*/
"use strict";
var AutoFocusMixin = _dereq_("./AutoFocusMixin");
var DOMPropertyOperations = _dereq_("./DOMPropertyOperations");
var LinkedValueUtils = _dereq_("./LinkedValueUtils");
var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin");
var ReactCompositeComponent = _dereq_("./ReactCompositeComponent");
var ReactElement = _dereq_("./ReactElement");
var ReactDOM = _dereq_("./ReactDOM");
var ReactMount = _dereq_("./ReactMount");
var ReactUpdates = _dereq_("./ReactUpdates");
var assign = _dereq_("./Object.assign");
var invariant = _dereq_("./invariant");
// Store a reference to the <input> `ReactDOMComponent`. TODO: use string
var input = ReactElement.createFactory(ReactDOM.input.type);
var instancesByReactID = {};
function forceUpdateIfMounted() {
/*jshint validthis:true */
if (this.isMounted()) {
this.forceUpdate();
}
}
/**
* Implements an <input> native component that allows setting these optional
* props: `checked`, `value`, `defaultChecked`, and `defaultValue`.
*
* If `checked` or `value` are not supplied (or null/undefined), user actions
* that affect the checked state or value will trigger updates to the element.
*
* If they are supplied (and not null/undefined), the rendered element will not
* trigger updates to the element. Instead, the props must change in order for
* the rendered element to be updated.
*
* The rendered element will be initialized as unchecked (or `defaultChecked`)
* with an empty value (or `defaultValue`).
*
* @see http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html
*/
var ReactDOMInput = ReactCompositeComponent.createClass({
displayName: 'ReactDOMInput',
mixins: [AutoFocusMixin, LinkedValueUtils.Mixin, ReactBrowserComponentMixin],
getInitialState: function() {
var defaultValue = this.props.defaultValue;
return {
initialChecked: this.props.defaultChecked || false,
initialValue: defaultValue != null ? defaultValue : null
};
},
render: function() {
// Clone `this.props` so we don't mutate the input.
var props = assign({}, this.props);
props.defaultChecked = null;
props.defaultValue = null;
var value = LinkedValueUtils.getValue(this);
props.value = value != null ? value : this.state.initialValue;
var checked = LinkedValueUtils.getChecked(this);
props.checked = checked != null ? checked : this.state.initialChecked;
props.onChange = this._handleChange;
return input(props, this.props.children);
},
componentDidMount: function() {
var id = ReactMount.getID(this.getDOMNode());
instancesByReactID[id] = this;
},
componentWillUnmount: function() {
var rootNode = this.getDOMNode();
var id = ReactMount.getID(rootNode);
delete instancesByReactID[id];
},
componentDidUpdate: function(prevProps, prevState, prevContext) {
var rootNode = this.getDOMNode();
if (this.props.checked != null) {
DOMPropertyOperations.setValueForProperty(
rootNode,
'checked',
this.props.checked || false
);
}
var value = LinkedValueUtils.getValue(this);
if (value != null) {
// Cast `value` to a string to ensure the value is set correctly. While
// browsers typically do this as necessary, jsdom doesn't.
DOMPropertyOperations.setValueForProperty(rootNode, 'value', '' + value);
}
},
_handleChange: function(event) {
var returnValue;
var onChange = LinkedValueUtils.getOnChange(this);
if (onChange) {
returnValue = onChange.call(this, event);
}
// Here we use asap to wait until all updates have propagated, which
// is important when using controlled components within layers:
// https://github.com/facebook/react/issues/1698
ReactUpdates.asap(forceUpdateIfMounted, this);
var name = this.props.name;
if (this.props.type === 'radio' && name != null) {
var rootNode = this.getDOMNode();
var queryRoot = rootNode;
while (queryRoot.parentNode) {
queryRoot = queryRoot.parentNode;
}
// If `rootNode.form` was non-null, then we could try `form.elements`,
// but that sometimes behaves strangely in IE8. We could also try using
// `form.getElementsByName`, but that will only return direct children
// and won't include inputs that use the HTML5 `form=` attribute. Since
// the input might not even be in a form, let's just use the global
// `querySelectorAll` to ensure we don't miss anything.
var group = queryRoot.querySelectorAll(
'input[name=' + JSON.stringify('' + name) + '][type="radio"]');
for (var i = 0, groupLen = group.length; i < groupLen; i++) {
var otherNode = group[i];
if (otherNode === rootNode ||
otherNode.form !== rootNode.form) {
continue;
}
var otherID = ReactMount.getID(otherNode);
("production" !== "development" ? invariant(
otherID,
'ReactDOMInput: Mixing React and non-React radio inputs with the ' +
'same `name` is not supported.'
) : invariant(otherID));
var otherInstance = instancesByReactID[otherID];
("production" !== "development" ? invariant(
otherInstance,
'ReactDOMInput: Unknown radio button ID %s.',
otherID
) : invariant(otherInstance));
// If this is a controlled radio button group, forcing the input that
// was previously checked to update will cause it to be come re-checked
// as appropriate.
ReactUpdates.asap(forceUpdateIfMounted, otherInstance);
}
}
return returnValue;
}
});
module.exports = ReactDOMInput;
},{"./AutoFocusMixin":2,"./DOMPropertyOperations":13,"./LinkedValueUtils":26,"./Object.assign":29,"./ReactBrowserComponentMixin":32,"./ReactCompositeComponent":40,"./ReactDOM":43,"./ReactElement":58,"./ReactMount":70,"./ReactUpdates":91,"./invariant":140}],50:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDOMOption
*/
"use strict";
var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin");
var ReactCompositeComponent = _dereq_("./ReactCompositeComponent");
var ReactElement = _dereq_("./ReactElement");
var ReactDOM = _dereq_("./ReactDOM");
var warning = _dereq_("./warning");
// Store a reference to the <option> `ReactDOMComponent`. TODO: use string
var option = ReactElement.createFactory(ReactDOM.option.type);
/**
* Implements an <option> native component that warns when `selected` is set.
*/
var ReactDOMOption = ReactCompositeComponent.createClass({
displayName: 'ReactDOMOption',
mixins: [ReactBrowserComponentMixin],
componentWillMount: function() {
// TODO (yungsters): Remove support for `selected` in <option>.
if ("production" !== "development") {
("production" !== "development" ? warning(
this.props.selected == null,
'Use the `defaultValue` or `value` props on <select> instead of ' +
'setting `selected` on <option>.'
) : null);
}
},
render: function() {
return option(this.props, this.props.children);
}
});
module.exports = ReactDOMOption;
},{"./ReactBrowserComponentMixin":32,"./ReactCompositeComponent":40,"./ReactDOM":43,"./ReactElement":58,"./warning":160}],51:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDOMSelect
*/
"use strict";
var AutoFocusMixin = _dereq_("./AutoFocusMixin");
var LinkedValueUtils = _dereq_("./LinkedValueUtils");
var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin");
var ReactCompositeComponent = _dereq_("./ReactCompositeComponent");
var ReactElement = _dereq_("./ReactElement");
var ReactDOM = _dereq_("./ReactDOM");
var ReactUpdates = _dereq_("./ReactUpdates");
var assign = _dereq_("./Object.assign");
// Store a reference to the <select> `ReactDOMComponent`. TODO: use string
var select = ReactElement.createFactory(ReactDOM.select.type);
function updateWithPendingValueIfMounted() {
/*jshint validthis:true */
if (this.isMounted()) {
this.setState({value: this._pendingValue});
this._pendingValue = 0;
}
}
/**
* Validation function for `value` and `defaultValue`.
* @private
*/
function selectValueType(props, propName, componentName) {
if (props[propName] == null) {
return;
}
if (props.multiple) {
if (!Array.isArray(props[propName])) {
return new Error(
("The `" + propName + "` prop supplied to <select> must be an array if ") +
("`multiple` is true.")
);
}
} else {
if (Array.isArray(props[propName])) {
return new Error(
("The `" + propName + "` prop supplied to <select> must be a scalar ") +
("value if `multiple` is false.")
);
}
}
}
/**
* If `value` is supplied, updates <option> elements on mount and update.
* @param {ReactComponent} component Instance of ReactDOMSelect
* @param {?*} propValue For uncontrolled components, null/undefined. For
* controlled components, a string (or with `multiple`, a list of strings).
* @private
*/
function updateOptions(component, propValue) {
var multiple = component.props.multiple;
var value = propValue != null ? propValue : component.state.value;
var options = component.getDOMNode().options;
var selectedValue, i, l;
if (multiple) {
selectedValue = {};
for (i = 0, l = value.length; i < l; ++i) {
selectedValue['' + value[i]] = true;
}
} else {
selectedValue = '' + value;
}
for (i = 0, l = options.length; i < l; i++) {
var selected = multiple ?
selectedValue.hasOwnProperty(options[i].value) :
options[i].value === selectedValue;
if (selected !== options[i].selected) {
options[i].selected = selected;
}
}
}
/**
* Implements a <select> native component that allows optionally setting the
* props `value` and `defaultValue`. If `multiple` is false, the prop must be a
* string. If `multiple` is true, the prop must be an array of strings.
*
* If `value` is not supplied (or null/undefined), user actions that change the
* selected option will trigger updates to the rendered options.
*
* If it is supplied (and not null/undefined), the rendered options will not
* update in response to user actions. Instead, the `value` prop must change in
* order for the rendered options to update.
*
* If `defaultValue` is provided, any options with the supplied values will be
* selected.
*/
var ReactDOMSelect = ReactCompositeComponent.createClass({
displayName: 'ReactDOMSelect',
mixins: [AutoFocusMixin, LinkedValueUtils.Mixin, ReactBrowserComponentMixin],
propTypes: {
defaultValue: selectValueType,
value: selectValueType
},
getInitialState: function() {
return {value: this.props.defaultValue || (this.props.multiple ? [] : '')};
},
componentWillMount: function() {
this._pendingValue = null;
},
componentWillReceiveProps: function(nextProps) {
if (!this.props.multiple && nextProps.multiple) {
this.setState({value: [this.state.value]});
} else if (this.props.multiple && !nextProps.multiple) {
this.setState({value: this.state.value[0]});
}
},
render: function() {
// Clone `this.props` so we don't mutate the input.
var props = assign({}, this.props);
props.onChange = this._handleChange;
props.value = null;
return select(props, this.props.children);
},
componentDidMount: function() {
updateOptions(this, LinkedValueUtils.getValue(this));
},
componentDidUpdate: function(prevProps) {
var value = LinkedValueUtils.getValue(this);
var prevMultiple = !!prevProps.multiple;
var multiple = !!this.props.multiple;
if (value != null || prevMultiple !== multiple) {
updateOptions(this, value);
}
},
_handleChange: function(event) {
var returnValue;
var onChange = LinkedValueUtils.getOnChange(this);
if (onChange) {
returnValue = onChange.call(this, event);
}
var selectedValue;
if (this.props.multiple) {
selectedValue = [];
var options = event.target.options;
for (var i = 0, l = options.length; i < l; i++) {
if (options[i].selected) {
selectedValue.push(options[i].value);
}
}
} else {
selectedValue = event.target.value;
}
this._pendingValue = selectedValue;
ReactUpdates.asap(updateWithPendingValueIfMounted, this);
return returnValue;
}
});
module.exports = ReactDOMSelect;
},{"./AutoFocusMixin":2,"./LinkedValueUtils":26,"./Object.assign":29,"./ReactBrowserComponentMixin":32,"./ReactCompositeComponent":40,"./ReactDOM":43,"./ReactElement":58,"./ReactUpdates":91}],52:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDOMSelection
*/
"use strict";
var ExecutionEnvironment = _dereq_("./ExecutionEnvironment");
var getNodeForCharacterOffset = _dereq_("./getNodeForCharacterOffset");
var getTextContentAccessor = _dereq_("./getTextContentAccessor");
/**
* While `isCollapsed` is available on the Selection object and `collapsed`
* is available on the Range object, IE11 sometimes gets them wrong.
* If the anchor/focus nodes and offsets are the same, the range is collapsed.
*/
function isCollapsed(anchorNode, anchorOffset, focusNode, focusOffset) {
return anchorNode === focusNode && anchorOffset === focusOffset;
}
/**
* Get the appropriate anchor and focus node/offset pairs for IE.
*
* The catch here is that IE's selection API doesn't provide information
* about whether the selection is forward or backward, so we have to
* behave as though it's always forward.
*
* IE text differs from modern selection in that it behaves as though
* block elements end with a new line. This means character offsets will
* differ between the two APIs.
*
* @param {DOMElement} node
* @return {object}
*/
function getIEOffsets(node) {
var selection = document.selection;
var selectedRange = selection.createRange();
var selectedLength = selectedRange.text.length;
// Duplicate selection so we can move range without breaking user selection.
var fromStart = selectedRange.duplicate();
fromStart.moveToElementText(node);
fromStart.setEndPoint('EndToStart', selectedRange);
var startOffset = fromStart.text.length;
var endOffset = startOffset + selectedLength;
return {
start: startOffset,
end: endOffset
};
}
/**
* @param {DOMElement} node
* @return {?object}
*/
function getModernOffsets(node) {
var selection = window.getSelection && window.getSelection();
if (!selection || selection.rangeCount === 0) {
return null;
}
var anchorNode = selection.anchorNode;
var anchorOffset = selection.anchorOffset;
var focusNode = selection.focusNode;
var focusOffset = selection.focusOffset;
var currentRange = selection.getRangeAt(0);
// If the node and offset values are the same, the selection is collapsed.
// `Selection.isCollapsed` is available natively, but IE sometimes gets
// this value wrong.
var isSelectionCollapsed = isCollapsed(
selection.anchorNode,
selection.anchorOffset,
selection.focusNode,
selection.focusOffset
);
var rangeLength = isSelectionCollapsed ? 0 : currentRange.toString().length;
var tempRange = currentRange.cloneRange();
tempRange.selectNodeContents(node);
tempRange.setEnd(currentRange.startContainer, currentRange.startOffset);
var isTempRangeCollapsed = isCollapsed(
tempRange.startContainer,
tempRange.startOffset,
tempRange.endContainer,
tempRange.endOffset
);
var start = isTempRangeCollapsed ? 0 : tempRange.toString().length;
var end = start + rangeLength;
// Detect whether the selection is backward.
var detectionRange = document.createRange();
detectionRange.setStart(anchorNode, anchorOffset);
detectionRange.setEnd(focusNode, focusOffset);
var isBackward = detectionRange.collapsed;
return {
start: isBackward ? end : start,
end: isBackward ? start : end
};
}
/**
* @param {DOMElement|DOMTextNode} node
* @param {object} offsets
*/
function setIEOffsets(node, offsets) {
var range = document.selection.createRange().duplicate();
var start, end;
if (typeof offsets.end === 'undefined') {
start = offsets.start;
end = start;
} else if (offsets.start > offsets.end) {
start = offsets.end;
end = offsets.start;
} else {
start = offsets.start;
end = offsets.end;
}
range.moveToElementText(node);
range.moveStart('character', start);
range.setEndPoint('EndToStart', range);
range.moveEnd('character', end - start);
range.select();
}
/**
* In modern non-IE browsers, we can support both forward and backward
* selections.
*
* Note: IE10+ supports the Selection object, but it does not support
* the `extend` method, which means that even in modern IE, it's not possible
* to programatically create a backward selection. Thus, for all IE
* versions, we use the old IE API to create our selections.
*
* @param {DOMElement|DOMTextNode} node
* @param {object} offsets
*/
function setModernOffsets(node, offsets) {
if (!window.getSelection) {
return;
}
var selection = window.getSelection();
var length = node[getTextContentAccessor()].length;
var start = Math.min(offsets.start, length);
var end = typeof offsets.end === 'undefined' ?
start : Math.min(offsets.end, length);
// IE 11 uses modern selection, but doesn't support the extend method.
// Flip backward selections, so we can set with a single range.
if (!selection.extend && start > end) {
var temp = end;
end = start;
start = temp;
}
var startMarker = getNodeForCharacterOffset(node, start);
var endMarker = getNodeForCharacterOffset(node, end);
if (startMarker && endMarker) {
var range = document.createRange();
range.setStart(startMarker.node, startMarker.offset);
selection.removeAllRanges();
if (start > end) {
selection.addRange(range);
selection.extend(endMarker.node, endMarker.offset);
} else {
range.setEnd(endMarker.node, endMarker.offset);
selection.addRange(range);
}
}
}
var useIEOffsets = ExecutionEnvironment.canUseDOM && document.selection;
var ReactDOMSelection = {
/**
* @param {DOMElement} node
*/
getOffsets: useIEOffsets ? getIEOffsets : getModernOffsets,
/**
* @param {DOMElement|DOMTextNode} node
* @param {object} offsets
*/
setOffsets: useIEOffsets ? setIEOffsets : setModernOffsets
};
module.exports = ReactDOMSelection;
},{"./ExecutionEnvironment":23,"./getNodeForCharacterOffset":133,"./getTextContentAccessor":135}],53:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDOMTextarea
*/
"use strict";
var AutoFocusMixin = _dereq_("./AutoFocusMixin");
var DOMPropertyOperations = _dereq_("./DOMPropertyOperations");
var LinkedValueUtils = _dereq_("./LinkedValueUtils");
var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin");
var ReactCompositeComponent = _dereq_("./ReactCompositeComponent");
var ReactElement = _dereq_("./ReactElement");
var ReactDOM = _dereq_("./ReactDOM");
var ReactUpdates = _dereq_("./ReactUpdates");
var assign = _dereq_("./Object.assign");
var invariant = _dereq_("./invariant");
var warning = _dereq_("./warning");
// Store a reference to the <textarea> `ReactDOMComponent`. TODO: use string
var textarea = ReactElement.createFactory(ReactDOM.textarea.type);
function forceUpdateIfMounted() {
/*jshint validthis:true */
if (this.isMounted()) {
this.forceUpdate();
}
}
/**
* Implements a <textarea> native component that allows setting `value`, and
* `defaultValue`. This differs from the traditional DOM API because value is
* usually set as PCDATA children.
*
* If `value` is not supplied (or null/undefined), user actions that affect the
* value will trigger updates to the element.
*
* If `value` is supplied (and not null/undefined), the rendered element will
* not trigger updates to the element. Instead, the `value` prop must change in
* order for the rendered element to be updated.
*
* The rendered element will be initialized with an empty value, the prop
* `defaultValue` if specified, or the children content (deprecated).
*/
var ReactDOMTextarea = ReactCompositeComponent.createClass({
displayName: 'ReactDOMTextarea',
mixins: [AutoFocusMixin, LinkedValueUtils.Mixin, ReactBrowserComponentMixin],
getInitialState: function() {
var defaultValue = this.props.defaultValue;
// TODO (yungsters): Remove support for children content in <textarea>.
var children = this.props.children;
if (children != null) {
if ("production" !== "development") {
("production" !== "development" ? warning(
false,
'Use the `defaultValue` or `value` props instead of setting ' +
'children on <textarea>.'
) : null);
}
("production" !== "development" ? invariant(
defaultValue == null,
'If you supply `defaultValue` on a <textarea>, do not pass children.'
) : invariant(defaultValue == null));
if (Array.isArray(children)) {
("production" !== "development" ? invariant(
children.length <= 1,
'<textarea> can only have at most one child.'
) : invariant(children.length <= 1));
children = children[0];
}
defaultValue = '' + children;
}
if (defaultValue == null) {
defaultValue = '';
}
var value = LinkedValueUtils.getValue(this);
return {
// We save the initial value so that `ReactDOMComponent` doesn't update
// `textContent` (unnecessary since we update value).
// The initial value can be a boolean or object so that's why it's
// forced to be a string.
initialValue: '' + (value != null ? value : defaultValue)
};
},
render: function() {
// Clone `this.props` so we don't mutate the input.
var props = assign({}, this.props);
("production" !== "development" ? invariant(
props.dangerouslySetInnerHTML == null,
'`dangerouslySetInnerHTML` does not make sense on <textarea>.'
) : invariant(props.dangerouslySetInnerHTML == null));
props.defaultValue = null;
props.value = null;
props.onChange = this._handleChange;
// Always set children to the same thing. In IE9, the selection range will
// get reset if `textContent` is mutated.
return textarea(props, this.state.initialValue);
},
componentDidUpdate: function(prevProps, prevState, prevContext) {
var value = LinkedValueUtils.getValue(this);
if (value != null) {
var rootNode = this.getDOMNode();
// Cast `value` to a string to ensure the value is set correctly. While
// browsers typically do this as necessary, jsdom doesn't.
DOMPropertyOperations.setValueForProperty(rootNode, 'value', '' + value);
}
},
_handleChange: function(event) {
var returnValue;
var onChange = LinkedValueUtils.getOnChange(this);
if (onChange) {
returnValue = onChange.call(this, event);
}
ReactUpdates.asap(forceUpdateIfMounted, this);
return returnValue;
}
});
module.exports = ReactDOMTextarea;
},{"./AutoFocusMixin":2,"./DOMPropertyOperations":13,"./LinkedValueUtils":26,"./Object.assign":29,"./ReactBrowserComponentMixin":32,"./ReactCompositeComponent":40,"./ReactDOM":43,"./ReactElement":58,"./ReactUpdates":91,"./invariant":140,"./warning":160}],54:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDefaultBatchingStrategy
*/
"use strict";
var ReactUpdates = _dereq_("./ReactUpdates");
var Transaction = _dereq_("./Transaction");
var assign = _dereq_("./Object.assign");
var emptyFunction = _dereq_("./emptyFunction");
var RESET_BATCHED_UPDATES = {
initialize: emptyFunction,
close: function() {
ReactDefaultBatchingStrategy.isBatchingUpdates = false;
}
};
var FLUSH_BATCHED_UPDATES = {
initialize: emptyFunction,
close: ReactUpdates.flushBatchedUpdates.bind(ReactUpdates)
};
var TRANSACTION_WRAPPERS = [FLUSH_BATCHED_UPDATES, RESET_BATCHED_UPDATES];
function ReactDefaultBatchingStrategyTransaction() {
this.reinitializeTransaction();
}
assign(
ReactDefaultBatchingStrategyTransaction.prototype,
Transaction.Mixin,
{
getTransactionWrappers: function() {
return TRANSACTION_WRAPPERS;
}
}
);
var transaction = new ReactDefaultBatchingStrategyTransaction();
var ReactDefaultBatchingStrategy = {
isBatchingUpdates: false,
/**
* Call the provided function in a context within which calls to `setState`
* and friends are batched such that components aren't updated unnecessarily.
*/
batchedUpdates: function(callback, a, b) {
var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;
ReactDefaultBatchingStrategy.isBatchingUpdates = true;
// The code is written this way to avoid extra allocations
if (alreadyBatchingUpdates) {
callback(a, b);
} else {
transaction.perform(callback, null, a, b);
}
}
};
module.exports = ReactDefaultBatchingStrategy;
},{"./Object.assign":29,"./ReactUpdates":91,"./Transaction":107,"./emptyFunction":121}],55:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDefaultInjection
*/
"use strict";
var BeforeInputEventPlugin = _dereq_("./BeforeInputEventPlugin");
var ChangeEventPlugin = _dereq_("./ChangeEventPlugin");
var ClientReactRootIndex = _dereq_("./ClientReactRootIndex");
var CompositionEventPlugin = _dereq_("./CompositionEventPlugin");
var DefaultEventPluginOrder = _dereq_("./DefaultEventPluginOrder");
var EnterLeaveEventPlugin = _dereq_("./EnterLeaveEventPlugin");
var ExecutionEnvironment = _dereq_("./ExecutionEnvironment");
var HTMLDOMPropertyConfig = _dereq_("./HTMLDOMPropertyConfig");
var MobileSafariClickEventPlugin = _dereq_("./MobileSafariClickEventPlugin");
var ReactBrowserComponentMixin = _dereq_("./ReactBrowserComponentMixin");
var ReactComponentBrowserEnvironment =
_dereq_("./ReactComponentBrowserEnvironment");
var ReactDefaultBatchingStrategy = _dereq_("./ReactDefaultBatchingStrategy");
var ReactDOMComponent = _dereq_("./ReactDOMComponent");
var ReactDOMButton = _dereq_("./ReactDOMButton");
var ReactDOMForm = _dereq_("./ReactDOMForm");
var ReactDOMImg = _dereq_("./ReactDOMImg");
var ReactDOMInput = _dereq_("./ReactDOMInput");
var ReactDOMOption = _dereq_("./ReactDOMOption");
var ReactDOMSelect = _dereq_("./ReactDOMSelect");
var ReactDOMTextarea = _dereq_("./ReactDOMTextarea");
var ReactEventListener = _dereq_("./ReactEventListener");
var ReactInjection = _dereq_("./ReactInjection");
var ReactInstanceHandles = _dereq_("./ReactInstanceHandles");
var ReactMount = _dereq_("./ReactMount");
var SelectEventPlugin = _dereq_("./SelectEventPlugin");
var ServerReactRootIndex = _dereq_("./ServerReactRootIndex");
var SimpleEventPlugin = _dereq_("./SimpleEventPlugin");
var SVGDOMPropertyConfig = _dereq_("./SVGDOMPropertyConfig");
var createFullPageComponent = _dereq_("./createFullPageComponent");
function inject() {
ReactInjection.EventEmitter.injectReactEventListener(
ReactEventListener
);
/**
* Inject modules for resolving DOM hierarchy and plugin ordering.
*/
ReactInjection.EventPluginHub.injectEventPluginOrder(DefaultEventPluginOrder);
ReactInjection.EventPluginHub.injectInstanceHandle(ReactInstanceHandles);
ReactInjection.EventPluginHub.injectMount(ReactMount);
/**
* Some important event plugins included by default (without having to require
* them).
*/
ReactInjection.EventPluginHub.injectEventPluginsByName({
SimpleEventPlugin: SimpleEventPlugin,
EnterLeaveEventPlugin: EnterLeaveEventPlugin,
ChangeEventPlugin: ChangeEventPlugin,
CompositionEventPlugin: CompositionEventPlugin,
MobileSafariClickEventPlugin: MobileSafariClickEventPlugin,
SelectEventPlugin: SelectEventPlugin,
BeforeInputEventPlugin: BeforeInputEventPlugin
});
ReactInjection.NativeComponent.injectGenericComponentClass(
ReactDOMComponent
);
ReactInjection.NativeComponent.injectComponentClasses({
'button': ReactDOMButton,
'form': ReactDOMForm,
'img': ReactDOMImg,
'input': ReactDOMInput,
'option': ReactDOMOption,
'select': ReactDOMSelect,
'textarea': ReactDOMTextarea,
'html': createFullPageComponent('html'),
'head': createFullPageComponent('head'),
'body': createFullPageComponent('body')
});
// This needs to happen after createFullPageComponent() otherwise the mixin
// gets double injected.
ReactInjection.CompositeComponent.injectMixin(ReactBrowserComponentMixin);
ReactInjection.DOMProperty.injectDOMPropertyConfig(HTMLDOMPropertyConfig);
ReactInjection.DOMProperty.injectDOMPropertyConfig(SVGDOMPropertyConfig);
ReactInjection.EmptyComponent.injectEmptyComponent('noscript');
ReactInjection.Updates.injectReconcileTransaction(
ReactComponentBrowserEnvironment.ReactReconcileTransaction
);
ReactInjection.Updates.injectBatchingStrategy(
ReactDefaultBatchingStrategy
);
ReactInjection.RootIndex.injectCreateReactRootIndex(
ExecutionEnvironment.canUseDOM ?
ClientReactRootIndex.createReactRootIndex :
ServerReactRootIndex.createReactRootIndex
);
ReactInjection.Component.injectEnvironment(ReactComponentBrowserEnvironment);
if ("production" !== "development") {
var url = (ExecutionEnvironment.canUseDOM && window.location.href) || '';
if ((/[?&]react_perf\b/).test(url)) {
var ReactDefaultPerf = _dereq_("./ReactDefaultPerf");
ReactDefaultPerf.start();
}
}
}
module.exports = {
inject: inject
};
},{"./BeforeInputEventPlugin":3,"./ChangeEventPlugin":8,"./ClientReactRootIndex":9,"./CompositionEventPlugin":10,"./DefaultEventPluginOrder":15,"./EnterLeaveEventPlugin":16,"./ExecutionEnvironment":23,"./HTMLDOMPropertyConfig":24,"./MobileSafariClickEventPlugin":28,"./ReactBrowserComponentMixin":32,"./ReactComponentBrowserEnvironment":38,"./ReactDOMButton":44,"./ReactDOMComponent":45,"./ReactDOMForm":46,"./ReactDOMImg":48,"./ReactDOMInput":49,"./ReactDOMOption":50,"./ReactDOMSelect":51,"./ReactDOMTextarea":53,"./ReactDefaultBatchingStrategy":54,"./ReactDefaultPerf":56,"./ReactEventListener":63,"./ReactInjection":64,"./ReactInstanceHandles":66,"./ReactMount":70,"./SVGDOMPropertyConfig":92,"./SelectEventPlugin":93,"./ServerReactRootIndex":94,"./SimpleEventPlugin":95,"./createFullPageComponent":116}],56:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDefaultPerf
* @typechecks static-only
*/
"use strict";
var DOMProperty = _dereq_("./DOMProperty");
var ReactDefaultPerfAnalysis = _dereq_("./ReactDefaultPerfAnalysis");
var ReactMount = _dereq_("./ReactMount");
var ReactPerf = _dereq_("./ReactPerf");
var performanceNow = _dereq_("./performanceNow");
function roundFloat(val) {
return Math.floor(val * 100) / 100;
}
function addValue(obj, key, val) {
obj[key] = (obj[key] || 0) + val;
}
var ReactDefaultPerf = {
_allMeasurements: [], // last item in the list is the current one
_mountStack: [0],
_injected: false,
start: function() {
if (!ReactDefaultPerf._injected) {
ReactPerf.injection.injectMeasure(ReactDefaultPerf.measure);
}
ReactDefaultPerf._allMeasurements.length = 0;
ReactPerf.enableMeasure = true;
},
stop: function() {
ReactPerf.enableMeasure = false;
},
getLastMeasurements: function() {
return ReactDefaultPerf._allMeasurements;
},
printExclusive: function(measurements) {
measurements = measurements || ReactDefaultPerf._allMeasurements;
var summary = ReactDefaultPerfAnalysis.getExclusiveSummary(measurements);
console.table(summary.map(function(item) {
return {
'Component class name': item.componentName,
'Total inclusive time (ms)': roundFloat(item.inclusive),
'Exclusive mount time (ms)': roundFloat(item.exclusive),
'Exclusive render time (ms)': roundFloat(item.render),
'Mount time per instance (ms)': roundFloat(item.exclusive / item.count),
'Render time per instance (ms)': roundFloat(item.render / item.count),
'Instances': item.count
};
}));
// TODO: ReactDefaultPerfAnalysis.getTotalTime() does not return the correct
// number.
},
printInclusive: function(measurements) {
measurements = measurements || ReactDefaultPerf._allMeasurements;
var summary = ReactDefaultPerfAnalysis.getInclusiveSummary(measurements);
console.table(summary.map(function(item) {
return {
'Owner > component': item.componentName,
'Inclusive time (ms)': roundFloat(item.time),
'Instances': item.count
};
}));
console.log(
'Total time:',
ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms'
);
},
getMeasurementsSummaryMap: function(measurements) {
var summary = ReactDefaultPerfAnalysis.getInclusiveSummary(
measurements,
true
);
return summary.map(function(item) {
return {
'Owner > component': item.componentName,
'Wasted time (ms)': item.time,
'Instances': item.count
};
});
},
printWasted: function(measurements) {
measurements = measurements || ReactDefaultPerf._allMeasurements;
console.table(ReactDefaultPerf.getMeasurementsSummaryMap(measurements));
console.log(
'Total time:',
ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms'
);
},
printDOM: function(measurements) {
measurements = measurements || ReactDefaultPerf._allMeasurements;
var summary = ReactDefaultPerfAnalysis.getDOMSummary(measurements);
console.table(summary.map(function(item) {
var result = {};
result[DOMProperty.ID_ATTRIBUTE_NAME] = item.id;
result['type'] = item.type;
result['args'] = JSON.stringify(item.args);
return result;
}));
console.log(
'Total time:',
ReactDefaultPerfAnalysis.getTotalTime(measurements).toFixed(2) + ' ms'
);
},
_recordWrite: function(id, fnName, totalTime, args) {
// TODO: totalTime isn't that useful since it doesn't count paints/reflows
var writes =
ReactDefaultPerf
._allMeasurements[ReactDefaultPerf._allMeasurements.length - 1]
.writes;
writes[id] = writes[id] || [];
writes[id].push({
type: fnName,
time: totalTime,
args: args
});
},
measure: function(moduleName, fnName, func) {
return function() {for (var args=[],$__0=0,$__1=arguments.length;$__0<$__1;$__0++) args.push(arguments[$__0]);
var totalTime;
var rv;
var start;
if (fnName === '_renderNewRootComponent' ||
fnName === 'flushBatchedUpdates') {
// A "measurement" is a set of metrics recorded for each flush. We want
// to group the metrics for a given flush together so we can look at the
// components that rendered and the DOM operations that actually
// happened to determine the amount of "wasted work" performed.
ReactDefaultPerf._allMeasurements.push({
exclusive: {},
inclusive: {},
render: {},
counts: {},
writes: {},
displayNames: {},
totalTime: 0
});
start = performanceNow();
rv = func.apply(this, args);
ReactDefaultPerf._allMeasurements[
ReactDefaultPerf._allMeasurements.length - 1
].totalTime = performanceNow() - start;
return rv;
} else if (moduleName === 'ReactDOMIDOperations' ||
moduleName === 'ReactComponentBrowserEnvironment') {
start = performanceNow();
rv = func.apply(this, args);
totalTime = performanceNow() - start;
if (fnName === 'mountImageIntoNode') {
var mountID = ReactMount.getID(args[1]);
ReactDefaultPerf._recordWrite(mountID, fnName, totalTime, args[0]);
} else if (fnName === 'dangerouslyProcessChildrenUpdates') {
// special format
args[0].forEach(function(update) {
var writeArgs = {};
if (update.fromIndex !== null) {
writeArgs.fromIndex = update.fromIndex;
}
if (update.toIndex !== null) {
writeArgs.toIndex = update.toIndex;
}
if (update.textContent !== null) {
writeArgs.textContent = update.textContent;
}
if (update.markupIndex !== null) {
writeArgs.markup = args[1][update.markupIndex];
}
ReactDefaultPerf._recordWrite(
update.parentID,
update.type,
totalTime,
writeArgs
);
});
} else {
// basic format
ReactDefaultPerf._recordWrite(
args[0],
fnName,
totalTime,
Array.prototype.slice.call(args, 1)
);
}
return rv;
} else if (moduleName === 'ReactCompositeComponent' && (
fnName === 'mountComponent' ||
fnName === 'updateComponent' || // TODO: receiveComponent()?
fnName === '_renderValidatedComponent')) {
var rootNodeID = fnName === 'mountComponent' ?
args[0] :
this._rootNodeID;
var isRender = fnName === '_renderValidatedComponent';
var isMount = fnName === 'mountComponent';
var mountStack = ReactDefaultPerf._mountStack;
var entry = ReactDefaultPerf._allMeasurements[
ReactDefaultPerf._allMeasurements.length - 1
];
if (isRender) {
addValue(entry.counts, rootNodeID, 1);
} else if (isMount) {
mountStack.push(0);
}
start = performanceNow();
rv = func.apply(this, args);
totalTime = performanceNow() - start;
if (isRender) {
addValue(entry.render, rootNodeID, totalTime);
} else if (isMount) {
var subMountTime = mountStack.pop();
mountStack[mountStack.length - 1] += totalTime;
addValue(entry.exclusive, rootNodeID, totalTime - subMountTime);
addValue(entry.inclusive, rootNodeID, totalTime);
} else {
addValue(entry.inclusive, rootNodeID, totalTime);
}
entry.displayNames[rootNodeID] = {
current: this.constructor.displayName,
owner: this._owner ? this._owner.constructor.displayName : '<root>'
};
return rv;
} else {
return func.apply(this, args);
}
};
}
};
module.exports = ReactDefaultPerf;
},{"./DOMProperty":12,"./ReactDefaultPerfAnalysis":57,"./ReactMount":70,"./ReactPerf":75,"./performanceNow":153}],57:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDefaultPerfAnalysis
*/
var assign = _dereq_("./Object.assign");
// Don't try to save users less than 1.2ms (a number I made up)
var DONT_CARE_THRESHOLD = 1.2;
var DOM_OPERATION_TYPES = {
'mountImageIntoNode': 'set innerHTML',
INSERT_MARKUP: 'set innerHTML',
MOVE_EXISTING: 'move',
REMOVE_NODE: 'remove',
TEXT_CONTENT: 'set textContent',
'updatePropertyByID': 'update attribute',
'deletePropertyByID': 'delete attribute',
'updateStylesByID': 'update styles',
'updateInnerHTMLByID': 'set innerHTML',
'dangerouslyReplaceNodeWithMarkupByID': 'replace'
};
function getTotalTime(measurements) {
// TODO: return number of DOM ops? could be misleading.
// TODO: measure dropped frames after reconcile?
// TODO: log total time of each reconcile and the top-level component
// class that triggered it.
var totalTime = 0;
for (var i = 0; i < measurements.length; i++) {
var measurement = measurements[i];
totalTime += measurement.totalTime;
}
return totalTime;
}
function getDOMSummary(measurements) {
var items = [];
for (var i = 0; i < measurements.length; i++) {
var measurement = measurements[i];
var id;
for (id in measurement.writes) {
measurement.writes[id].forEach(function(write) {
items.push({
id: id,
type: DOM_OPERATION_TYPES[write.type] || write.type,
args: write.args
});
});
}
}
return items;
}
function getExclusiveSummary(measurements) {
var candidates = {};
var displayName;
for (var i = 0; i < measurements.length; i++) {
var measurement = measurements[i];
var allIDs = assign(
{},
measurement.exclusive,
measurement.inclusive
);
for (var id in allIDs) {
displayName = measurement.displayNames[id].current;
candidates[displayName] = candidates[displayName] || {
componentName: displayName,
inclusive: 0,
exclusive: 0,
render: 0,
count: 0
};
if (measurement.render[id]) {
candidates[displayName].render += measurement.render[id];
}
if (measurement.exclusive[id]) {
candidates[displayName].exclusive += measurement.exclusive[id];
}
if (measurement.inclusive[id]) {
candidates[displayName].inclusive += measurement.inclusive[id];
}
if (measurement.counts[id]) {
candidates[displayName].count += measurement.counts[id];
}
}
}
// Now make a sorted array with the results.
var arr = [];
for (displayName in candidates) {
if (candidates[displayName].exclusive >= DONT_CARE_THRESHOLD) {
arr.push(candidates[displayName]);
}
}
arr.sort(function(a, b) {
return b.exclusive - a.exclusive;
});
return arr;
}
function getInclusiveSummary(measurements, onlyClean) {
var candidates = {};
var inclusiveKey;
for (var i = 0; i < measurements.length; i++) {
var measurement = measurements[i];
var allIDs = assign(
{},
measurement.exclusive,
measurement.inclusive
);
var cleanComponents;
if (onlyClean) {
cleanComponents = getUnchangedComponents(measurement);
}
for (var id in allIDs) {
if (onlyClean && !cleanComponents[id]) {
continue;
}
var displayName = measurement.displayNames[id];
// Inclusive time is not useful for many components without knowing where
// they are instantiated. So we aggregate inclusive time with both the
// owner and current displayName as the key.
inclusiveKey = displayName.owner + ' > ' + displayName.current;
candidates[inclusiveKey] = candidates[inclusiveKey] || {
componentName: inclusiveKey,
time: 0,
count: 0
};
if (measurement.inclusive[id]) {
candidates[inclusiveKey].time += measurement.inclusive[id];
}
if (measurement.counts[id]) {
candidates[inclusiveKey].count += measurement.counts[id];
}
}
}
// Now make a sorted array with the results.
var arr = [];
for (inclusiveKey in candidates) {
if (candidates[inclusiveKey].time >= DONT_CARE_THRESHOLD) {
arr.push(candidates[inclusiveKey]);
}
}
arr.sort(function(a, b) {
return b.time - a.time;
});
return arr;
}
function getUnchangedComponents(measurement) {
// For a given reconcile, look at which components did not actually
// render anything to the DOM and return a mapping of their ID to
// the amount of time it took to render the entire subtree.
var cleanComponents = {};
var dirtyLeafIDs = Object.keys(measurement.writes);
var allIDs = assign({}, measurement.exclusive, measurement.inclusive);
for (var id in allIDs) {
var isDirty = false;
// For each component that rendered, see if a component that triggered
// a DOM op is in its subtree.
for (var i = 0; i < dirtyLeafIDs.length; i++) {
if (dirtyLeafIDs[i].indexOf(id) === 0) {
isDirty = true;
break;
}
}
if (!isDirty && measurement.counts[id] > 0) {
cleanComponents[id] = true;
}
}
return cleanComponents;
}
var ReactDefaultPerfAnalysis = {
getExclusiveSummary: getExclusiveSummary,
getInclusiveSummary: getInclusiveSummary,
getDOMSummary: getDOMSummary,
getTotalTime: getTotalTime
};
module.exports = ReactDefaultPerfAnalysis;
},{"./Object.assign":29}],58:[function(_dereq_,module,exports){
/**
* Copyright 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactElement
*/
"use strict";
var ReactContext = _dereq_("./ReactContext");
var ReactCurrentOwner = _dereq_("./ReactCurrentOwner");
var warning = _dereq_("./warning");
var RESERVED_PROPS = {
key: true,
ref: true
};
/**
* Warn for mutations.
*
* @internal
* @param {object} object
* @param {string} key
*/
function defineWarningProperty(object, key) {
Object.defineProperty(object, key, {
configurable: false,
enumerable: true,
get: function() {
if (!this._store) {
return null;
}
return this._store[key];
},
set: function(value) {
("production" !== "development" ? warning(
false,
'Don\'t set the ' + key + ' property of the component. ' +
'Mutate the existing props object instead.'
) : null);
this._store[key] = value;
}
});
}
/**
* This is updated to true if the membrane is successfully created.
*/
var useMutationMembrane = false;
/**
* Warn for mutations.
*
* @internal
* @param {object} element
*/
function defineMutationMembrane(prototype) {
try {
var pseudoFrozenProperties = {
props: true
};
for (var key in pseudoFrozenProperties) {
defineWarningProperty(prototype, key);
}
useMutationMembrane = true;
} catch (x) {
// IE will fail on defineProperty
}
}
/**
* Base constructor for all React elements. This is only used to make this
* work with a dynamic instanceof check. Nothing should live on this prototype.
*
* @param {*} type
* @param {string|object} ref
* @param {*} key
* @param {*} props
* @internal
*/
var ReactElement = function(type, key, ref, owner, context, props) {
// Built-in properties that belong on the element
this.type = type;
this.key = key;
this.ref = ref;
// Record the component responsible for creating this element.
this._owner = owner;
// TODO: Deprecate withContext, and then the context becomes accessible
// through the owner.
this._context = context;
if ("production" !== "development") {
// The validation flag and props are currently mutative. We put them on
// an external backing store so that we can freeze the whole object.
// This can be replaced with a WeakMap once they are implemented in
// commonly used development environments.
this._store = { validated: false, props: props };
// We're not allowed to set props directly on the object so we early
// return and rely on the prototype membrane to forward to the backing
// store.
if (useMutationMembrane) {
Object.freeze(this);
return;
}
}
this.props = props;
};
// We intentionally don't expose the function on the constructor property.
// ReactElement should be indistinguishable from a plain object.
ReactElement.prototype = {
_isReactElement: true
};
if ("production" !== "development") {
defineMutationMembrane(ReactElement.prototype);
}
ReactElement.createElement = function(type, config, children) {
var propName;
// Reserved names are extracted
var props = {};
var key = null;
var ref = null;
if (config != null) {
ref = config.ref === undefined ? null : config.ref;
if ("production" !== "development") {
("production" !== "development" ? warning(
config.key !== null,
'createElement(...): Encountered component with a `key` of null. In ' +
'a future version, this will be treated as equivalent to the string ' +
'\'null\'; instead, provide an explicit key or use undefined.'
) : null);
}
// TODO: Change this back to `config.key === undefined`
key = config.key == null ? null : '' + config.key;
// Remaining properties are added to a new props object
for (propName in config) {
if (config.hasOwnProperty(propName) &&
!RESERVED_PROPS.hasOwnProperty(propName)) {
props[propName] = config[propName];
}
}
}
// Children can be more than one argument, and those are transferred onto
// the newly allocated props object.
var childrenLength = arguments.length - 2;
if (childrenLength === 1) {
props.children = children;
} else if (childrenLength > 1) {
var childArray = Array(childrenLength);
for (var i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 2];
}
props.children = childArray;
}
// Resolve default props
if (type && type.defaultProps) {
var defaultProps = type.defaultProps;
for (propName in defaultProps) {
if (typeof props[propName] === 'undefined') {
props[propName] = defaultProps[propName];
}
}
}
return new ReactElement(
type,
key,
ref,
ReactCurrentOwner.current,
ReactContext.current,
props
);
};
ReactElement.createFactory = function(type) {
var factory = ReactElement.createElement.bind(null, type);
// Expose the type on the factory and the prototype so that it can be
// easily accessed on elements. E.g. <Foo />.type === Foo.type.
// This should not be named `constructor` since this may not be the function
// that created the element, and it may not even be a constructor.
factory.type = type;
return factory;
};
ReactElement.cloneAndReplaceProps = function(oldElement, newProps) {
var newElement = new ReactElement(
oldElement.type,
oldElement.key,
oldElement.ref,
oldElement._owner,
oldElement._context,
newProps
);
if ("production" !== "development") {
// If the key on the original is valid, then the clone is valid
newElement._store.validated = oldElement._store.validated;
}
return newElement;
};
/**
* @param {?object} object
* @return {boolean} True if `object` is a valid component.
* @final
*/
ReactElement.isValidElement = function(object) {
// ReactTestUtils is often used outside of beforeEach where as React is
// within it. This leads to two different instances of React on the same
// page. To identify a element from a different React instance we use
// a flag instead of an instanceof check.
var isElement = !!(object && object._isReactElement);
// if (isElement && !(object instanceof ReactElement)) {
// This is an indicator that you're using multiple versions of React at the
// same time. This will screw with ownership and stuff. Fix it, please.
// TODO: We could possibly warn here.
// }
return isElement;
};
module.exports = ReactElement;
},{"./ReactContext":41,"./ReactCurrentOwner":42,"./warning":160}],59:[function(_dereq_,module,exports){
/**
* Copyright 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactElementValidator
*/
/**
* ReactElementValidator provides a wrapper around a element factory
* which validates the props passed to the element. This is intended to be
* used only in DEV and could be replaced by a static type checker for languages
* that support it.
*/
"use strict";
var ReactElement = _dereq_("./ReactElement");
var ReactPropTypeLocations = _dereq_("./ReactPropTypeLocations");
var ReactCurrentOwner = _dereq_("./ReactCurrentOwner");
var monitorCodeUse = _dereq_("./monitorCodeUse");
var warning = _dereq_("./warning");
/**
* Warn if there's no key explicitly set on dynamic arrays of children or
* object keys are not valid. This allows us to keep track of children between
* updates.
*/
var ownerHasKeyUseWarning = {
'react_key_warning': {},
'react_numeric_key_warning': {}
};
var ownerHasMonitoredObjectMap = {};
var loggedTypeFailures = {};
var NUMERIC_PROPERTY_REGEX = /^\d+$/;
/**
* Gets the current owner's displayName for use in warnings.
*
* @internal
* @return {?string} Display name or undefined
*/
function getCurrentOwnerDisplayName() {
var current = ReactCurrentOwner.current;
return current && current.constructor.displayName || undefined;
}
/**
* Warn if the component doesn't have an explicit key assigned to it.
* This component is in an array. The array could grow and shrink or be
* reordered. All children that haven't already been validated are required to
* have a "key" property assigned to it.
*
* @internal
* @param {ReactComponent} component Component that requires a key.
* @param {*} parentType component's parent's type.
*/
function validateExplicitKey(component, parentType) {
if (component._store.validated || component.key != null) {
return;
}
component._store.validated = true;
warnAndMonitorForKeyUse(
'react_key_warning',
'Each child in an array should have a unique "key" prop.',
component,
parentType
);
}
/**
* Warn if the key is being defined as an object property but has an incorrect
* value.
*
* @internal
* @param {string} name Property name of the key.
* @param {ReactComponent} component Component that requires a key.
* @param {*} parentType component's parent's type.
*/
function validatePropertyKey(name, component, parentType) {
if (!NUMERIC_PROPERTY_REGEX.test(name)) {
return;
}
warnAndMonitorForKeyUse(
'react_numeric_key_warning',
'Child objects should have non-numeric keys so ordering is preserved.',
component,
parentType
);
}
/**
* Shared warning and monitoring code for the key warnings.
*
* @internal
* @param {string} warningID The id used when logging.
* @param {string} message The base warning that gets output.
* @param {ReactComponent} component Component that requires a key.
* @param {*} parentType component's parent's type.
*/
function warnAndMonitorForKeyUse(warningID, message, component, parentType) {
var ownerName = getCurrentOwnerDisplayName();
var parentName = parentType.displayName;
var useName = ownerName || parentName;
var memoizer = ownerHasKeyUseWarning[warningID];
if (memoizer.hasOwnProperty(useName)) {
return;
}
memoizer[useName] = true;
message += ownerName ?
(" Check the render method of " + ownerName + ".") :
(" Check the renderComponent call using <" + parentName + ">.");
// Usually the current owner is the offender, but if it accepts children as a
// property, it may be the creator of the child that's responsible for
// assigning it a key.
var childOwnerName = null;
if (component._owner && component._owner !== ReactCurrentOwner.current) {
// Name of the component that originally created this child.
childOwnerName = component._owner.constructor.displayName;
message += (" It was passed a child from " + childOwnerName + ".");
}
message += ' See http://fb.me/react-warning-keys for more information.';
monitorCodeUse(warningID, {
component: useName,
componentOwner: childOwnerName
});
console.warn(message);
}
/**
* Log that we're using an object map. We're considering deprecating this
* feature and replace it with proper Map and ImmutableMap data structures.
*
* @internal
*/
function monitorUseOfObjectMap() {
var currentName = getCurrentOwnerDisplayName() || '';
if (ownerHasMonitoredObjectMap.hasOwnProperty(currentName)) {
return;
}
ownerHasMonitoredObjectMap[currentName] = true;
monitorCodeUse('react_object_map_children');
}
/**
* Ensure that every component either is passed in a static location, in an
* array with an explicit keys property defined, or in an object literal
* with valid key property.
*
* @internal
* @param {*} component Statically passed child of any type.
* @param {*} parentType component's parent's type.
* @return {boolean}
*/
function validateChildKeys(component, parentType) {
if (Array.isArray(component)) {
for (var i = 0; i < component.length; i++) {
var child = component[i];
if (ReactElement.isValidElement(child)) {
validateExplicitKey(child, parentType);
}
}
} else if (ReactElement.isValidElement(component)) {
// This component was passed in a valid location.
component._store.validated = true;
} else if (component && typeof component === 'object') {
monitorUseOfObjectMap();
for (var name in component) {
validatePropertyKey(name, component[name], parentType);
}
}
}
/**
* Assert that the props are valid
*
* @param {string} componentName Name of the component for error messages.
* @param {object} propTypes Map of prop name to a ReactPropType
* @param {object} props
* @param {string} location e.g. "prop", "context", "child context"
* @private
*/
function checkPropTypes(componentName, propTypes, props, location) {
for (var propName in propTypes) {
if (propTypes.hasOwnProperty(propName)) {
var error;
// Prop type validation may throw. In case they do, we don't want to
// fail the render phase where it didn't fail before. So we log it.
// After these have been cleaned up, we'll let them throw.
try {
error = propTypes[propName](props, propName, componentName, location);
} catch (ex) {
error = ex;
}
if (error instanceof Error && !(error.message in loggedTypeFailures)) {
// Only monitor this failure once because there tends to be a lot of the
// same error.
loggedTypeFailures[error.message] = true;
// This will soon use the warning module
monitorCodeUse(
'react_failed_descriptor_type_check',
{ message: error.message }
);
}
}
}
}
var ReactElementValidator = {
createElement: function(type, props, children) {
// We warn in this case but don't throw. We expect the element creation to
// succeed and there will likely be errors in render.
("production" !== "development" ? warning(
type != null,
'React.createElement: type should not be null or undefined. It should ' +
'be a string (for DOM elements) or a ReactClass (for composite ' +
'components).'
) : null);
var element = ReactElement.createElement.apply(this, arguments);
// The result can be nullish if a mock or a custom function is used.
// TODO: Drop this when these are no longer allowed as the type argument.
if (element == null) {
return element;
}
for (var i = 2; i < arguments.length; i++) {
validateChildKeys(arguments[i], type);
}
if (type) {
var name = type.displayName;
if (type.propTypes) {
checkPropTypes(
name,
type.propTypes,
element.props,
ReactPropTypeLocations.prop
);
}
if (type.contextTypes) {
checkPropTypes(
name,
type.contextTypes,
element._context,
ReactPropTypeLocations.context
);
}
}
return element;
},
createFactory: function(type) {
var validatedFactory = ReactElementValidator.createElement.bind(
null,
type
);
validatedFactory.type = type;
return validatedFactory;
}
};
module.exports = ReactElementValidator;
},{"./ReactCurrentOwner":42,"./ReactElement":58,"./ReactPropTypeLocations":78,"./monitorCodeUse":150,"./warning":160}],60:[function(_dereq_,module,exports){
/**
* Copyright 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactEmptyComponent
*/
"use strict";
var ReactElement = _dereq_("./ReactElement");
var invariant = _dereq_("./invariant");
var component;
// This registry keeps track of the React IDs of the components that rendered to
// `null` (in reality a placeholder such as `noscript`)
var nullComponentIdsRegistry = {};
var ReactEmptyComponentInjection = {
injectEmptyComponent: function(emptyComponent) {
component = ReactElement.createFactory(emptyComponent);
}
};
/**
* @return {ReactComponent} component The injected empty component.
*/
function getEmptyComponent() {
("production" !== "development" ? invariant(
component,
'Trying to return null from a render, but no null placeholder component ' +
'was injected.'
) : invariant(component));
return component();
}
/**
* Mark the component as having rendered to null.
* @param {string} id Component's `_rootNodeID`.
*/
function registerNullComponentID(id) {
nullComponentIdsRegistry[id] = true;
}
/**
* Unmark the component as having rendered to null: it renders to something now.
* @param {string} id Component's `_rootNodeID`.
*/
function deregisterNullComponentID(id) {
delete nullComponentIdsRegistry[id];
}
/**
* @param {string} id Component's `_rootNodeID`.
* @return {boolean} True if the component is rendered to null.
*/
function isNullComponentID(id) {
return nullComponentIdsRegistry[id];
}
var ReactEmptyComponent = {
deregisterNullComponentID: deregisterNullComponentID,
getEmptyComponent: getEmptyComponent,
injection: ReactEmptyComponentInjection,
isNullComponentID: isNullComponentID,
registerNullComponentID: registerNullComponentID
};
module.exports = ReactEmptyComponent;
},{"./ReactElement":58,"./invariant":140}],61:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactErrorUtils
* @typechecks
*/
"use strict";
var ReactErrorUtils = {
/**
* Creates a guarded version of a function. This is supposed to make debugging
* of event handlers easier. To aid debugging with the browser's debugger,
* this currently simply returns the original function.
*
* @param {function} func Function to be executed
* @param {string} name The name of the guard
* @return {function}
*/
guard: function(func, name) {
return func;
}
};
module.exports = ReactErrorUtils;
},{}],62:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactEventEmitterMixin
*/
"use strict";
var EventPluginHub = _dereq_("./EventPluginHub");
function runEventQueueInBatch(events) {
EventPluginHub.enqueueEvents(events);
EventPluginHub.processEventQueue();
}
var ReactEventEmitterMixin = {
/**
* Streams a fired top-level event to `EventPluginHub` where plugins have the
* opportunity to create `ReactEvent`s to be dispatched.
*
* @param {string} topLevelType Record from `EventConstants`.
* @param {object} topLevelTarget The listening component root node.
* @param {string} topLevelTargetID ID of `topLevelTarget`.
* @param {object} nativeEvent Native environment event.
*/
handleTopLevel: function(
topLevelType,
topLevelTarget,
topLevelTargetID,
nativeEvent) {
var events = EventPluginHub.extractEvents(
topLevelType,
topLevelTarget,
topLevelTargetID,
nativeEvent
);
runEventQueueInBatch(events);
}
};
module.exports = ReactEventEmitterMixin;
},{"./EventPluginHub":19}],63:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactEventListener
* @typechecks static-only
*/
"use strict";
var EventListener = _dereq_("./EventListener");
var ExecutionEnvironment = _dereq_("./ExecutionEnvironment");
var PooledClass = _dereq_("./PooledClass");
var ReactInstanceHandles = _dereq_("./ReactInstanceHandles");
var ReactMount = _dereq_("./ReactMount");
var ReactUpdates = _dereq_("./ReactUpdates");
var assign = _dereq_("./Object.assign");
var getEventTarget = _dereq_("./getEventTarget");
var getUnboundedScrollPosition = _dereq_("./getUnboundedScrollPosition");
/**
* Finds the parent React component of `node`.
*
* @param {*} node
* @return {?DOMEventTarget} Parent container, or `null` if the specified node
* is not nested.
*/
function findParent(node) {
// TODO: It may be a good idea to cache this to prevent unnecessary DOM
// traversal, but caching is difficult to do correctly without using a
// mutation observer to listen for all DOM changes.
var nodeID = ReactMount.getID(node);
var rootID = ReactInstanceHandles.getReactRootIDFromNodeID(nodeID);
var container = ReactMount.findReactContainerForID(rootID);
var parent = ReactMount.getFirstReactDOM(container);
return parent;
}
// Used to store ancestor hierarchy in top level callback
function TopLevelCallbackBookKeeping(topLevelType, nativeEvent) {
this.topLevelType = topLevelType;
this.nativeEvent = nativeEvent;
this.ancestors = [];
}
assign(TopLevelCallbackBookKeeping.prototype, {
destructor: function() {
this.topLevelType = null;
this.nativeEvent = null;
this.ancestors.length = 0;
}
});
PooledClass.addPoolingTo(
TopLevelCallbackBookKeeping,
PooledClass.twoArgumentPooler
);
function handleTopLevelImpl(bookKeeping) {
var topLevelTarget = ReactMount.getFirstReactDOM(
getEventTarget(bookKeeping.nativeEvent)
) || window;
// Loop through the hierarchy, in case there's any nested components.
// It's important that we build the array of ancestors before calling any
// event handlers, because event handlers can modify the DOM, leading to
// inconsistencies with ReactMount's node cache. See #1105.
var ancestor = topLevelTarget;
while (ancestor) {
bookKeeping.ancestors.push(ancestor);
ancestor = findParent(ancestor);
}
for (var i = 0, l = bookKeeping.ancestors.length; i < l; i++) {
topLevelTarget = bookKeeping.ancestors[i];
var topLevelTargetID = ReactMount.getID(topLevelTarget) || '';
ReactEventListener._handleTopLevel(
bookKeeping.topLevelType,
topLevelTarget,
topLevelTargetID,
bookKeeping.nativeEvent
);
}
}
function scrollValueMonitor(cb) {
var scrollPosition = getUnboundedScrollPosition(window);
cb(scrollPosition);
}
var ReactEventListener = {
_enabled: true,
_handleTopLevel: null,
WINDOW_HANDLE: ExecutionEnvironment.canUseDOM ? window : null,
setHandleTopLevel: function(handleTopLevel) {
ReactEventListener._handleTopLevel = handleTopLevel;
},
setEnabled: function(enabled) {
ReactEventListener._enabled = !!enabled;
},
isEnabled: function() {
return ReactEventListener._enabled;
},
/**
* Traps top-level events by using event bubbling.
*
* @param {string} topLevelType Record from `EventConstants`.
* @param {string} handlerBaseName Event name (e.g. "click").
* @param {object} handle Element on which to attach listener.
* @return {object} An object with a remove function which will forcefully
* remove the listener.
* @internal
*/
trapBubbledEvent: function(topLevelType, handlerBaseName, handle) {
var element = handle;
if (!element) {
return;
}
return EventListener.listen(
element,
handlerBaseName,
ReactEventListener.dispatchEvent.bind(null, topLevelType)
);
},
/**
* Traps a top-level event by using event capturing.
*
* @param {string} topLevelType Record from `EventConstants`.
* @param {string} handlerBaseName Event name (e.g. "click").
* @param {object} handle Element on which to attach listener.
* @return {object} An object with a remove function which will forcefully
* remove the listener.
* @internal
*/
trapCapturedEvent: function(topLevelType, handlerBaseName, handle) {
var element = handle;
if (!element) {
return;
}
return EventListener.capture(
element,
handlerBaseName,
ReactEventListener.dispatchEvent.bind(null, topLevelType)
);
},
monitorScrollValue: function(refresh) {
var callback = scrollValueMonitor.bind(null, refresh);
EventListener.listen(window, 'scroll', callback);
EventListener.listen(window, 'resize', callback);
},
dispatchEvent: function(topLevelType, nativeEvent) {
if (!ReactEventListener._enabled) {
return;
}
var bookKeeping = TopLevelCallbackBookKeeping.getPooled(
topLevelType,
nativeEvent
);
try {
// Event queue being processed in the same cycle allows
// `preventDefault`.
ReactUpdates.batchedUpdates(handleTopLevelImpl, bookKeeping);
} finally {
TopLevelCallbackBookKeeping.release(bookKeeping);
}
}
};
module.exports = ReactEventListener;
},{"./EventListener":18,"./ExecutionEnvironment":23,"./Object.assign":29,"./PooledClass":30,"./ReactInstanceHandles":66,"./ReactMount":70,"./ReactUpdates":91,"./getEventTarget":131,"./getUnboundedScrollPosition":136}],64:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactInjection
*/
"use strict";
var DOMProperty = _dereq_("./DOMProperty");
var EventPluginHub = _dereq_("./EventPluginHub");
var ReactComponent = _dereq_("./ReactComponent");
var ReactCompositeComponent = _dereq_("./ReactCompositeComponent");
var ReactEmptyComponent = _dereq_("./ReactEmptyComponent");
var ReactBrowserEventEmitter = _dereq_("./ReactBrowserEventEmitter");
var ReactNativeComponent = _dereq_("./ReactNativeComponent");
var ReactPerf = _dereq_("./ReactPerf");
var ReactRootIndex = _dereq_("./ReactRootIndex");
var ReactUpdates = _dereq_("./ReactUpdates");
var ReactInjection = {
Component: ReactComponent.injection,
CompositeComponent: ReactCompositeComponent.injection,
DOMProperty: DOMProperty.injection,
EmptyComponent: ReactEmptyComponent.injection,
EventPluginHub: EventPluginHub.injection,
EventEmitter: ReactBrowserEventEmitter.injection,
NativeComponent: ReactNativeComponent.injection,
Perf: ReactPerf.injection,
RootIndex: ReactRootIndex.injection,
Updates: ReactUpdates.injection
};
module.exports = ReactInjection;
},{"./DOMProperty":12,"./EventPluginHub":19,"./ReactBrowserEventEmitter":33,"./ReactComponent":37,"./ReactCompositeComponent":40,"./ReactEmptyComponent":60,"./ReactNativeComponent":73,"./ReactPerf":75,"./ReactRootIndex":82,"./ReactUpdates":91}],65:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactInputSelection
*/
"use strict";
var ReactDOMSelection = _dereq_("./ReactDOMSelection");
var containsNode = _dereq_("./containsNode");
var focusNode = _dereq_("./focusNode");
var getActiveElement = _dereq_("./getActiveElement");
function isInDocument(node) {
return containsNode(document.documentElement, node);
}
/**
* @ReactInputSelection: React input selection module. Based on Selection.js,
* but modified to be suitable for react and has a couple of bug fixes (doesn't
* assume buttons have range selections allowed).
* Input selection module for React.
*/
var ReactInputSelection = {
hasSelectionCapabilities: function(elem) {
return elem && (
(elem.nodeName === 'INPUT' && elem.type === 'text') ||
elem.nodeName === 'TEXTAREA' ||
elem.contentEditable === 'true'
);
},
getSelectionInformation: function() {
var focusedElem = getActiveElement();
return {
focusedElem: focusedElem,
selectionRange:
ReactInputSelection.hasSelectionCapabilities(focusedElem) ?
ReactInputSelection.getSelection(focusedElem) :
null
};
},
/**
* @restoreSelection: If any selection information was potentially lost,
* restore it. This is useful when performing operations that could remove dom
* nodes and place them back in, resulting in focus being lost.
*/
restoreSelection: function(priorSelectionInformation) {
var curFocusedElem = getActiveElement();
var priorFocusedElem = priorSelectionInformation.focusedElem;
var priorSelectionRange = priorSelectionInformation.selectionRange;
if (curFocusedElem !== priorFocusedElem &&
isInDocument(priorFocusedElem)) {
if (ReactInputSelection.hasSelectionCapabilities(priorFocusedElem)) {
ReactInputSelection.setSelection(
priorFocusedElem,
priorSelectionRange
);
}
focusNode(priorFocusedElem);
}
},
/**
* @getSelection: Gets the selection bounds of a focused textarea, input or
* contentEditable node.
* -@input: Look up selection bounds of this input
* -@return {start: selectionStart, end: selectionEnd}
*/
getSelection: function(input) {
var selection;
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);
}
return selection || {start: 0, end: 0};
},
/**
* @setSelection: Sets the selection bounds of a textarea or input and focuses
* the input.
* -@input Set selection bounds of this input or textarea
* -@offsets Object of same form that is returned from get*
*/
setSelection: function(input, offsets) {
var start = offsets.start;
var end = offsets.end;
if (typeof end === 'undefined') {
end = start;
}
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);
}
}
};
module.exports = ReactInputSelection;
},{"./ReactDOMSelection":52,"./containsNode":114,"./focusNode":125,"./getActiveElement":127}],66:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactInstanceHandles
* @typechecks static-only
*/
"use strict";
var ReactRootIndex = _dereq_("./ReactRootIndex");
var invariant = _dereq_("./invariant");
var SEPARATOR = '.';
var SEPARATOR_LENGTH = SEPARATOR.length;
/**
* Maximum depth of traversals before we consider the possibility of a bad ID.
*/
var MAX_TREE_DEPTH = 100;
/**
* Creates a DOM ID prefix to use when mounting React components.
*
* @param {number} index A unique integer
* @return {string} React root ID.
* @internal
*/
function getReactRootIDString(index) {
return SEPARATOR + index.toString(36);
}
/**
* Checks if a character in the supplied ID is a separator or the end.
*
* @param {string} id A React DOM ID.
* @param {number} index Index of the character to check.
* @return {boolean} True if the character is a separator or end of the ID.
* @private
*/
function isBoundary(id, index) {
return id.charAt(index) === SEPARATOR || index === id.length;
}
/**
* Checks if the supplied string is a valid React DOM ID.
*
* @param {string} id A React DOM ID, maybe.
* @return {boolean} True if the string is a valid React DOM ID.
* @private
*/
function isValidID(id) {
return id === '' || (
id.charAt(0) === SEPARATOR && id.charAt(id.length - 1) !== SEPARATOR
);
}
/**
* Checks if the first ID is an ancestor of or equal to the second ID.
*
* @param {string} ancestorID
* @param {string} descendantID
* @return {boolean} True if `ancestorID` is an ancestor of `descendantID`.
* @internal
*/
function isAncestorIDOf(ancestorID, descendantID) {
return (
descendantID.indexOf(ancestorID) === 0 &&
isBoundary(descendantID, ancestorID.length)
);
}
/**
* Gets the parent ID of the supplied React DOM ID, `id`.
*
* @param {string} id ID of a component.
* @return {string} ID of the parent, or an empty string.
* @private
*/
function getParentID(id) {
return id ? id.substr(0, id.lastIndexOf(SEPARATOR)) : '';
}
/**
* Gets the next DOM ID on the tree path from the supplied `ancestorID` to the
* supplied `destinationID`. If they are equal, the ID is returned.
*
* @param {string} ancestorID ID of an ancestor node of `destinationID`.
* @param {string} destinationID ID of the destination node.
* @return {string} Next ID on the path from `ancestorID` to `destinationID`.
* @private
*/
function getNextDescendantID(ancestorID, destinationID) {
("production" !== "development" ? invariant(
isValidID(ancestorID) && isValidID(destinationID),
'getNextDescendantID(%s, %s): Received an invalid React DOM ID.',
ancestorID,
destinationID
) : invariant(isValidID(ancestorID) && isValidID(destinationID)));
("production" !== "development" ? invariant(
isAncestorIDOf(ancestorID, destinationID),
'getNextDescendantID(...): React has made an invalid assumption about ' +
'the DOM hierarchy. Expected `%s` to be an ancestor of `%s`.',
ancestorID,
destinationID
) : invariant(isAncestorIDOf(ancestorID, destinationID)));
if (ancestorID === destinationID) {
return ancestorID;
}
// Skip over the ancestor and the immediate separator. Traverse until we hit
// another separator or we reach the end of `destinationID`.
var start = ancestorID.length + SEPARATOR_LENGTH;
for (var i = start; i < destinationID.length; i++) {
if (isBoundary(destinationID, i)) {
break;
}
}
return destinationID.substr(0, i);
}
/**
* Gets the nearest common ancestor ID of two IDs.
*
* Using this ID scheme, the nearest common ancestor ID is the longest common
* prefix of the two IDs that immediately preceded a "marker" in both strings.
*
* @param {string} oneID
* @param {string} twoID
* @return {string} Nearest common ancestor ID, or the empty string if none.
* @private
*/
function getFirstCommonAncestorID(oneID, twoID) {
var minLength = Math.min(oneID.length, twoID.length);
if (minLength === 0) {
return '';
}
var lastCommonMarkerIndex = 0;
// Use `<=` to traverse until the "EOL" of the shorter string.
for (var i = 0; i <= minLength; i++) {
if (isBoundary(oneID, i) && isBoundary(twoID, i)) {
lastCommonMarkerIndex = i;
} else if (oneID.charAt(i) !== twoID.charAt(i)) {
break;
}
}
var longestCommonID = oneID.substr(0, lastCommonMarkerIndex);
("production" !== "development" ? invariant(
isValidID(longestCommonID),
'getFirstCommonAncestorID(%s, %s): Expected a valid React DOM ID: %s',
oneID,
twoID,
longestCommonID
) : invariant(isValidID(longestCommonID)));
return longestCommonID;
}
/**
* Traverses the parent path between two IDs (either up or down). The IDs must
* not be the same, and there must exist a parent path between them. If the
* callback returns `false`, traversal is stopped.
*
* @param {?string} start ID at which to start traversal.
* @param {?string} stop ID at which to end traversal.
* @param {function} cb Callback to invoke each ID with.
* @param {?boolean} skipFirst Whether or not to skip the first node.
* @param {?boolean} skipLast Whether or not to skip the last node.
* @private
*/
function traverseParentPath(start, stop, cb, arg, skipFirst, skipLast) {
start = start || '';
stop = stop || '';
("production" !== "development" ? invariant(
start !== stop,
'traverseParentPath(...): Cannot traverse from and to the same ID, `%s`.',
start
) : invariant(start !== stop));
var traverseUp = isAncestorIDOf(stop, start);
("production" !== "development" ? invariant(
traverseUp || isAncestorIDOf(start, stop),
'traverseParentPath(%s, %s, ...): Cannot traverse from two IDs that do ' +
'not have a parent path.',
start,
stop
) : invariant(traverseUp || isAncestorIDOf(start, stop)));
// Traverse from `start` to `stop` one depth at a time.
var depth = 0;
var traverse = traverseUp ? getParentID : getNextDescendantID;
for (var id = start; /* until break */; id = traverse(id, stop)) {
var ret;
if ((!skipFirst || id !== start) && (!skipLast || id !== stop)) {
ret = cb(id, traverseUp, arg);
}
if (ret === false || id === stop) {
// Only break //after// visiting `stop`.
break;
}
("production" !== "development" ? invariant(
depth++ < MAX_TREE_DEPTH,
'traverseParentPath(%s, %s, ...): Detected an infinite loop while ' +
'traversing the React DOM ID tree. This may be due to malformed IDs: %s',
start, stop
) : invariant(depth++ < MAX_TREE_DEPTH));
}
}
/**
* Manages the IDs assigned to DOM representations of React components. This
* uses a specific scheme in order to traverse the DOM efficiently (e.g. in
* order to simulate events).
*
* @internal
*/
var ReactInstanceHandles = {
/**
* Constructs a React root ID
* @return {string} A React root ID.
*/
createReactRootID: function() {
return getReactRootIDString(ReactRootIndex.createReactRootIndex());
},
/**
* Constructs a React ID by joining a root ID with a name.
*
* @param {string} rootID Root ID of a parent component.
* @param {string} name A component's name (as flattened children).
* @return {string} A React ID.
* @internal
*/
createReactID: function(rootID, name) {
return rootID + name;
},
/**
* Gets the DOM ID of the React component that is the root of the tree that
* contains the React component with the supplied DOM ID.
*
* @param {string} id DOM ID of a React component.
* @return {?string} DOM ID of the React component that is the root.
* @internal
*/
getReactRootIDFromNodeID: function(id) {
if (id && id.charAt(0) === SEPARATOR && id.length > 1) {
var index = id.indexOf(SEPARATOR, 1);
return index > -1 ? id.substr(0, index) : id;
}
return null;
},
/**
* Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that
* should would receive a `mouseEnter` or `mouseLeave` event.
*
* NOTE: Does not invoke the callback on the nearest common ancestor because
* nothing "entered" or "left" that element.
*
* @param {string} leaveID ID being left.
* @param {string} enterID ID being entered.
* @param {function} cb Callback to invoke on each entered/left ID.
* @param {*} upArg Argument to invoke the callback with on left IDs.
* @param {*} downArg Argument to invoke the callback with on entered IDs.
* @internal
*/
traverseEnterLeave: function(leaveID, enterID, cb, upArg, downArg) {
var ancestorID = getFirstCommonAncestorID(leaveID, enterID);
if (ancestorID !== leaveID) {
traverseParentPath(leaveID, ancestorID, cb, upArg, false, true);
}
if (ancestorID !== enterID) {
traverseParentPath(ancestorID, enterID, cb, downArg, true, false);
}
},
/**
* Simulates the traversal of a two-phase, capture/bubble event dispatch.
*
* NOTE: This traversal happens on IDs without touching the DOM.
*
* @param {string} targetID ID of the target node.
* @param {function} cb Callback to invoke.
* @param {*} arg Argument to invoke the callback with.
* @internal
*/
traverseTwoPhase: function(targetID, cb, arg) {
if (targetID) {
traverseParentPath('', targetID, cb, arg, true, false);
traverseParentPath(targetID, '', cb, arg, false, true);
}
},
/**
* Traverse a node ID, calling the supplied `cb` for each ancestor ID. For
* example, passing `.0.$row-0.1` would result in `cb` getting called
* with `.0`, `.0.$row-0`, and `.0.$row-0.1`.
*
* NOTE: This traversal happens on IDs without touching the DOM.
*
* @param {string} targetID ID of the target node.
* @param {function} cb Callback to invoke.
* @param {*} arg Argument to invoke the callback with.
* @internal
*/
traverseAncestors: function(targetID, cb, arg) {
traverseParentPath('', targetID, cb, arg, true, false);
},
/**
* Exposed for unit testing.
* @private
*/
_getFirstCommonAncestorID: getFirstCommonAncestorID,
/**
* Exposed for unit testing.
* @private
*/
_getNextDescendantID: getNextDescendantID,
isAncestorIDOf: isAncestorIDOf,
SEPARATOR: SEPARATOR
};
module.exports = ReactInstanceHandles;
},{"./ReactRootIndex":82,"./invariant":140}],67:[function(_dereq_,module,exports){
/**
* Copyright 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactLegacyElement
*/
"use strict";
var ReactCurrentOwner = _dereq_("./ReactCurrentOwner");
var invariant = _dereq_("./invariant");
var monitorCodeUse = _dereq_("./monitorCodeUse");
var warning = _dereq_("./warning");
var legacyFactoryLogs = {};
function warnForLegacyFactoryCall() {
if (!ReactLegacyElementFactory._isLegacyCallWarningEnabled) {
return;
}
var owner = ReactCurrentOwner.current;
var name = owner && owner.constructor ? owner.constructor.displayName : '';
if (!name) {
name = 'Something';
}
if (legacyFactoryLogs.hasOwnProperty(name)) {
return;
}
legacyFactoryLogs[name] = true;
("production" !== "development" ? warning(
false,
name + ' is calling a React component directly. ' +
'Use a factory or JSX instead. See: http://fb.me/react-legacyfactory'
) : null);
monitorCodeUse('react_legacy_factory_call', { version: 3, name: name });
}
function warnForPlainFunctionType(type) {
var isReactClass =
type.prototype &&
typeof type.prototype.mountComponent === 'function' &&
typeof type.prototype.receiveComponent === 'function';
if (isReactClass) {
("production" !== "development" ? warning(
false,
'Did not expect to get a React class here. Use `Component` instead ' +
'of `Component.type` or `this.constructor`.'
) : null);
} else {
if (!type._reactWarnedForThisType) {
try {
type._reactWarnedForThisType = true;
} catch (x) {
// just incase this is a frozen object or some special object
}
monitorCodeUse(
'react_non_component_in_jsx',
{ version: 3, name: type.name }
);
}
("production" !== "development" ? warning(
false,
'This JSX uses a plain function. Only React components are ' +
'valid in React\'s JSX transform.'
) : null);
}
}
function warnForNonLegacyFactory(type) {
("production" !== "development" ? warning(
false,
'Do not pass React.DOM.' + type.type + ' to JSX or createFactory. ' +
'Use the string "' + type.type + '" instead.'
) : null);
}
/**
* Transfer static properties from the source to the target. Functions are
* rebound to have this reflect the original source.
*/
function proxyStaticMethods(target, source) {
if (typeof source !== 'function') {
return;
}
for (var key in source) {
if (source.hasOwnProperty(key)) {
var value = source[key];
if (typeof value === 'function') {
var bound = value.bind(source);
// Copy any properties defined on the function, such as `isRequired` on
// a PropTypes validator.
for (var k in value) {
if (value.hasOwnProperty(k)) {
bound[k] = value[k];
}
}
target[key] = bound;
} else {
target[key] = value;
}
}
}
}
// We use an object instead of a boolean because booleans are ignored by our
// mocking libraries when these factories gets mocked.
var LEGACY_MARKER = {};
var NON_LEGACY_MARKER = {};
var ReactLegacyElementFactory = {};
ReactLegacyElementFactory.wrapCreateFactory = function(createFactory) {
var legacyCreateFactory = function(type) {
if (typeof type !== 'function') {
// Non-function types cannot be legacy factories
return createFactory(type);
}
if (type.isReactNonLegacyFactory) {
// This is probably a factory created by ReactDOM we unwrap it to get to
// the underlying string type. It shouldn't have been passed here so we
// warn.
if ("production" !== "development") {
warnForNonLegacyFactory(type);
}
return createFactory(type.type);
}
if (type.isReactLegacyFactory) {
// This is probably a legacy factory created by ReactCompositeComponent.
// We unwrap it to get to the underlying class.
return createFactory(type.type);
}
if ("production" !== "development") {
warnForPlainFunctionType(type);
}
// Unless it's a legacy factory, then this is probably a plain function,
// that is expecting to be invoked by JSX. We can just return it as is.
return type;
};
return legacyCreateFactory;
};
ReactLegacyElementFactory.wrapCreateElement = function(createElement) {
var legacyCreateElement = function(type, props, children) {
if (typeof type !== 'function') {
// Non-function types cannot be legacy factories
return createElement.apply(this, arguments);
}
var args;
if (type.isReactNonLegacyFactory) {
// This is probably a factory created by ReactDOM we unwrap it to get to
// the underlying string type. It shouldn't have been passed here so we
// warn.
if ("production" !== "development") {
warnForNonLegacyFactory(type);
}
args = Array.prototype.slice.call(arguments, 0);
args[0] = type.type;
return createElement.apply(this, args);
}
if (type.isReactLegacyFactory) {
// This is probably a legacy factory created by ReactCompositeComponent.
// We unwrap it to get to the underlying class.
if (type._isMockFunction) {
// If this is a mock function, people will expect it to be called. We
// will actually call the original mock factory function instead. This
// future proofs unit testing that assume that these are classes.
type.type._mockedReactClassConstructor = type;
}
args = Array.prototype.slice.call(arguments, 0);
args[0] = type.type;
return createElement.apply(this, args);
}
if ("production" !== "development") {
warnForPlainFunctionType(type);
}
// This is being called with a plain function we should invoke it
// immediately as if this was used with legacy JSX.
return type.apply(null, Array.prototype.slice.call(arguments, 1));
};
return legacyCreateElement;
};
ReactLegacyElementFactory.wrapFactory = function(factory) {
("production" !== "development" ? invariant(
typeof factory === 'function',
'This is suppose to accept a element factory'
) : invariant(typeof factory === 'function'));
var legacyElementFactory = function(config, children) {
// This factory should not be called when JSX is used. Use JSX instead.
if ("production" !== "development") {
warnForLegacyFactoryCall();
}
return factory.apply(this, arguments);
};
proxyStaticMethods(legacyElementFactory, factory.type);
legacyElementFactory.isReactLegacyFactory = LEGACY_MARKER;
legacyElementFactory.type = factory.type;
return legacyElementFactory;
};
// This is used to mark a factory that will remain. E.g. we're allowed to call
// it as a function. However, you're not suppose to pass it to createElement
// or createFactory, so it will warn you if you do.
ReactLegacyElementFactory.markNonLegacyFactory = function(factory) {
factory.isReactNonLegacyFactory = NON_LEGACY_MARKER;
return factory;
};
// Checks if a factory function is actually a legacy factory pretending to
// be a class.
ReactLegacyElementFactory.isValidFactory = function(factory) {
// TODO: This will be removed and moved into a class validator or something.
return typeof factory === 'function' &&
factory.isReactLegacyFactory === LEGACY_MARKER;
};
ReactLegacyElementFactory.isValidClass = function(factory) {
if ("production" !== "development") {
("production" !== "development" ? warning(
false,
'isValidClass is deprecated and will be removed in a future release. ' +
'Use a more specific validator instead.'
) : null);
}
return ReactLegacyElementFactory.isValidFactory(factory);
};
ReactLegacyElementFactory._isLegacyCallWarningEnabled = true;
module.exports = ReactLegacyElementFactory;
},{"./ReactCurrentOwner":42,"./invariant":140,"./monitorCodeUse":150,"./warning":160}],68:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactLink
* @typechecks static-only
*/
"use strict";
/**
* ReactLink encapsulates a common pattern in which a component wants to modify
* a prop received from its parent. ReactLink allows the parent to pass down a
* value coupled with a callback that, when invoked, expresses an intent to
* modify that value. For example:
*
* React.createClass({
* getInitialState: function() {
* return {value: ''};
* },
* render: function() {
* var valueLink = new ReactLink(this.state.value, this._handleValueChange);
* return <input valueLink={valueLink} />;
* },
* this._handleValueChange: function(newValue) {
* this.setState({value: newValue});
* }
* });
*
* We have provided some sugary mixins to make the creation and
* consumption of ReactLink easier; see LinkedValueUtils and LinkedStateMixin.
*/
var React = _dereq_("./React");
/**
* @param {*} value current value of the link
* @param {function} requestChange callback to request a change
*/
function ReactLink(value, requestChange) {
this.value = value;
this.requestChange = requestChange;
}
/**
* Creates a PropType that enforces the ReactLink API and optionally checks the
* type of the value being passed inside the link. Example:
*
* MyComponent.propTypes = {
* tabIndexLink: ReactLink.PropTypes.link(React.PropTypes.number)
* }
*/
function createLinkTypeChecker(linkType) {
var shapes = {
value: typeof linkType === 'undefined' ?
React.PropTypes.any.isRequired :
linkType.isRequired,
requestChange: React.PropTypes.func.isRequired
};
return React.PropTypes.shape(shapes);
}
ReactLink.PropTypes = {
link: createLinkTypeChecker
};
module.exports = ReactLink;
},{"./React":31}],69:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactMarkupChecksum
*/
"use strict";
var adler32 = _dereq_("./adler32");
var ReactMarkupChecksum = {
CHECKSUM_ATTR_NAME: 'data-react-checksum',
/**
* @param {string} markup Markup string
* @return {string} Markup string with checksum attribute attached
*/
addChecksumToMarkup: function(markup) {
var checksum = adler32(markup);
return markup.replace(
'>',
' ' + ReactMarkupChecksum.CHECKSUM_ATTR_NAME + '="' + checksum + '">'
);
},
/**
* @param {string} markup to use
* @param {DOMElement} element root React element
* @returns {boolean} whether or not the markup is the same
*/
canReuseMarkup: function(markup, element) {
var existingChecksum = element.getAttribute(
ReactMarkupChecksum.CHECKSUM_ATTR_NAME
);
existingChecksum = existingChecksum && parseInt(existingChecksum, 10);
var markupChecksum = adler32(markup);
return markupChecksum === existingChecksum;
}
};
module.exports = ReactMarkupChecksum;
},{"./adler32":110}],70:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactMount
*/
"use strict";
var DOMProperty = _dereq_("./DOMProperty");
var ReactBrowserEventEmitter = _dereq_("./ReactBrowserEventEmitter");
var ReactCurrentOwner = _dereq_("./ReactCurrentOwner");
var ReactElement = _dereq_("./ReactElement");
var ReactLegacyElement = _dereq_("./ReactLegacyElement");
var ReactInstanceHandles = _dereq_("./ReactInstanceHandles");
var ReactPerf = _dereq_("./ReactPerf");
var containsNode = _dereq_("./containsNode");
var deprecated = _dereq_("./deprecated");
var getReactRootElementInContainer = _dereq_("./getReactRootElementInContainer");
var instantiateReactComponent = _dereq_("./instantiateReactComponent");
var invariant = _dereq_("./invariant");
var shouldUpdateReactComponent = _dereq_("./shouldUpdateReactComponent");
var warning = _dereq_("./warning");
var createElement = ReactLegacyElement.wrapCreateElement(
ReactElement.createElement
);
var SEPARATOR = ReactInstanceHandles.SEPARATOR;
var ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;
var nodeCache = {};
var ELEMENT_NODE_TYPE = 1;
var DOC_NODE_TYPE = 9;
/** Mapping from reactRootID to React component instance. */
var instancesByReactRootID = {};
/** Mapping from reactRootID to `container` nodes. */
var containersByReactRootID = {};
if ("production" !== "development") {
/** __DEV__-only mapping from reactRootID to root elements. */
var rootElementsByReactRootID = {};
}
// Used to store breadth-first search state in findComponentRoot.
var findComponentRootReusableArray = [];
/**
* @param {DOMElement} container DOM element that may contain a React component.
* @return {?string} A "reactRoot" ID, if a React component is rendered.
*/
function getReactRootID(container) {
var rootElement = getReactRootElementInContainer(container);
return rootElement && ReactMount.getID(rootElement);
}
/**
* Accessing node[ATTR_NAME] or calling getAttribute(ATTR_NAME) on a form
* element can return its control whose name or ID equals ATTR_NAME. All
* DOM nodes support `getAttributeNode` but this can also get called on
* other objects so just return '' if we're given something other than a
* DOM node (such as window).
*
* @param {?DOMElement|DOMWindow|DOMDocument|DOMTextNode} node DOM node.
* @return {string} ID of the supplied `domNode`.
*/
function getID(node) {
var id = internalGetID(node);
if (id) {
if (nodeCache.hasOwnProperty(id)) {
var cached = nodeCache[id];
if (cached !== node) {
("production" !== "development" ? invariant(
!isValid(cached, id),
'ReactMount: Two valid but unequal nodes with the same `%s`: %s',
ATTR_NAME, id
) : invariant(!isValid(cached, id)));
nodeCache[id] = node;
}
} else {
nodeCache[id] = node;
}
}
return id;
}
function internalGetID(node) {
// If node is something like a window, document, or text node, none of
// which support attributes or a .getAttribute method, gracefully return
// the empty string, as if the attribute were missing.
return node && node.getAttribute && node.getAttribute(ATTR_NAME) || '';
}
/**
* Sets the React-specific ID of the given node.
*
* @param {DOMElement} node The DOM node whose ID will be set.
* @param {string} id The value of the ID attribute.
*/
function setID(node, id) {
var oldID = internalGetID(node);
if (oldID !== id) {
delete nodeCache[oldID];
}
node.setAttribute(ATTR_NAME, id);
nodeCache[id] = node;
}
/**
* Finds the node with the supplied React-generated DOM ID.
*
* @param {string} id A React-generated DOM ID.
* @return {DOMElement} DOM node with the suppled `id`.
* @internal
*/
function getNode(id) {
if (!nodeCache.hasOwnProperty(id) || !isValid(nodeCache[id], id)) {
nodeCache[id] = ReactMount.findReactNodeByID(id);
}
return nodeCache[id];
}
/**
* A node is "valid" if it is contained by a currently mounted container.
*
* This means that the node does not have to be contained by a document in
* order to be considered valid.
*
* @param {?DOMElement} node The candidate DOM node.
* @param {string} id The expected ID of the node.
* @return {boolean} Whether the node is contained by a mounted container.
*/
function isValid(node, id) {
if (node) {
("production" !== "development" ? invariant(
internalGetID(node) === id,
'ReactMount: Unexpected modification of `%s`',
ATTR_NAME
) : invariant(internalGetID(node) === id));
var container = ReactMount.findReactContainerForID(id);
if (container && containsNode(container, node)) {
return true;
}
}
return false;
}
/**
* Causes the cache to forget about one React-specific ID.
*
* @param {string} id The ID to forget.
*/
function purgeID(id) {
delete nodeCache[id];
}
var deepestNodeSoFar = null;
function findDeepestCachedAncestorImpl(ancestorID) {
var ancestor = nodeCache[ancestorID];
if (ancestor && isValid(ancestor, ancestorID)) {
deepestNodeSoFar = ancestor;
} else {
// This node isn't populated in the cache, so presumably none of its
// descendants are. Break out of the loop.
return false;
}
}
/**
* Return the deepest cached node whose ID is a prefix of `targetID`.
*/
function findDeepestCachedAncestor(targetID) {
deepestNodeSoFar = null;
ReactInstanceHandles.traverseAncestors(
targetID,
findDeepestCachedAncestorImpl
);
var foundNode = deepestNodeSoFar;
deepestNodeSoFar = null;
return foundNode;
}
/**
* Mounting is the process of initializing a React component by creatings its
* representative DOM elements and inserting them into a supplied `container`.
* Any prior content inside `container` is destroyed in the process.
*
* ReactMount.render(
* component,
* document.getElementById('container')
* );
*
* <div id="container"> <-- Supplied `container`.
* <div data-reactid=".3"> <-- Rendered reactRoot of React
* // ... component.
* </div>
* </div>
*
* Inside of `container`, the first element rendered is the "reactRoot".
*/
var ReactMount = {
/** Exposed for debugging purposes **/
_instancesByReactRootID: instancesByReactRootID,
/**
* This is a hook provided to support rendering React components while
* ensuring that the apparent scroll position of its `container` does not
* change.
*
* @param {DOMElement} container The `container` being rendered into.
* @param {function} renderCallback This must be called once to do the render.
*/
scrollMonitor: function(container, renderCallback) {
renderCallback();
},
/**
* Take a component that's already mounted into the DOM and replace its props
* @param {ReactComponent} prevComponent component instance already in the DOM
* @param {ReactComponent} nextComponent component instance to render
* @param {DOMElement} container container to render into
* @param {?function} callback function triggered on completion
*/
_updateRootComponent: function(
prevComponent,
nextComponent,
container,
callback) {
var nextProps = nextComponent.props;
ReactMount.scrollMonitor(container, function() {
prevComponent.replaceProps(nextProps, callback);
});
if ("production" !== "development") {
// Record the root element in case it later gets transplanted.
rootElementsByReactRootID[getReactRootID(container)] =
getReactRootElementInContainer(container);
}
return prevComponent;
},
/**
* Register a component into the instance map and starts scroll value
* monitoring
* @param {ReactComponent} nextComponent component instance to render
* @param {DOMElement} container container to render into
* @return {string} reactRoot ID prefix
*/
_registerComponent: function(nextComponent, container) {
("production" !== "development" ? invariant(
container && (
container.nodeType === ELEMENT_NODE_TYPE ||
container.nodeType === DOC_NODE_TYPE
),
'_registerComponent(...): Target container is not a DOM element.'
) : invariant(container && (
container.nodeType === ELEMENT_NODE_TYPE ||
container.nodeType === DOC_NODE_TYPE
)));
ReactBrowserEventEmitter.ensureScrollValueMonitoring();
var reactRootID = ReactMount.registerContainer(container);
instancesByReactRootID[reactRootID] = nextComponent;
return reactRootID;
},
/**
* Render a new component into the DOM.
* @param {ReactComponent} nextComponent component instance to render
* @param {DOMElement} container container to render into
* @param {boolean} shouldReuseMarkup if we should skip the markup insertion
* @return {ReactComponent} nextComponent
*/
_renderNewRootComponent: ReactPerf.measure(
'ReactMount',
'_renderNewRootComponent',
function(
nextComponent,
container,
shouldReuseMarkup) {
// Various parts of our code (such as ReactCompositeComponent's
// _renderValidatedComponent) assume that calls to render aren't nested;
// verify that that's the case.
("production" !== "development" ? warning(
ReactCurrentOwner.current == null,
'_renderNewRootComponent(): Render methods should be a pure function ' +
'of props and state; triggering nested component updates from ' +
'render is not allowed. If necessary, trigger nested updates in ' +
'componentDidUpdate.'
) : null);
var componentInstance = instantiateReactComponent(nextComponent, null);
var reactRootID = ReactMount._registerComponent(
componentInstance,
container
);
componentInstance.mountComponentIntoNode(
reactRootID,
container,
shouldReuseMarkup
);
if ("production" !== "development") {
// Record the root element in case it later gets transplanted.
rootElementsByReactRootID[reactRootID] =
getReactRootElementInContainer(container);
}
return componentInstance;
}
),
/**
* Renders a React component into the DOM in the supplied `container`.
*
* If the React component was previously rendered into `container`, this will
* perform an update on it and only mutate the DOM as necessary to reflect the
* latest React component.
*
* @param {ReactElement} nextElement Component element to render.
* @param {DOMElement} container DOM element to render into.
* @param {?function} callback function triggered on completion
* @return {ReactComponent} Component instance rendered in `container`.
*/
render: function(nextElement, container, callback) {
("production" !== "development" ? invariant(
ReactElement.isValidElement(nextElement),
'renderComponent(): Invalid component element.%s',
(
typeof nextElement === 'string' ?
' Instead of passing an element string, make sure to instantiate ' +
'it by passing it to React.createElement.' :
ReactLegacyElement.isValidFactory(nextElement) ?
' Instead of passing a component class, make sure to instantiate ' +
'it by passing it to React.createElement.' :
// Check if it quacks like a element
typeof nextElement.props !== "undefined" ?
' This may be caused by unintentionally loading two independent ' +
'copies of React.' :
''
)
) : invariant(ReactElement.isValidElement(nextElement)));
var prevComponent = instancesByReactRootID[getReactRootID(container)];
if (prevComponent) {
var prevElement = prevComponent._currentElement;
if (shouldUpdateReactComponent(prevElement, nextElement)) {
return ReactMount._updateRootComponent(
prevComponent,
nextElement,
container,
callback
);
} else {
ReactMount.unmountComponentAtNode(container);
}
}
var reactRootElement = getReactRootElementInContainer(container);
var containerHasReactMarkup =
reactRootElement && ReactMount.isRenderedByReact(reactRootElement);
var shouldReuseMarkup = containerHasReactMarkup && !prevComponent;
var component = ReactMount._renderNewRootComponent(
nextElement,
container,
shouldReuseMarkup
);
callback && callback.call(component);
return component;
},
/**
* Constructs a component instance of `constructor` with `initialProps` and
* renders it into the supplied `container`.
*
* @param {function} constructor React component constructor.
* @param {?object} props Initial props of the component instance.
* @param {DOMElement} container DOM element to render into.
* @return {ReactComponent} Component instance rendered in `container`.
*/
constructAndRenderComponent: function(constructor, props, container) {
var element = createElement(constructor, props);
return ReactMount.render(element, container);
},
/**
* Constructs a component instance of `constructor` with `initialProps` and
* renders it into a container node identified by supplied `id`.
*
* @param {function} componentConstructor React component constructor
* @param {?object} props Initial props of the component instance.
* @param {string} id ID of the DOM element to render into.
* @return {ReactComponent} Component instance rendered in the container node.
*/
constructAndRenderComponentByID: function(constructor, props, id) {
var domNode = document.getElementById(id);
("production" !== "development" ? invariant(
domNode,
'Tried to get element with id of "%s" but it is not present on the page.',
id
) : invariant(domNode));
return ReactMount.constructAndRenderComponent(constructor, props, domNode);
},
/**
* Registers a container node into which React components will be rendered.
* This also creates the "reactRoot" ID that will be assigned to the element
* rendered within.
*
* @param {DOMElement} container DOM element to register as a container.
* @return {string} The "reactRoot" ID of elements rendered within.
*/
registerContainer: function(container) {
var reactRootID = getReactRootID(container);
if (reactRootID) {
// If one exists, make sure it is a valid "reactRoot" ID.
reactRootID = ReactInstanceHandles.getReactRootIDFromNodeID(reactRootID);
}
if (!reactRootID) {
// No valid "reactRoot" ID found, create one.
reactRootID = ReactInstanceHandles.createReactRootID();
}
containersByReactRootID[reactRootID] = container;
return reactRootID;
},
/**
* Unmounts and destroys the React component rendered in the `container`.
*
* @param {DOMElement} container DOM element containing a React component.
* @return {boolean} True if a component was found in and unmounted from
* `container`
*/
unmountComponentAtNode: function(container) {
// Various parts of our code (such as ReactCompositeComponent's
// _renderValidatedComponent) assume that calls to render aren't nested;
// verify that that's the case. (Strictly speaking, unmounting won't cause a
// render but we still don't expect to be in a render call here.)
("production" !== "development" ? warning(
ReactCurrentOwner.current == null,
'unmountComponentAtNode(): Render methods should be a pure function of ' +
'props and state; triggering nested component updates from render is ' +
'not allowed. If necessary, trigger nested updates in ' +
'componentDidUpdate.'
) : null);
var reactRootID = getReactRootID(container);
var component = instancesByReactRootID[reactRootID];
if (!component) {
return false;
}
ReactMount.unmountComponentFromNode(component, container);
delete instancesByReactRootID[reactRootID];
delete containersByReactRootID[reactRootID];
if ("production" !== "development") {
delete rootElementsByReactRootID[reactRootID];
}
return true;
},
/**
* Unmounts a component and removes it from the DOM.
*
* @param {ReactComponent} instance React component instance.
* @param {DOMElement} container DOM element to unmount from.
* @final
* @internal
* @see {ReactMount.unmountComponentAtNode}
*/
unmountComponentFromNode: function(instance, container) {
instance.unmountComponent();
if (container.nodeType === DOC_NODE_TYPE) {
container = container.documentElement;
}
// http://jsperf.com/emptying-a-node
while (container.lastChild) {
container.removeChild(container.lastChild);
}
},
/**
* Finds the container DOM element that contains React component to which the
* supplied DOM `id` belongs.
*
* @param {string} id The ID of an element rendered by a React component.
* @return {?DOMElement} DOM element that contains the `id`.
*/
findReactContainerForID: function(id) {
var reactRootID = ReactInstanceHandles.getReactRootIDFromNodeID(id);
var container = containersByReactRootID[reactRootID];
if ("production" !== "development") {
var rootElement = rootElementsByReactRootID[reactRootID];
if (rootElement && rootElement.parentNode !== container) {
("production" !== "development" ? invariant(
// Call internalGetID here because getID calls isValid which calls
// findReactContainerForID (this function).
internalGetID(rootElement) === reactRootID,
'ReactMount: Root element ID differed from reactRootID.'
) : invariant(// Call internalGetID here because getID calls isValid which calls
// findReactContainerForID (this function).
internalGetID(rootElement) === reactRootID));
var containerChild = container.firstChild;
if (containerChild &&
reactRootID === internalGetID(containerChild)) {
// If the container has a new child with the same ID as the old
// root element, then rootElementsByReactRootID[reactRootID] is
// just stale and needs to be updated. The case that deserves a
// warning is when the container is empty.
rootElementsByReactRootID[reactRootID] = containerChild;
} else {
console.warn(
'ReactMount: Root element has been removed from its original ' +
'container. New container:', rootElement.parentNode
);
}
}
}
return container;
},
/**
* Finds an element rendered by React with the supplied ID.
*
* @param {string} id ID of a DOM node in the React component.
* @return {DOMElement} Root DOM node of the React component.
*/
findReactNodeByID: function(id) {
var reactRoot = ReactMount.findReactContainerForID(id);
return ReactMount.findComponentRoot(reactRoot, id);
},
/**
* True if the supplied `node` is rendered by React.
*
* @param {*} node DOM Element to check.
* @return {boolean} True if the DOM Element appears to be rendered by React.
* @internal
*/
isRenderedByReact: function(node) {
if (node.nodeType !== 1) {
// Not a DOMElement, therefore not a React component
return false;
}
var id = ReactMount.getID(node);
return id ? id.charAt(0) === SEPARATOR : false;
},
/**
* Traverses up the ancestors of the supplied node to find a node that is a
* DOM representation of a React component.
*
* @param {*} node
* @return {?DOMEventTarget}
* @internal
*/
getFirstReactDOM: function(node) {
var current = node;
while (current && current.parentNode !== current) {
if (ReactMount.isRenderedByReact(current)) {
return current;
}
current = current.parentNode;
}
return null;
},
/**
* Finds a node with the supplied `targetID` inside of the supplied
* `ancestorNode`. Exploits the ID naming scheme to perform the search
* quickly.
*
* @param {DOMEventTarget} ancestorNode Search from this root.
* @pararm {string} targetID ID of the DOM representation of the component.
* @return {DOMEventTarget} DOM node with the supplied `targetID`.
* @internal
*/
findComponentRoot: function(ancestorNode, targetID) {
var firstChildren = findComponentRootReusableArray;
var childIndex = 0;
var deepestAncestor = findDeepestCachedAncestor(targetID) || ancestorNode;
firstChildren[0] = deepestAncestor.firstChild;
firstChildren.length = 1;
while (childIndex < firstChildren.length) {
var child = firstChildren[childIndex++];
var targetChild;
while (child) {
var childID = ReactMount.getID(child);
if (childID) {
// Even if we find the node we're looking for, we finish looping
// through its siblings to ensure they're cached so that we don't have
// to revisit this node again. Otherwise, we make n^2 calls to getID
// when visiting the many children of a single node in order.
if (targetID === childID) {
targetChild = child;
} else if (ReactInstanceHandles.isAncestorIDOf(childID, targetID)) {
// If we find a child whose ID is an ancestor of the given ID,
// then we can be sure that we only want to search the subtree
// rooted at this child, so we can throw out the rest of the
// search state.
firstChildren.length = childIndex = 0;
firstChildren.push(child.firstChild);
}
} else {
// If this child had no ID, then there's a chance that it was
// injected automatically by the browser, as when a `<table>`
// element sprouts an extra `<tbody>` child as a side effect of
// `.innerHTML` parsing. Optimistically continue down this
// branch, but not before examining the other siblings.
firstChildren.push(child.firstChild);
}
child = child.nextSibling;
}
if (targetChild) {
// Emptying firstChildren/findComponentRootReusableArray is
// not necessary for correctness, but it helps the GC reclaim
// any nodes that were left at the end of the search.
firstChildren.length = 0;
return targetChild;
}
}
firstChildren.length = 0;
("production" !== "development" ? invariant(
false,
'findComponentRoot(..., %s): Unable to find element. This probably ' +
'means the DOM was unexpectedly mutated (e.g., by the browser), ' +
'usually due to forgetting a <tbody> when using tables, nesting tags ' +
'like <form>,
'];
var svgWrap = [1, '<svg>', ''];
var markupWrap = {
'*': [1, '?<div>', '
'],
'area': [1, '<map>', ''],
'col': [2, '<table>
', '
'],
'legend': [1, '<fieldset>', ''],
'param': [1, '<object>', ''],
'tr': [2, '<table>', ''],
'optgroup': selectWrap,
'option': selectWrap,
'caption': tableWrap,
'colgroup': tableWrap,
'tbody': tableWrap,
'tfoot': tableWrap,
'thead': tableWrap,
'td': trWrap,
'th': trWrap,
'circle': svgWrap,
'defs': svgWrap,
'ellipse': svgWrap,
'g': svgWrap,
'line': svgWrap,
'linearGradient': svgWrap,
'path': svgWrap,
'polygon': svgWrap,
'polyline': svgWrap,
'radialGradient': svgWrap,
'rect': svgWrap,
'stop': svgWrap,
'text': svgWrap
};
/**
* Gets the markup wrap configuration for the supplied `nodeName`.
*
* NOTE: This lazily detects which wraps are necessary for the current browser.
*
* @param {string} nodeName Lowercase `nodeName`.
* @return {?array} Markup wrap configuration, if applicable.
*/
function getMarkupWrap(nodeName) {
("production" !== "development" ? invariant(!!dummyNode, 'Markup wrapping node not initialized') : invariant(!!dummyNode));
if (!markupWrap.hasOwnProperty(nodeName)) {
nodeName = '*';
}
if (!shouldWrap.hasOwnProperty(nodeName)) {
if (nodeName === '*') {
dummyNode.innerHTML = '<link />';
} else {
dummyNode.innerHTML = '<' + nodeName + '>' + nodeName + '>';
}
shouldWrap[nodeName] = !dummyNode.firstChild;
}
return shouldWrap[nodeName] ? markupWrap[nodeName] : null;
}
module.exports = getMarkupWrap;
},{"./ExecutionEnvironment":23,"./invariant":140}],133:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule getNodeForCharacterOffset
*/
"use strict";
/**
* Given any node return the first leaf node without children.
*
* @param {DOMElement|DOMTextNode} node
* @return {DOMElement|DOMTextNode}
*/
function getLeafNode(node) {
while (node && node.firstChild) {
node = node.firstChild;
}
return node;
}
/**
* Get the next sibling within a container. This will walk up the
* DOM if a node's siblings have been exhausted.
*
* @param {DOMElement|DOMTextNode} node
* @return {?DOMElement|DOMTextNode}
*/
function getSiblingNode(node) {
while (node) {
if (node.nextSibling) {
return node.nextSibling;
}
node = node.parentNode;
}
}
/**
* Get object describing the nodes which contain characters at offset.
*
* @param {DOMElement|DOMTextNode} root
* @param {number} offset
* @return {?object}
*/
function getNodeForCharacterOffset(root, offset) {
var node = getLeafNode(root);
var nodeStart = 0;
var nodeEnd = 0;
while (node) {
if (node.nodeType == 3) {
nodeEnd = nodeStart + node.textContent.length;
if (nodeStart <= offset && nodeEnd >= offset) {
return {
node: node,
offset: offset - nodeStart
};
}
nodeStart = nodeEnd;
}
node = getLeafNode(getSiblingNode(node));
}
}
module.exports = getNodeForCharacterOffset;
},{}],134:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule getReactRootElementInContainer
*/
"use strict";
var DOC_NODE_TYPE = 9;
/**
* @param {DOMElement|DOMDocument} container DOM element that may contain
* a React component
* @return {?*} DOM element that may have the reactRoot ID, or null.
*/
function getReactRootElementInContainer(container) {
if (!container) {
return null;
}
if (container.nodeType === DOC_NODE_TYPE) {
return container.documentElement;
} else {
return container.firstChild;
}
}
module.exports = getReactRootElementInContainer;
},{}],135:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule getTextContentAccessor
*/
"use strict";
var ExecutionEnvironment = _dereq_("./ExecutionEnvironment");
var contentKey = null;
/**
* Gets the key used to access text content on a DOM node.
*
* @return {?string} Key used to access text content.
* @internal
*/
function getTextContentAccessor() {
if (!contentKey && ExecutionEnvironment.canUseDOM) {
// Prefer textContent to innerText because many browsers support both but
// SVG <text> elements don't support innerText even when
does.
contentKey = 'textContent' in document.documentElement ?
'textContent' :
'innerText';
}
return contentKey;
}
module.exports = getTextContentAccessor;
},{"./ExecutionEnvironment":23}],136:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule getUnboundedScrollPosition
* @typechecks
*/
"use strict";
/**
* Gets the scroll position of the supplied element or window.
*
* The return values are unbounded, unlike `getScrollPosition`. This means they
* may be negative or exceed the element boundaries (which is possible using
* inertial scrolling).
*
* @param {DOMWindow|DOMElement} scrollable
* @return {object} Map with `x` and `y` keys.
*/
function getUnboundedScrollPosition(scrollable) {
if (scrollable === window) {
return {
x: window.pageXOffset || document.documentElement.scrollLeft,
y: window.pageYOffset || document.documentElement.scrollTop
};
}
return {
x: scrollable.scrollLeft,
y: scrollable.scrollTop
};
}
module.exports = getUnboundedScrollPosition;
},{}],137:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule hyphenate
* @typechecks
*/
var _uppercasePattern = /([A-Z])/g;
/**
* Hyphenates a camelcased string, for example:
*
* > hyphenate('backgroundColor')
* < "background-color"
*
* For CSS style names, use `hyphenateStyleName` instead which works properly
* with all vendor prefixes, including `ms`.
*
* @param {string} string
* @return {string}
*/
function hyphenate(string) {
return string.replace(_uppercasePattern, '-$1').toLowerCase();
}
module.exports = hyphenate;
},{}],138:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule hyphenateStyleName
* @typechecks
*/
"use strict";
var hyphenate = _dereq_("./hyphenate");
var msPattern = /^ms-/;
/**
* Hyphenates a camelcased CSS property name, for example:
*
* > hyphenateStyleName('backgroundColor')
* < "background-color"
* > hyphenateStyleName('MozTransition')
* < "-moz-transition"
* > hyphenateStyleName('msTransition')
* < "-ms-transition"
*
* As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix
* is converted to `-ms-`.
*
* @param {string} string
* @return {string}
*/
function hyphenateStyleName(string) {
return hyphenate(string).replace(msPattern, '-ms-');
}
module.exports = hyphenateStyleName;
},{"./hyphenate":137}],139:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule instantiateReactComponent
* @typechecks static-only
*/
"use strict";
var warning = _dereq_("./warning");
var ReactElement = _dereq_("./ReactElement");
var ReactLegacyElement = _dereq_("./ReactLegacyElement");
var ReactNativeComponent = _dereq_("./ReactNativeComponent");
var ReactEmptyComponent = _dereq_("./ReactEmptyComponent");
/**
* Given an `element` create an instance that will actually be mounted.
*
* @param {object} element
* @param {*} parentCompositeType The composite type that resolved this.
* @return {object} A new instance of the element's constructor.
* @protected
*/
function instantiateReactComponent(element, parentCompositeType) {
var instance;
if ("production" !== "development") {
("production" !== "development" ? warning(
element && (typeof element.type === 'function' ||
typeof element.type === 'string'),
'Only functions or strings can be mounted as React components.'
) : null);
// Resolve mock instances
if (element.type._mockedReactClassConstructor) {
// If this is a mocked class, we treat the legacy factory as if it was the
// class constructor for future proofing unit tests. Because this might
// be mocked as a legacy factory, we ignore any warnings triggerd by
// this temporary hack.
ReactLegacyElement._isLegacyCallWarningEnabled = false;
try {
instance = new element.type._mockedReactClassConstructor(
element.props
);
} finally {
ReactLegacyElement._isLegacyCallWarningEnabled = true;
}
// If the mock implementation was a legacy factory, then it returns a
// element. We need to turn this into a real component instance.
if (ReactElement.isValidElement(instance)) {
instance = new instance.type(instance.props);
}
var render = instance.render;
if (!render) {
// For auto-mocked factories, the prototype isn't shimmed and therefore
// there is no render function on the instance. We replace the whole
// component with an empty component instance instead.
element = ReactEmptyComponent.getEmptyComponent();
} else {
if (render._isMockFunction && !render._getMockImplementation()) {
// Auto-mocked components may have a prototype with a mocked render
// function. For those, we'll need to mock the result of the render
// since we consider undefined to be invalid results from render.
render.mockImplementation(
ReactEmptyComponent.getEmptyComponent
);
}
instance.construct(element);
return instance;
}
}
}
// Special case string values
if (typeof element.type === 'string') {
instance = ReactNativeComponent.createInstanceForTag(
element.type,
element.props,
parentCompositeType
);
} else {
// Normal case for non-mocks and non-strings
instance = new element.type(element.props);
}
if ("production" !== "development") {
("production" !== "development" ? warning(
typeof instance.construct === 'function' &&
typeof instance.mountComponent === 'function' &&
typeof instance.receiveComponent === 'function',
'Only React Components can be mounted.'
) : null);
}
// This actually sets up the internal instance. This will become decoupled
// from the public instance in a future diff.
instance.construct(element);
return instance;
}
module.exports = instantiateReactComponent;
},{"./ReactElement":58,"./ReactEmptyComponent":60,"./ReactLegacyElement":67,"./ReactNativeComponent":73,"./warning":160}],140:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule invariant
*/
"use strict";
/**
* Use invariant() to assert state which your program assumes to be true.
*
* Provide sprintf-style format (only %s is supported) and arguments
* to provide information about what broke and what you were
* expecting.
*
* The invariant message will be stripped in production, but the invariant
* will remain to ensure logic does not differ in production.
*/
var invariant = function(condition, format, a, b, c, d, e, f) {
if ("production" !== "development") {
if (format === undefined) {
throw new Error('invariant requires an error message argument');
}
}
if (!condition) {
var error;
if (format === undefined) {
error = new Error(
'Minified exception occurred; use the non-minified dev environment ' +
'for the full error message and additional helpful warnings.'
);
} else {
var args = [a, b, c, d, e, f];
var argIndex = 0;
error = new Error(
'Invariant Violation: ' +
format.replace(/%s/g, function() { return args[argIndex++]; })
);
}
error.framesToPop = 1; // we don't care about invariant's own frame
throw error;
}
};
module.exports = invariant;
},{}],141:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule isEventSupported
*/
"use strict";
var ExecutionEnvironment = _dereq_("./ExecutionEnvironment");
var useHasFeature;
if (ExecutionEnvironment.canUseDOM) {
useHasFeature =
document.implementation &&
document.implementation.hasFeature &&
// always returns true in newer browsers as per the standard.
// @see http://dom.spec.whatwg.org/#dom-domimplementation-hasfeature
document.implementation.hasFeature('', '') !== true;
}
/**
* Checks if an event is supported in the current execution environment.
*
* NOTE: This will not work correctly for non-generic events such as `change`,
* `reset`, `load`, `error`, and `select`.
*
* Borrows from Modernizr.
*
* @param {string} eventNameSuffix Event name, e.g. "click".
* @param {?boolean} capture Check if the capture phase is supported.
* @return {boolean} True if the event is supported.
* @internal
* @license Modernizr 3.0.0pre (Custom Build) | MIT
*/
function isEventSupported(eventNameSuffix, capture) {
if (!ExecutionEnvironment.canUseDOM ||
capture && !('addEventListener' in document)) {
return false;
}
var eventName = 'on' + eventNameSuffix;
var isSupported = eventName in document;
if (!isSupported) {
var element = document.createElement('div');
element.setAttribute(eventName, 'return;');
isSupported = typeof element[eventName] === 'function';
}
if (!isSupported && useHasFeature && eventNameSuffix === 'wheel') {
// This is the only way to test support for the `wheel` event in IE9+.
isSupported = document.implementation.hasFeature('Events.wheel', '3.0');
}
return isSupported;
}
module.exports = isEventSupported;
},{"./ExecutionEnvironment":23}],142:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule isNode
* @typechecks
*/
/**
* @param {*} object The object to check.
* @return {boolean} Whether or not the object is a DOM node.
*/
function isNode(object) {
return !!(object && (
typeof Node === 'function' ? object instanceof Node :
typeof object === 'object' &&
typeof object.nodeType === 'number' &&
typeof object.nodeName === 'string'
));
}
module.exports = isNode;
},{}],143:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule isTextInputElement
*/
"use strict";
/**
* @see http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary
*/
var supportedInputTypes = {
'color': true,
'date': true,
'datetime': true,
'datetime-local': true,
'email': true,
'month': true,
'number': true,
'password': true,
'range': true,
'search': true,
'tel': true,
'text': true,
'time': true,
'url': true,
'week': true
};
function isTextInputElement(elem) {
return elem && (
(elem.nodeName === 'INPUT' && supportedInputTypes[elem.type]) ||
elem.nodeName === 'TEXTAREA'
);
}
module.exports = isTextInputElement;
},{}],144:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule isTextNode
* @typechecks
*/
var isNode = _dereq_("./isNode");
/**
* @param {*} object The object to check.
* @return {boolean} Whether or not the object is a DOM text node.
*/
function isTextNode(object) {
return isNode(object) && object.nodeType == 3;
}
module.exports = isTextNode;
},{"./isNode":142}],145:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule joinClasses
* @typechecks static-only
*/
"use strict";
/**
* Combines multiple className strings into one.
* http://jsperf.com/joinclasses-args-vs-array
*
* @param {...?string} classes
* @return {string}
*/
function joinClasses(className/*, ... */) {
if (!className) {
className = '';
}
var nextClass;
var argLength = arguments.length;
if (argLength > 1) {
for (var ii = 1; ii < argLength; ii++) {
nextClass = arguments[ii];
if (nextClass) {
className = (className ? className + ' ' : '') + nextClass;
}
}
}
return className;
}
module.exports = joinClasses;
},{}],146:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule keyMirror
* @typechecks static-only
*/
"use strict";
var invariant = _dereq_("./invariant");
/**
* Constructs an enumeration with keys equal to their value.
*
* For example:
*
* var COLORS = keyMirror({blue: null, red: null});
* var myColor = COLORS.blue;
* var isColorValid = !!COLORS[myColor];
*
* The last line could not be performed if the values of the generated enum were
* not equal to their keys.
*
* Input: {key1: val1, key2: val2}
* Output: {key1: key1, key2: key2}
*
* @param {object} obj
* @return {object}
*/
var keyMirror = function(obj) {
var ret = {};
var key;
("production" !== "development" ? invariant(
obj instanceof Object && !Array.isArray(obj),
'keyMirror(...): Argument must be an object.'
) : invariant(obj instanceof Object && !Array.isArray(obj)));
for (key in obj) {
if (!obj.hasOwnProperty(key)) {
continue;
}
ret[key] = key;
}
return ret;
};
module.exports = keyMirror;
},{"./invariant":140}],147:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule keyOf
*/
/**
* Allows extraction of a minified key. Let's the build system minify keys
* without loosing the ability to dynamically use key strings as values
* themselves. Pass in an object with a single key/val pair and it will return
* you the string key of that single record. Suppose you want to grab the
* value for a key 'className' inside of an object. Key/val minification may
* have aliased that key to be 'xa12'. keyOf({className: null}) will return
* 'xa12' in that case. Resolve keys you want to use once at startup time, then
* reuse those resolutions.
*/
var keyOf = function(oneKeyObj) {
var key;
for (key in oneKeyObj) {
if (!oneKeyObj.hasOwnProperty(key)) {
continue;
}
return key;
}
return null;
};
module.exports = keyOf;
},{}],148:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule mapObject
*/
'use strict';
var hasOwnProperty = Object.prototype.hasOwnProperty;
/**
* Executes the provided `callback` once for each enumerable own property in the
* object and constructs a new object from the results. The `callback` is
* invoked with three arguments:
*
* - the property value
* - the property name
* - the object being traversed
*
* Properties that are added after the call to `mapObject` will not be visited
* by `callback`. If the values of existing properties are changed, the value
* passed to `callback` will be the value at the time `mapObject` visits them.
* Properties that are deleted before being visited are not visited.
*
* @grep function objectMap()
* @grep function objMap()
*
* @param {?object} object
* @param {function} callback
* @param {*} context
* @return {?object}
*/
function mapObject(object, callback, context) {
if (!object) {
return null;
}
var result = {};
for (var name in object) {
if (hasOwnProperty.call(object, name)) {
result[name] = callback.call(context, object[name], name, object);
}
}
return result;
}
module.exports = mapObject;
},{}],149:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule memoizeStringOnly
* @typechecks static-only
*/
"use strict";
/**
* Memoizes the return value of a function that accepts one string argument.
*
* @param {function} callback
* @return {function}
*/
function memoizeStringOnly(callback) {
var cache = {};
return function(string) {
if (cache.hasOwnProperty(string)) {
return cache[string];
} else {
return cache[string] = callback.call(this, string);
}
};
}
module.exports = memoizeStringOnly;
},{}],150:[function(_dereq_,module,exports){
/**
* Copyright 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule monitorCodeUse
*/
"use strict";
var invariant = _dereq_("./invariant");
/**
* Provides open-source compatible instrumentation for monitoring certain API
* uses before we're ready to issue a warning or refactor. It accepts an event
* name which may only contain the characters [a-z0-9_] and an optional data
* object with further information.
*/
function monitorCodeUse(eventName, data) {
("production" !== "development" ? invariant(
eventName && !/[^a-z0-9_]/.test(eventName),
'You must provide an eventName using only the characters [a-z0-9_]'
) : invariant(eventName && !/[^a-z0-9_]/.test(eventName)));
}
module.exports = monitorCodeUse;
},{"./invariant":140}],151:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule onlyChild
*/
"use strict";
var ReactElement = _dereq_("./ReactElement");
var invariant = _dereq_("./invariant");
/**
* Returns the first child in a collection of children and verifies that there
* is only one child in the collection. The current implementation of this
* function assumes that a single child gets passed without a wrapper, but the
* purpose of this helper function is to abstract away the particular structure
* of children.
*
* @param {?object} children Child collection structure.
* @return {ReactComponent} The first and only `ReactComponent` contained in the
* structure.
*/
function onlyChild(children) {
("production" !== "development" ? invariant(
ReactElement.isValidElement(children),
'onlyChild must be passed a children with exactly one child.'
) : invariant(ReactElement.isValidElement(children)));
return children;
}
module.exports = onlyChild;
},{"./ReactElement":58,"./invariant":140}],152:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule performance
* @typechecks
*/
"use strict";
var ExecutionEnvironment = _dereq_("./ExecutionEnvironment");
var performance;
if (ExecutionEnvironment.canUseDOM) {
performance =
window.performance ||
window.msPerformance ||
window.webkitPerformance;
}
module.exports = performance || {};
},{"./ExecutionEnvironment":23}],153:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule performanceNow
* @typechecks
*/
var performance = _dereq_("./performance");
/**
* Detect if we can use `window.performance.now()` and gracefully fallback to
* `Date.now()` if it doesn't exist. We need to support Firefox < 15 for now
* because of Facebook's testing infrastructure.
*/
if (!performance || !performance.now) {
performance = Date;
}
var performanceNow = performance.now.bind(performance);
module.exports = performanceNow;
},{"./performance":152}],154:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule setInnerHTML
*/
"use strict";
var ExecutionEnvironment = _dereq_("./ExecutionEnvironment");
var WHITESPACE_TEST = /^[ \r\n\t\f]/;
var NONVISIBLE_TEST = /<(!--|link|noscript|meta|script|style)[ \r\n\t\f\/>]/;
/**
* Set the innerHTML property of a node, ensuring that whitespace is preserved
* even in IE8.
*
* @param {DOMElement} node
* @param {string} html
* @internal
*/
var setInnerHTML = function(node, html) {
node.innerHTML = html;
};
if (ExecutionEnvironment.canUseDOM) {
// 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);
}
// 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 (WHITESPACE_TEST.test(html) ||
html[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;
// deleteData leaves an empty `TextNode` which offsets the index of all
// children. Definitely want to avoid this.
var textNode = node.firstChild;
if (textNode.data.length === 1) {
node.removeChild(textNode);
} else {
textNode.deleteData(0, 1);
}
} else {
node.innerHTML = html;
}
};
}
}
module.exports = setInnerHTML;
},{"./ExecutionEnvironment":23}],155:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule shallowEqual
*/
"use strict";
/**
* Performs equality by iterating through keys on an object and returning
* false when any key has values which are not strictly equal between
* objA and objB. Returns true when the values of all keys are strictly equal.
*
* @return {boolean}
*/
function shallowEqual(objA, objB) {
if (objA === objB) {
return true;
}
var key;
// Test for A's keys different from B.
for (key in objA) {
if (objA.hasOwnProperty(key) &&
(!objB.hasOwnProperty(key) || objA[key] !== objB[key])) {
return false;
}
}
// Test for B's keys missing from A.
for (key in objB) {
if (objB.hasOwnProperty(key) && !objA.hasOwnProperty(key)) {
return false;
}
}
return true;
}
module.exports = shallowEqual;
},{}],156:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule shouldUpdateReactComponent
* @typechecks static-only
*/
"use strict";
/**
* Given a `prevElement` and `nextElement`, determines if the existing
* instance should be updated as opposed to being destroyed or replaced by a new
* instance. Both arguments are elements. This ensures that this logic can
* operate on stateless trees without any backing instance.
*
* @param {?object} prevElement
* @param {?object} nextElement
* @return {boolean} True if the existing instance should be updated.
* @protected
*/
function shouldUpdateReactComponent(prevElement, nextElement) {
if (prevElement && nextElement &&
prevElement.type === nextElement.type &&
prevElement.key === nextElement.key &&
prevElement._owner === nextElement._owner) {
return true;
}
return false;
}
module.exports = shouldUpdateReactComponent;
},{}],157:[function(_dereq_,module,exports){
/**
* Copyright 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule toArray
* @typechecks
*/
var invariant = _dereq_("./invariant");
/**
* Convert array-like objects to arrays.
*
* This API assumes the caller knows the contents of the data type. For less
* well defined inputs use createArrayFrom.
*
* @param {object|function|filelist} obj
* @return {array}
*/
function toArray(obj) {
var length = obj.length;
// Some browse builtin objects can report typeof 'function' (e.g. NodeList in
// old versions of Safari).
("production" !== "development" ? invariant(
!Array.isArray(obj) &&
(typeof obj === 'object' || typeof obj === 'function'),
'toArray: Array-like object expected'
) : invariant(!Array.isArray(obj) &&
(typeof obj === 'object' || typeof obj === 'function')));
("production" !== "development" ? invariant(
typeof length === 'number',
'toArray: Object needs a length property'
) : invariant(typeof length === 'number'));
("production" !== "development" ? invariant(
length === 0 ||
(length - 1) in obj,
'toArray: Object should have keys for indices'
) : invariant(length === 0 ||
(length - 1) in obj));
// Old IE doesn't give collections access to hasOwnProperty. Assume inputs
// without method will throw during the slice call and skip straight to the
// fallback.
if (obj.hasOwnProperty) {
try {
return Array.prototype.slice.call(obj);
} catch (e) {
// IE < 9 does not support Array#slice on collections objects
}
}
// Fall back to copying key by key. This assumes all keys have a value,
// so will not preserve sparsely populated inputs.
var ret = Array(length);
for (var ii = 0; ii < length; ii++) {
ret[ii] = obj[ii];
}
return ret;
}
module.exports = toArray;
},{"./invariant":140}],158:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule traverseAllChildren
*/
"use strict";
var ReactElement = _dereq_("./ReactElement");
var ReactInstanceHandles = _dereq_("./ReactInstanceHandles");
var invariant = _dereq_("./invariant");
var SEPARATOR = ReactInstanceHandles.SEPARATOR;
var SUBSEPARATOR = ':';
/**
* TODO: Test that:
* 1. `mapChildren` transforms strings and numbers into `ReactTextComponent`.
* 2. it('should fail when supplied duplicate key', function() {
* 3. That a single child and an array with one item have the same key pattern.
* });
*/
var userProvidedKeyEscaperLookup = {
'=': '=0',
'.': '=1',
':': '=2'
};
var userProvidedKeyEscapeRegex = /[=.:]/g;
function userProvidedKeyEscaper(match) {
return userProvidedKeyEscaperLookup[match];
}
/**
* Generate a key string that identifies a component within a set.
*
* @param {*} component A component that could contain a manual key.
* @param {number} index Index that is used if a manual key is not provided.
* @return {string}
*/
function getComponentKey(component, index) {
if (component && component.key != null) {
// Explicit key
return wrapUserProvidedKey(component.key);
}
// Implicit key determined by the index in the set
return index.toString(36);
}
/**
* Escape a component key so that it is safe to use in a reactid.
*
* @param {*} key Component key to be escaped.
* @return {string} An escaped string.
*/
function escapeUserProvidedKey(text) {
return ('' + text).replace(
userProvidedKeyEscapeRegex,
userProvidedKeyEscaper
);
}
/**
* Wrap a `key` value explicitly provided by the user to distinguish it from
* implicitly-generated keys generated by a component's index in its parent.
*
* @param {string} key Value of a user-provided `key` attribute
* @return {string}
*/
function wrapUserProvidedKey(key) {
return '$' + escapeUserProvidedKey(key);
}
/**
* @param {?*} children Children tree container.
* @param {!string} nameSoFar Name of the key path so far.
* @param {!number} indexSoFar Number of children encountered until this point.
* @param {!function} callback Callback to invoke with each child found.
* @param {?*} traverseContext Used to pass information throughout the traversal
* process.
* @return {!number} The number of children in this subtree.
*/
var traverseAllChildrenImpl =
function(children, nameSoFar, indexSoFar, callback, traverseContext) {
var nextName, nextIndex;
var subtreeCount = 0; // Count of children found in the current subtree.
if (Array.isArray(children)) {
for (var i = 0; i < children.length; i++) {
var child = children[i];
nextName = (
nameSoFar +
(nameSoFar ? SUBSEPARATOR : SEPARATOR) +
getComponentKey(child, i)
);
nextIndex = indexSoFar + subtreeCount;
subtreeCount += traverseAllChildrenImpl(
child,
nextName,
nextIndex,
callback,
traverseContext
);
}
} else {
var type = typeof children;
var isOnlyChild = nameSoFar === '';
// If it's the only child, treat the name as if it was wrapped in an array
// so that it's consistent if the number of children grows
var storageName =
isOnlyChild ? SEPARATOR + getComponentKey(children, 0) : nameSoFar;
if (children == null || type === 'boolean') {
// All of the above are perceived as null.
callback(traverseContext, null, storageName, indexSoFar);
subtreeCount = 1;
} else if (type === 'string' || type === 'number' ||
ReactElement.isValidElement(children)) {
callback(traverseContext, children, storageName, indexSoFar);
subtreeCount = 1;
} else if (type === 'object') {
("production" !== "development" ? invariant(
!children || children.nodeType !== 1,
'traverseAllChildren(...): Encountered an invalid child; DOM ' +
'elements are not valid children of React components.'
) : invariant(!children || children.nodeType !== 1));
for (var key in children) {
if (children.hasOwnProperty(key)) {
nextName = (
nameSoFar + (nameSoFar ? SUBSEPARATOR : SEPARATOR) +
wrapUserProvidedKey(key) + SUBSEPARATOR +
getComponentKey(children[key], 0)
);
nextIndex = indexSoFar + subtreeCount;
subtreeCount += traverseAllChildrenImpl(
children[key],
nextName,
nextIndex,
callback,
traverseContext
);
}
}
}
}
return subtreeCount;
};
/**
* Traverses children that are typically specified as `props.children`, but
* might also be specified through attributes:
*
* - `traverseAllChildren(this.props.children, ...)`
* - `traverseAllChildren(this.props.leftPanelChildren, ...)`
*
* The `traverseContext` is an optional argument that is passed through the
* entire traversal. It can be used to store accumulations or anything else that
* the callback might find relevant.
*
* @param {?*} children Children tree object.
* @param {!function} callback To invoke upon traversing each child.
* @param {?*} traverseContext Context for traversal.
* @return {!number} The number of children in this subtree.
*/
function traverseAllChildren(children, callback, traverseContext) {
if (children == null) {
return 0;
}
return traverseAllChildrenImpl(children, '', 0, callback, traverseContext);
}
module.exports = traverseAllChildren;
},{"./ReactElement":58,"./ReactInstanceHandles":66,"./invariant":140}],159:[function(_dereq_,module,exports){
/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule update
*/
"use strict";
var assign = _dereq_("./Object.assign");
var keyOf = _dereq_("./keyOf");
var invariant = _dereq_("./invariant");
function shallowCopy(x) {
if (Array.isArray(x)) {
return x.concat();
} else if (x && typeof x === 'object') {
return assign(new x.constructor(), x);
} else {
return x;
}
}
var COMMAND_PUSH = keyOf({$push: null});
var COMMAND_UNSHIFT = keyOf({$unshift: null});
var COMMAND_SPLICE = keyOf({$splice: null});
var COMMAND_SET = keyOf({$set: null});
var COMMAND_MERGE = keyOf({$merge: null});
var COMMAND_APPLY = keyOf({$apply: null});
var ALL_COMMANDS_LIST = [
COMMAND_PUSH,
COMMAND_UNSHIFT,
COMMAND_SPLICE,
COMMAND_SET,
COMMAND_MERGE,
COMMAND_APPLY
];
var ALL_COMMANDS_SET = {};
ALL_COMMANDS_LIST.forEach(function(command) {
ALL_COMMANDS_SET[command] = true;
});
function invariantArrayCase(value, spec, command) {
("production" !== "development" ? invariant(
Array.isArray(value),
'update(): expected target of %s to be an array; got %s.',
command,
value
) : invariant(Array.isArray(value)));
var specValue = spec[command];
("production" !== "development" ? invariant(
Array.isArray(specValue),
'update(): expected spec of %s to be an array; got %s. ' +
'Did you forget to wrap your parameter in an array?',
command,
specValue
) : invariant(Array.isArray(specValue)));
}
function update(value, spec) {
("production" !== "development" ? invariant(
typeof spec === 'object',
'update(): You provided a key path to update() that did not contain one ' +
'of %s. Did you forget to include {%s: ...}?',
ALL_COMMANDS_LIST.join(', '),
COMMAND_SET
) : invariant(typeof spec === 'object'));
if (spec.hasOwnProperty(COMMAND_SET)) {
("production" !== "development" ? invariant(
Object.keys(spec).length === 1,
'Cannot have more than one key in an object with %s',
COMMAND_SET
) : invariant(Object.keys(spec).length === 1));
return spec[COMMAND_SET];
}
var nextValue = shallowCopy(value);
if (spec.hasOwnProperty(COMMAND_MERGE)) {
var mergeObj = spec[COMMAND_MERGE];
("production" !== "development" ? invariant(
mergeObj && typeof mergeObj === 'object',
'update(): %s expects a spec of type \'object\'; got %s',
COMMAND_MERGE,
mergeObj
) : invariant(mergeObj && typeof mergeObj === 'object'));
("production" !== "development" ? invariant(
nextValue && typeof nextValue === 'object',
'update(): %s expects a target of type \'object\'; got %s',
COMMAND_MERGE,
nextValue
) : invariant(nextValue && typeof nextValue === 'object'));
assign(nextValue, spec[COMMAND_MERGE]);
}
if (spec.hasOwnProperty(COMMAND_PUSH)) {
invariantArrayCase(value, spec, COMMAND_PUSH);
spec[COMMAND_PUSH].forEach(function(item) {
nextValue.push(item);
});
}
if (spec.hasOwnProperty(COMMAND_UNSHIFT)) {
invariantArrayCase(value, spec, COMMAND_UNSHIFT);
spec[COMMAND_UNSHIFT].forEach(function(item) {
nextValue.unshift(item);
});
}
if (spec.hasOwnProperty(COMMAND_SPLICE)) {
("production" !== "development" ? invariant(
Array.isArray(value),
'Expected %s target to be an array; got %s',
COMMAND_SPLICE,
value
) : invariant(Array.isArray(value)));
("production" !== "development" ? invariant(
Array.isArray(spec[COMMAND_SPLICE]),
'update(): expected spec of %s to be an array of arrays; got %s. ' +
'Did you forget to wrap your parameters in an array?',
COMMAND_SPLICE,
spec[COMMAND_SPLICE]
) : invariant(Array.isArray(spec[COMMAND_SPLICE])));
spec[COMMAND_SPLICE].forEach(function(args) {
("production" !== "development" ? invariant(
Array.isArray(args),
'update(): expected spec of %s to be an array of arrays; got %s. ' +
'Did you forget to wrap your parameters in an array?',
COMMAND_SPLICE,
spec[COMMAND_SPLICE]
) : invariant(Array.isArray(args)));
nextValue.splice.apply(nextValue, args);
});
}
if (spec.hasOwnProperty(COMMAND_APPLY)) {
("production" !== "development" ? invariant(
typeof spec[COMMAND_APPLY] === 'function',
'update(): expected spec of %s to be a function; got %s.',
COMMAND_APPLY,
spec[COMMAND_APPLY]
) : invariant(typeof spec[COMMAND_APPLY] === 'function'));
nextValue = spec[COMMAND_APPLY](nextValue);
}
for (var k in spec) {
if (!(ALL_COMMANDS_SET.hasOwnProperty(k) && ALL_COMMANDS_SET[k])) {
nextValue[k] = update(value[k], spec[k]);
}
}
return nextValue;
}
module.exports = update;
},{"./Object.assign":29,"./invariant":140,"./keyOf":147}],160:[function(_dereq_,module,exports){
/**
* Copyright 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule warning
*/
"use strict";
var emptyFunction = _dereq_("./emptyFunction");
/**
* Similar to invariant but only logs a warning if the condition is not met.
* This can be used to log issues in development environments in critical
* paths. Removing the logging code for production environments will keep the
* same logic and follow the same code paths.
*/
var warning = emptyFunction;
if ("production" !== "development") {
warning = function(condition, format ) {for (var args=[],$__0=2,$__1=arguments.length;$__0<$__1;$__0++) args.push(arguments[$__0]);
if (format === undefined) {
throw new Error(
'`warning(condition, format, ...args)` requires a warning ' +
'message argument'
);
}
if (!condition) {
var argIndex = 0;
console.warn('Warning: ' + format.replace(/%s/g, function() {return args[argIndex++];}));
}
};
}
module.exports = warning;
},{"./emptyFunction":121}]},{},[1])(1)
});
Other Java examples (source code examples)
Here is a short list of links related to this Java react-with-addons.js source code file: