/* Copyright 2008-2013 Clipperz Srl This file is part of Clipperz, the online password manager. For further information about its features and functionalities please refer to http://www.clipperz.com. * Clipperz is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * Clipperz is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. * You should have received a copy of the GNU Affero General Public License along with Clipperz. If not, see http://www.gnu.org/licenses/. */ /** * React v0.4.1 */ (function(e){if("function"==typeof bootstrap)bootstrap("react",e);else if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeReact=e}else"undefined"!=typeof window?window.React=e():global.React=e()})(function(){var define,ses,bootstrap,module,exports; return (function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s createMarkupForStyles({width: '200px', height: 0}) * "width:200px;height:0;" * * Undefined values are ignored so that declarative programming is easier. * * @param {object} styles * @return {?string} */ createMarkupForStyles: function(styles) { var serialized = ''; for (var styleName in styles) { if (!styles.hasOwnProperty(styleName)) { continue; } 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; } var styleValue = dangerousStyleValue(styleName, styles[styleName]); 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":2,"./dangerousStyleValue":65,"./escapeTextForBrowser":67,"./hyphenate":76,"./memoizeStringOnly":83}],4:[function(require,module,exports){ /** * Copyright 2013 Facebook, 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. * * @providesModule CallbackRegistry * @typechecks static-only */ "use strict"; var listenerBank = {}; /** * Stores "listeners" by `registrationName`/`id`. There should be at most one * "listener" per `registrationName`/`id` in the `listenerBank`. * * Access listeners via `listenerBank[registrationName][id]`. * * @class CallbackRegistry * @internal */ var CallbackRegistry = { /** * Stores `listener` at `listenerBank[registrationName][id]`. Is idempotent. * * @param {string} id ID of the DOM element. * @param {string} registrationName Name of listener (e.g. `onClick`). * @param {?function} listener The callback to store. */ putListener: function(id, registrationName, listener) { var bankForRegistrationName = listenerBank[registrationName] || (listenerBank[registrationName] = {}); bankForRegistrationName[id] = listener; }, /** * @param {string} id ID of the DOM element. * @param {string} registrationName Name of listener (e.g. `onClick`). * @return {?function} The stored callback. */ getListener: function(id, registrationName) { var bankForRegistrationName = listenerBank[registrationName]; return bankForRegistrationName && bankForRegistrationName[id]; }, /** * Deletes a listener from the registration bank. * * @param {string} id ID of the DOM element. * @param {string} registrationName Name of listener (e.g. `onClick`). */ deleteListener: function(id, registrationName) { var bankForRegistrationName = listenerBank[registrationName]; if (bankForRegistrationName) { delete bankForRegistrationName[id]; } }, /** * Deletes all listeners for the DOM element with the supplied ID. * * @param {string} id ID of the DOM element. */ deleteAllListeners: function(id) { for (var registrationName in listenerBank) { delete listenerBank[registrationName][id]; } }, /** * This is needed for tests only. Do not use! */ __purge: function() { listenerBank = {}; } }; module.exports = CallbackRegistry; },{}],5:[function(require,module,exports){ (function(){/** * Copyright 2013 Facebook, 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. * * @providesModule ChangeEventPlugin */ "use strict"; var EventConstants = require("./EventConstants"); var EventPluginHub = require("./EventPluginHub"); var EventPropagators = require("./EventPropagators"); var ExecutionEnvironment = require("./ExecutionEnvironment"); var SyntheticEvent = require("./SyntheticEvent"); var isEventSupported = require("./isEventSupported"); var keyOf = require("./keyOf"); var topLevelTypes = EventConstants.topLevelTypes; var eventTypes = { change: { phasedRegistrationNames: { bubbled: keyOf({onChange: null}), captured: keyOf({onChangeCapture: null}) } } }; /** * 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 bubbled, we'd just bind to it like all the other events // and have it go through ReactEventTopLevelCallback. Since it doesn't, we // manually listen for the change event and so we have to enqueue and // process the abstract event manually. 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 ); } /** * @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 shouldUseInputEvent(elem) { return ( (elem.nodeName === 'INPUT' && supportedInputTypes[elem.type]) || elem.nodeName === 'TEXTAREA' ); } /** * (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 `supportedInputTypes`) * - 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 (shouldUseInputEvent(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":13,"./EventPluginHub":15,"./EventPropagators":18,"./ExecutionEnvironment":19,"./SyntheticEvent":51,"./isEventSupported":79,"./keyOf":82}],6:[function(require,module,exports){ (function(){/** * Copyright 2013 Facebook, 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. * * @providesModule DOMChildrenOperations */ // Empty blocks improve readability so disable that warning // jshint -W035 "use strict"; var Danger = require("./Danger"); var insertNodeAt = require("./insertNodeAt"); var keyOf = require("./keyOf"); var throwIf = require("./throwIf"); var NON_INCREASING_OPERATIONS; if (true) { NON_INCREASING_OPERATIONS = 'DOM child management operations must be provided in order ' + 'of increasing destination index. This is likely an issue with ' + 'the core framework.'; } var MOVE_NODE_AT_ORIG_INDEX = keyOf({moveFrom: null}); var INSERT_MARKUP = keyOf({insertMarkup: null}); var REMOVE_AT = keyOf({removeAt: null}); /** * In order to carry out movement of DOM nodes without knowing their IDs, we * have to first store knowledge about nodes' original indices before beginning * to carry out the sequence of operations. Once we begin the sequence, the DOM * indices in future instructions are no longer valid. * * @param {Element} parent Parent DOM node. * @param {Object} childOperations Description of child operations. * @return {Array?} Sparse array containing elements by their current index in * the DOM. */ var _getNodesByOriginalIndex = function(parent, childOperations) { var nodesByOriginalIndex; // Sparse array. var childOperation; var origIndex; for (var i = 0; i < childOperations.length; i++) { childOperation = childOperations[i]; if (MOVE_NODE_AT_ORIG_INDEX in childOperation) { nodesByOriginalIndex = nodesByOriginalIndex || []; origIndex = childOperation.moveFrom; nodesByOriginalIndex[origIndex] = parent.childNodes[origIndex]; } else if (REMOVE_AT in childOperation) { nodesByOriginalIndex = nodesByOriginalIndex || []; origIndex = childOperation.removeAt; nodesByOriginalIndex[origIndex] = parent.childNodes[origIndex]; } } return nodesByOriginalIndex; }; /** * Removes DOM elements from their parent, or moved. * @param {Element} parent Parent DOM node. * @param {Array} nodesByOriginalIndex Child nodes by their original index * (potentially sparse.) */ var _removeChildrenByOriginalIndex = function(parent, nodesByOriginalIndex) { for (var j = 0; j < nodesByOriginalIndex.length; j++) { var nodeToRemove = nodesByOriginalIndex[j]; if (nodeToRemove) { // We used a sparse array. parent.removeChild(nodesByOriginalIndex[j]); } } }; /** * Once all nodes that will be removed or moved - are removed from the parent * node, we can begin the process of placing nodes into their final locations. * We must perform all operations in the order of the final DOM index - * otherwise, we couldn't count on the fact that an insertion at index X, will * remain at index X. This will iterate through the child operations, adding * content where needed, skip over removals (they've already been removed) and * insert "moved" Elements that were previously removed. The "moved" elements * are only temporarily removed from the parent, so that index calculations can * be manageable and perform well in the cases that matter. */ var _placeNodesAtDestination = function(parent, childOperations, nodesByOriginalIndex) { var origNode; var finalIndex; var lastFinalIndex = -1; var childOperation; for (var k = 0; k < childOperations.length; k++) { childOperation = childOperations[k]; if (MOVE_NODE_AT_ORIG_INDEX in childOperation) { origNode = nodesByOriginalIndex[childOperation.moveFrom]; finalIndex = childOperation.finalIndex; insertNodeAt(parent, origNode, finalIndex); if (true) { throwIf(finalIndex <= lastFinalIndex, NON_INCREASING_OPERATIONS); lastFinalIndex = finalIndex; } } else if (REMOVE_AT in childOperation) { } else if (INSERT_MARKUP in childOperation) { finalIndex = childOperation.finalIndex; var markup = childOperation.insertMarkup; Danger.dangerouslyInsertMarkupAt(parent, markup, finalIndex); if (true) { throwIf(finalIndex <= lastFinalIndex, NON_INCREASING_OPERATIONS); lastFinalIndex = finalIndex; } } } }; var manageChildren = function(parent, childOperations) { var nodesByOriginalIndex = _getNodesByOriginalIndex(parent, childOperations); if (nodesByOriginalIndex) { _removeChildrenByOriginalIndex(parent, nodesByOriginalIndex); } _placeNodesAtDestination(parent, childOperations, nodesByOriginalIndex); }; /** * Also reexport all of the dangerous functions. It helps to have all dangerous * functions located in a single module `Danger`. */ var DOMChildrenOperations = { dangerouslyReplaceNodeWithMarkup: Danger.dangerouslyReplaceNodeWithMarkup, manageChildren: manageChildren }; module.exports = DOMChildrenOperations; })() },{"./Danger":9,"./insertNodeAt":77,"./keyOf":82,"./throwIf":89}],7:[function(require,module,exports){ /** * Copyright 2013 Facebook, 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. * * @providesModule DOMProperty * @typechecks static-only */ /*jslint bitwise: true */ "use strict"; var invariant = require("./invariant"); var DOMPropertyInjection = { /** * Mapping from normalized, camelcased property names to a configuration that * specifies how the associated DOM property should be accessed or rendered. */ MUST_USE_ATTRIBUTE: 0x1, MUST_USE_PROPERTY: 0x2, HAS_BOOLEAN_VALUE: 0x4, HAS_SIDE_EFFECTS: 0x8, /** * Inject some specialized knowledge about the DOM. This takes a config object * with the following properties: * * isCustomAttribute: function that given an attribute name will return true * if it can be inserted into the DOM verbatim. Useful for data-* or aria-* * attributes where it's impossible to enumerate all of the possible * attribute names, * * Properties: object mapping DOM property name to one of the * DOMPropertyInjection constants or null. If your attribute isn't in here, * it won't get written to the DOM. * * DOMAttributeNames: object mapping React attribute name to the DOM * attribute name. Attribute names not specified use the **lowercase** * normalized name. * * DOMPropertyNames: similar to DOMAttributeNames but for DOM properties. * Property names not specified use the normalized name. * * DOMMutationMethods: Properties that require special mutation methods. If * `value` is undefined, the mutation method should unset the property. * * @param {object} domPropertyConfig the config as described above. */ injectDOMPropertyConfig: function(domPropertyConfig) { var Properties = domPropertyConfig.Properties || {}; var DOMAttributeNames = domPropertyConfig.DOMAttributeNames || {}; var DOMPropertyNames = domPropertyConfig.DOMPropertyNames || {}; var DOMMutationMethods = domPropertyConfig.DOMMutationMethods || {}; if (domPropertyConfig.isCustomAttribute) { DOMProperty._isCustomAttributeFunctions.push( domPropertyConfig.isCustomAttribute ); } for (var propName in Properties) { invariant( !DOMProperty.isStandardName[propName], 'injectDOMPropertyConfig(...): You\'re trying to inject DOM property ' + '\'%s\' which has already been injected. You may be accidentally ' + 'injecting the same DOM property config twice, or you may be ' + 'injecting two configs that have conflicting property names.', propName ); DOMProperty.isStandardName[propName] = true; DOMProperty.getAttributeName[propName] = DOMAttributeNames[propName] || propName.toLowerCase(); DOMProperty.getPropertyName[propName] = DOMPropertyNames[propName] || propName; var mutationMethod = DOMMutationMethods[propName]; if (mutationMethod) { DOMProperty.getMutationMethod[propName] = mutationMethod; } var propConfig = Properties[propName]; DOMProperty.mustUseAttribute[propName] = propConfig & DOMPropertyInjection.MUST_USE_ATTRIBUTE; DOMProperty.mustUseProperty[propName] = propConfig & DOMPropertyInjection.MUST_USE_PROPERTY; DOMProperty.hasBooleanValue[propName] = propConfig & DOMPropertyInjection.HAS_BOOLEAN_VALUE; DOMProperty.hasSideEffects[propName] = propConfig & DOMPropertyInjection.HAS_SIDE_EFFECTS; invariant( !DOMProperty.mustUseAttribute[propName] || !DOMProperty.mustUseProperty[propName], 'DOMProperty: Cannot use require using both attribute and property: %s', propName ); invariant( DOMProperty.mustUseProperty[propName] || !DOMProperty.hasSideEffects[propName], 'DOMProperty: Properties that have side effects must use property: %s', propName ); } } }; var defaultValueCache = {}; /** * DOMProperty exports lookup objects that can be used like functions: * * > DOMProperty.isValid['id'] * true * > DOMProperty.isValid['foobar'] * undefined * * Although this may be confusing, it performs better in general. * * @see http://jsperf.com/key-exists * @see http://jsperf.com/key-missing */ var DOMProperty = { /** * Checks whether a property name is a standard property. * @type {Object} */ isStandardName: {}, /** * Mapping from normalized names to attribute names that differ. Attribute * names are used when rendering markup or with `*Attribute()`. * @type {Object} */ getAttributeName: {}, /** * Mapping from normalized names to properties on DOM node instances. * (This includes properties that mutate due to external factors.) * @type {Object} */ getPropertyName: {}, /** * Mapping from normalized names to mutation methods. This will only exist if * mutation cannot be set simply by the property or `setAttribute()`. * @type {Object} */ getMutationMethod: {}, /** * Whether the property must be accessed and mutated as an object property. * @type {Object} */ mustUseAttribute: {}, /** * Whether the property must be accessed and mutated using `*Attribute()`. * (This includes anything that fails ` in `.) * @type {Object} */ mustUseProperty: {}, /** * Whether the property should be removed when set to a falsey value. * @type {Object} */ hasBooleanValue: {}, /** * Whether or not setting a value causes side effects such as triggering * resources to be loaded or text selection changes. We must ensure that * the value is only set if it has changed. * @type {Object} */ hasSideEffects: {}, /** * All of the isCustomAttribute() functions that have been injected. */ _isCustomAttributeFunctions: [], /** * Checks whether a property name is a custom attribute. * @method */ isCustomAttribute: function(attributeName) { return DOMProperty._isCustomAttributeFunctions.some( function(isCustomAttributeFn) { return isCustomAttributeFn.call(null, attributeName); } ); }, /** * Returns the default property value for a DOM property (i.e., not an * attribute). Most default values are '' or false, but not all. Worse yet, * some (in particular, `type`) vary depending on the type of element. * * TODO: Is it better to grab all the possible properties when creating an * element to avoid having to create the same element twice? */ getDefaultValueForProperty: function(nodeName, prop) { var nodeDefaults = defaultValueCache[nodeName]; var testElement; if (!nodeDefaults) { defaultValueCache[nodeName] = nodeDefaults = {}; } if (!(prop in nodeDefaults)) { testElement = document.createElement(nodeName); nodeDefaults[prop] = testElement[prop]; } return nodeDefaults[prop]; }, injection: DOMPropertyInjection }; module.exports = DOMProperty; },{"./invariant":78}],8:[function(require,module,exports){ /** * Copyright 2013 Facebook, 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. * * @providesModule DOMPropertyOperations * @typechecks static-only */ "use strict"; var DOMProperty = require("./DOMProperty"); var escapeTextForBrowser = require("./escapeTextForBrowser"); var memoizeStringOnly = require("./memoizeStringOnly"); var processAttributeNameAndPrefix = memoizeStringOnly(function(name) { return escapeTextForBrowser(name) + '="'; }); /** * Operations for dealing with DOM properties. */ var DOMPropertyOperations = { /** * Creates markup for a property. * * @param {string} name * @param {*} value * @return {?string} Markup string, or null if the property was invalid. */ createMarkupForProperty: function(name, value) { if (DOMProperty.isStandardName[name]) { if (value == null || DOMProperty.hasBooleanValue[name] && !value) { return ''; } var attributeName = DOMProperty.getAttributeName[name]; return processAttributeNameAndPrefix(attributeName) + escapeTextForBrowser(value) + '"'; } else if (DOMProperty.isCustomAttribute(name)) { if (value == null) { return ''; } return processAttributeNameAndPrefix(name) + escapeTextForBrowser(value) + '"'; } else { return null; } }, /** * Sets the value for a property on a node. * * @param {DOMElement} node * @param {string} name * @param {*} value */ setValueForProperty: function(node, name, value) { if (DOMProperty.isStandardName[name]) { var mutationMethod = DOMProperty.getMutationMethod[name]; if (mutationMethod) { mutationMethod(node, value); } else if (DOMProperty.mustUseAttribute[name]) { if (DOMProperty.hasBooleanValue[name] && !value) { node.removeAttribute(DOMProperty.getAttributeName[name]); } else { node.setAttribute(DOMProperty.getAttributeName[name], value); } } else { var propName = DOMProperty.getPropertyName[name]; if (!DOMProperty.hasSideEffects[name] || node[propName] !== value) { node[propName] = value; } } } else if (DOMProperty.isCustomAttribute(name)) { node.setAttribute(name, value); } }, /** * Deletes the value for a property on a node. * * @param {DOMElement} node * @param {string} name */ deleteValueForProperty: function(node, name) { if (DOMProperty.isStandardName[name]) { var mutationMethod = DOMProperty.getMutationMethod[name]; if (mutationMethod) { mutationMethod(node, undefined); } else if (DOMProperty.mustUseAttribute[name]) { node.removeAttribute(DOMProperty.getAttributeName[name]); } else { var propName = DOMProperty.getPropertyName[name]; node[propName] = DOMProperty.getDefaultValueForProperty( node.nodeName, name ); } } else if (DOMProperty.isCustomAttribute(name)) { node.removeAttribute(name); } } }; module.exports = DOMPropertyOperations; },{"./DOMProperty":7,"./escapeTextForBrowser":67,"./memoizeStringOnly":83}],9:[function(require,module,exports){ /** * Copyright 2013 Facebook, 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. * * @providesModule Danger */ /*jslint evil: true, sub: true */ "use strict"; var ExecutionEnvironment = require("./ExecutionEnvironment"); var throwIf = require("./throwIf"); var DOM_UNSUPPORTED; var NO_MARKUP_PARENT; var NO_MULTI_MARKUP; if (true) { DOM_UNSUPPORTED = 'You may not insert markup into the document while you are in a worker ' + 'thread. It\'s not you, it\'s me. This is likely the fault of the ' + 'framework. Please report this immediately.'; NO_MARKUP_PARENT = 'You have attempted to inject markup without a suitable parent. This is ' + 'likely the fault of the framework - please report immediately.'; NO_MULTI_MARKUP = 'The framework has attempted to either insert zero or multiple markup ' + 'roots into a single location when it should not. This is a serious ' + 'error - a fault of the framework - please report immediately.'; } var validateMarkupParams; if (true) { validateMarkupParams = function(parentNode, markup) { throwIf(!ExecutionEnvironment.canUseDOM, DOM_UNSUPPORTED); throwIf(!parentNode || !parentNode.tagName, NO_MARKUP_PARENT); throwIf(!markup, NO_MULTI_MARKUP); }; } /** * Dummy container used to render all markup. */ var dummyNode = ExecutionEnvironment.canUseDOM ? document.createElement('div') : null; /** * Some browsers cannot use `innerHTML` to render certain elements standalone, * so we wrap them, render the wrapped nodes, then extract the desired node. */ var markupWrap = { 'option': [1, ''], 'legend': [1, '
', '
'], 'area': [1, '', ''], 'param': [1, '', ''], 'thead': [1, '', '
'], 'tr': [2, '', '
'], 'col': [2, '', '
'], 'td': [3, '', '
'] }; markupWrap['optgroup'] = markupWrap['option']; markupWrap['tbody'] = markupWrap['thead']; markupWrap['tfoot'] = markupWrap['thead']; markupWrap['colgroup'] = markupWrap['thead']; markupWrap['caption'] = markupWrap['thead']; markupWrap['th'] = markupWrap['td']; /** * In IE8, certain elements cannot render alone, so wrap all elements. */ var defaultWrap = [1, '?
', '
']; /** * Feature detection, remove wraps that are unnecessary for the current browser. */ if (dummyNode) { for (var nodeName in markupWrap) { if (!markupWrap.hasOwnProperty(nodeName)) { continue; } dummyNode.innerHTML = '<' + nodeName + '>'; if (dummyNode.firstChild) { markupWrap[nodeName] = null; } } dummyNode.innerHTML = ''; if (dummyNode.firstChild) { defaultWrap = null; } } /** * Renders markup into nodes. The returned HTMLCollection is live and should be * used immediately (or at least before the next invocation to `renderMarkup`). * * NOTE: Extracting the `nodeName` does not require a regular expression match * because we make assumptions about React-generated markup (i.e. there are no * spaces surrounding the opening tag and there is at least one attribute). * @see http://jsperf.com/extract-nodename * * @param {string} markup * @return {*} An HTMLCollection. */ function renderMarkup(markup) { var node = dummyNode; var nodeName = markup.substring(1, markup.indexOf(' ')); var wrap = markupWrap[nodeName.toLowerCase()] || defaultWrap; if (wrap) { node.innerHTML = wrap[1] + markup + wrap[2]; var wrapDepth = wrap[0]; while (wrapDepth--) { node = node.lastChild; } } else { node.innerHTML = markup; } return node.childNodes; } /** * Inserts node after 'after'. If 'after' is null, inserts it after nothing, * which is inserting it at the beginning. * * @param {Element} elem Parent element. * @param {Element} insert Element to insert. * @param {Element} after Element to insert after. * @return {Element} Element that was inserted. */ function insertNodeAfterNode(elem, insert, after) { if (true) { throwIf(!ExecutionEnvironment.canUseDOM, DOM_UNSUPPORTED); } if (after) { if (after.nextSibling) { return elem.insertBefore(insert, after.nextSibling); } else { return elem.appendChild(insert); } } else { return elem.insertBefore(insert, elem.firstChild); } } /** * Slow: Should only be used when it is known there are a few (or one) element * in the node list. * @param {Element} parentRootDomNode Parent element. * @param {HTMLCollection} htmlCollection HTMLCollection to insert. * @param {Element} after Element to insert the node list after. */ function inefficientlyInsertHTMLCollectionAfter( parentRootDomNode, htmlCollection, after) { if (true) { throwIf(!ExecutionEnvironment.canUseDOM, DOM_UNSUPPORTED); } var ret; var originalLength = htmlCollection.length; // Access htmlCollection[0] because htmlCollection shrinks as we remove items. // `insertNodeAfterNode` will remove items from the htmlCollection. for (var i = 0; i < originalLength; i++) { ret = insertNodeAfterNode(parentRootDomNode, htmlCollection[0], ret || after); } } /** * Super-dangerously inserts markup into existing DOM structure. Seriously, you * don't want to use this module unless you are building a framework. This * requires that the markup that you are inserting represents the root of a * tree. We do not support the case where there `markup` represents several * roots. * * @param {Element} parentNode Parent DOM element. * @param {string} markup Markup to dangerously insert. * @param {number} index Position to insert markup at. */ function dangerouslyInsertMarkupAt(parentNode, markup, index) { if (true) { validateMarkupParams(parentNode, markup); } var htmlCollection = renderMarkup(markup); var afterNode = index ? parentNode.childNodes[index - 1] : null; inefficientlyInsertHTMLCollectionAfter(parentNode, htmlCollection, afterNode); } /** * Replaces a node with a string of markup at its current position within its * parent. `childNode` must be in the document (or at least within a parent * node). The string of markup must represent a tree of markup with a single * root. * * @param {Element} childNode Child node to replace. * @param {string} markup Markup to dangerously replace child with. */ function dangerouslyReplaceNodeWithMarkup(childNode, markup) { var parentNode = childNode.parentNode; if (true) { validateMarkupParams(parentNode, markup); } var htmlCollection = renderMarkup(markup); if (true) { throwIf(htmlCollection.length !== 1, NO_MULTI_MARKUP); } parentNode.replaceChild(htmlCollection[0], childNode); } var Danger = { dangerouslyInsertMarkupAt: dangerouslyInsertMarkupAt, dangerouslyReplaceNodeWithMarkup: dangerouslyReplaceNodeWithMarkup }; module.exports = Danger; },{"./ExecutionEnvironment":19,"./throwIf":89}],10:[function(require,module,exports){ /** * Copyright 2013 Facebook, 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. * * @providesModule DefaultDOMPropertyConfig */ "use strict"; var DOMProperty = require("./DOMProperty"); var MUST_USE_ATTRIBUTE = DOMProperty.injection.MUST_USE_ATTRIBUTE; var MUST_USE_PROPERTY = DOMProperty.injection.MUST_USE_PROPERTY; var HAS_BOOLEAN_VALUE = DOMProperty.injection.HAS_BOOLEAN_VALUE; var HAS_SIDE_EFFECTS = DOMProperty.injection.HAS_SIDE_EFFECTS; var DefaultDOMPropertyConfig = { isCustomAttribute: RegExp.prototype.test.bind( /^(data|aria)-[a-z_][a-z\d_.\-]*$/ ), Properties: { /** * Standard Properties */ accessKey: null, accept: null, action: null, ajaxify: MUST_USE_ATTRIBUTE, allowFullScreen: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE, allowTransparency: MUST_USE_ATTRIBUTE, alt: null, autoComplete: null, autoFocus: HAS_BOOLEAN_VALUE, autoPlay: HAS_BOOLEAN_VALUE, cellPadding: null, cellSpacing: null, checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, className: MUST_USE_PROPERTY, colSpan: null, contentEditable: null, contextMenu: MUST_USE_ATTRIBUTE, controls: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, data: null, // For `` acts as `src`. dateTime: MUST_USE_ATTRIBUTE, dir: null, disabled: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, draggable: null, encType: null, frameBorder: MUST_USE_ATTRIBUTE, height: MUST_USE_ATTRIBUTE, hidden: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE, href: null, htmlFor: null, icon: null, id: MUST_USE_PROPERTY, label: null, lang: null, list: null, max: null, maxLength: MUST_USE_ATTRIBUTE, method: null, min: null, multiple: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, name: null, pattern: null, poster: null, preload: null, placeholder: null, radioGroup: null, rel: null, readOnly: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, required: HAS_BOOLEAN_VALUE, role: MUST_USE_ATTRIBUTE, scrollLeft: MUST_USE_PROPERTY, scrollTop: MUST_USE_PROPERTY, selected: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, size: null, spellCheck: null, src: null, step: null, style: null, tabIndex: null, target: null, title: null, type: null, value: MUST_USE_PROPERTY | HAS_SIDE_EFFECTS, width: MUST_USE_ATTRIBUTE, wmode: MUST_USE_ATTRIBUTE, /** * SVG Properties */ cx: MUST_USE_PROPERTY, cy: MUST_USE_PROPERTY, d: MUST_USE_PROPERTY, fill: MUST_USE_PROPERTY, fx: MUST_USE_PROPERTY, fy: MUST_USE_PROPERTY, points: MUST_USE_PROPERTY, r: MUST_USE_PROPERTY, stroke: MUST_USE_PROPERTY, strokeLinecap: MUST_USE_PROPERTY, strokeWidth: MUST_USE_PROPERTY, transform: MUST_USE_PROPERTY, x: MUST_USE_PROPERTY, x1: MUST_USE_PROPERTY, x2: MUST_USE_PROPERTY, version: MUST_USE_PROPERTY, viewBox: MUST_USE_PROPERTY, y: MUST_USE_PROPERTY, y1: MUST_USE_PROPERTY, y2: MUST_USE_PROPERTY, spreadMethod: MUST_USE_PROPERTY, offset: MUST_USE_PROPERTY, stopColor: MUST_USE_PROPERTY, stopOpacity: MUST_USE_PROPERTY, gradientUnits: MUST_USE_PROPERTY, gradientTransform: MUST_USE_PROPERTY }, DOMAttributeNames: { className: 'class', htmlFor: 'for', strokeLinecap: 'stroke-linecap', strokeWidth: 'stroke-width', stopColor: 'stop-color', stopOpacity: 'stop-opacity' }, DOMPropertyNames: { autoComplete: 'autocomplete', autoFocus: 'autofocus', autoPlay: 'autoplay', encType: 'enctype', radioGroup: 'radiogroup', spellCheck: 'spellcheck' }, DOMMutationMethods: { /** * Setting `className` to null may cause it to be set to the string "null". * * @param {DOMElement} node * @param {*} value */ className: function(node, value) { node.className = value || ''; } } }; module.exports = DefaultDOMPropertyConfig; },{"./DOMProperty":7}],11:[function(require,module,exports){ /** * Copyright 2013 Facebook, 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. * * @providesModule DefaultEventPluginOrder */ "use strict"; var keyOf = require("./keyOf"); /** * Module that is injectable into `EventPluginHub`, that specifies a * deterministic ordering of `EventPlugin`s. A convenient way to reason about * plugins, without having to package every one of them. This is better than * having plugins be ordered in the same order that they are injected because * that ordering would be influenced by the packaging order. * `ResponderEventPlugin` must occur before `SimpleEventPlugin` so that * preventing default on events is convenient in `SimpleEventPlugin` handlers. */ var DefaultEventPluginOrder = [ keyOf({ResponderEventPlugin: null}), keyOf({SimpleEventPlugin: null}), keyOf({TapEventPlugin: null}), keyOf({EnterLeaveEventPlugin: null}), keyOf({ChangeEventPlugin: null}), keyOf({AnalyticsEventPlugin: null}), keyOf({MobileSafariClickEventPlugin: null}) ]; module.exports = DefaultEventPluginOrder; },{"./keyOf":82}],12:[function(require,module,exports){ (function(){/** * Copyright 2013 Facebook, 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. * * @providesModule EnterLeaveEventPlugin * @typechecks static-only */ "use strict"; var EventConstants = require("./EventConstants"); var EventPropagators = require("./EventPropagators"); var ExecutionEnvironment = require("./ExecutionEnvironment"); var SyntheticMouseEvent = require("./SyntheticMouseEvent"); var ReactMount = require("./ReactMount"); var keyOf = require("./keyOf"); var topLevelTypes = EventConstants.topLevelTypes; var getFirstReactDOM = ReactMount.getFirstReactDOM; var eventTypes = { mouseEnter: {registrationName: keyOf({onMouseEnter: null})}, mouseLeave: {registrationName: keyOf({onMouseLeave: null})} }; var EnterLeaveEventPlugin = { eventTypes: eventTypes, /** * For almost every interaction we care about, there will be both a top-level * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that * we do not extract duplicate events. However, moving the mouse into the * browser from outside will not fire a `mouseout` event. In this case, we use * the `mouseover` top-level event. * * @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) { if (topLevelType === topLevelTypes.topMouseOver && (nativeEvent.relatedTarget || nativeEvent.fromElement)) { return null; } if (topLevelType !== topLevelTypes.topMouseOut && topLevelType !== topLevelTypes.topMouseOver) { // Must not be a mouse in or mouse out - ignoring. return null; } var from, to; if (topLevelType === topLevelTypes.topMouseOut) { from = topLevelTarget; to = getFirstReactDOM(nativeEvent.relatedTarget || nativeEvent.toElement) || ExecutionEnvironment.global; } else { from = ExecutionEnvironment.global; to = topLevelTarget; } if (from === to) { // Nothing pertains to our managed components. return null; } var fromID = from ? ReactMount.getID(from) : ''; var toID = to ? ReactMount.getID(to) : ''; var leave = SyntheticMouseEvent.getPooled( eventTypes.mouseLeave, fromID, nativeEvent ); var enter = SyntheticMouseEvent.getPooled( eventTypes.mouseEnter, toID, nativeEvent ); EventPropagators.accumulateEnterLeaveDispatches(leave, enter, fromID, toID); return [leave, enter]; } }; module.exports = EnterLeaveEventPlugin; })() },{"./EventConstants":13,"./EventPropagators":18,"./ExecutionEnvironment":19,"./ReactMount":39,"./SyntheticMouseEvent":54,"./keyOf":82}],13:[function(require,module,exports){ /** * Copyright 2013 Facebook, 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. * * @providesModule EventConstants */ "use strict"; var keyMirror = require("./keyMirror"); var PropagationPhases = keyMirror({bubbled: null, captured: null}); /** * Types of raw signals from the browser caught at the top level. */ var topLevelTypes = keyMirror({ topBlur: null, topChange: null, topClick: null, topDOMCharacterDataModified: null, topDoubleClick: null, topDrag: null, topDragEnd: null, topDragEnter: null, topDragExit: null, topDragLeave: null, topDragOver: null, topDragStart: null, topDrop: null, topFocus: null, topInput: null, topKeyDown: null, topKeyPress: null, topKeyUp: null, topMouseDown: null, topMouseMove: null, topMouseOut: null, topMouseOver: null, topMouseUp: null, topScroll: null, topSelectionChange: null, topSubmit: null, topTouchCancel: null, topTouchEnd: null, topTouchMove: null, topTouchStart: null, topWheel: null }); var EventConstants = { topLevelTypes: topLevelTypes, PropagationPhases: PropagationPhases }; module.exports = EventConstants; },{"./keyMirror":81}],14:[function(require,module,exports){ /** * Copyright 2013 Facebook, 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. * * @providesModule EventListener */ /** * Upstream version of event listener. Does not take into account specific * nature of platform. */ var EventListener = { /** * Listens to bubbled events on a DOM node. * * @param {Element} el DOM element to register listener on. * @param {string} handlerBaseName 'click'/'mouseover' * @param {Function!} cb Callback function */ listen: function(el, handlerBaseName, cb) { if (el.addEventListener) { el.addEventListener(handlerBaseName, cb, false); } else if (el.attachEvent) { el.attachEvent('on' + handlerBaseName, cb); } }, /** * Listens to captured events on a DOM node. * * @see `EventListener.listen` for params. * @throws Exception if addEventListener is not supported. */ capture: function(el, handlerBaseName, cb) { if (!el.addEventListener) { if (true) { console.error( 'You are attempting to use addEventlistener ' + 'in a browser that does not support it support it.' + 'This likely means that you will not receive events that ' + 'your application relies on (such as scroll).'); } return; } else { el.addEventListener(handlerBaseName, cb, true); } } }; module.exports = EventListener; },{}],15:[function(require,module,exports){ /** * Copyright 2013 Facebook, 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. * * @providesModule EventPluginHub */ "use strict"; var CallbackRegistry = require("./CallbackRegistry"); var EventPluginRegistry = require("./EventPluginRegistry"); var EventPluginUtils = require("./EventPluginUtils"); var EventPropagators = require("./EventPropagators"); var ExecutionEnvironment = require("./ExecutionEnvironment"); var accumulate = require("./accumulate"); var forEachAccumulated = require("./forEachAccumulated"); var invariant = require("./invariant"); /** * Internal queue of events that have accumulated their dispatches and are * waiting to have their dispatches executed. */ var eventQueue = null; /** * Dispatches an event and releases it back into the pool, unless persistent. * * @param {?object} event Synthetic event to be dispatched. * @private */ var executeDispatchesAndRelease = function(event) { if (event) { var executeDispatch = EventPluginUtils.executeDispatch; // Plugins can provide custom behavior when dispatching events. var PluginModule = EventPluginRegistry.getPluginModuleForEvent(event); if (PluginModule && PluginModule.executeDispatch) { executeDispatch = PluginModule.executeDispatch; } EventPluginUtils.executeDispatchesInOrder(event, executeDispatch); if (!event.isPersistent()) { event.constructor.release(event); } } }; /** * This is a unified interface for event plugins to be installed and configured. * * Event plugins can implement the following properties: * * `extractEvents` {function(string, DOMEventTarget, string, object): *} * Required. When a top-level event is fired, this method is expected to * extract synthetic events that will in turn be queued and dispatched. * * `eventTypes` {object} * Optional, plugins that fire events must publish a mapping of registration * names that are used to register listeners. Values of this mapping must * be objects that contain `registrationName` or `phasedRegistrationNames`. * * `executeDispatch` {function(object, function, string)} * Optional, allows plugins to override how an event gets dispatched. By * default, the listener is simply invoked. * * Each plugin that is injected into `EventsPluginHub` is immediately operable. * * @public */ var EventPluginHub = { /** * Methods for injecting dependencies. */ injection: { /** * @param {object} InjectedInstanceHandle * @public */ injectInstanceHandle: EventPropagators.injection.injectInstanceHandle, /** * @param {array} InjectedEventPluginOrder * @public */ injectEventPluginOrder: EventPluginRegistry.injectEventPluginOrder, /** * @param {object} injectedNamesToPlugins Map from names to plugin modules. */ injectEventPluginsByName: EventPluginRegistry.injectEventPluginsByName }, registrationNames: EventPluginRegistry.registrationNames, putListener: CallbackRegistry.putListener, getListener: CallbackRegistry.getListener, deleteListener: CallbackRegistry.deleteListener, deleteAllListeners: CallbackRegistry.deleteAllListeners, /** * Allows registered plugins an opportunity to extract events from top-level * native browser events. * * @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. * @internal */ extractEvents: function( topLevelType, topLevelTarget, topLevelTargetID, nativeEvent) { var events; var plugins = EventPluginRegistry.plugins; for (var i = 0, l = plugins.length; i < l; i++) { // Not every plugin in the ordering may be loaded at runtime. var possiblePlugin = plugins[i]; if (possiblePlugin) { var extractedEvents = possiblePlugin.extractEvents( topLevelType, topLevelTarget, topLevelTargetID, nativeEvent ); if (extractedEvents) { events = accumulate(events, extractedEvents); } } } return events; }, /** * Enqueues a synthetic event that should be dispatched when * `processEventQueue` is invoked. * * @param {*} events An accumulation of synthetic events. * @internal */ enqueueEvents: function(events) { if (events) { eventQueue = accumulate(eventQueue, events); } }, /** * Dispatches all synthetic events on the event queue. * * @internal */ processEventQueue: function() { // Set `eventQueue` to null before processing it so that we can tell if more // events get enqueued while processing. var processingEventQueue = eventQueue; eventQueue = null; forEachAccumulated(processingEventQueue, executeDispatchesAndRelease); invariant( !eventQueue, 'processEventQueue(): Additional events were enqueued while processing ' + 'an event queue. Support for this has not yet been implemented.' ); } }; if (ExecutionEnvironment.canUseDOM) { window.EventPluginHub = EventPluginHub; } module.exports = EventPluginHub; },{"./CallbackRegistry":4,"./EventPluginRegistry":16,"./EventPluginUtils":17,"./EventPropagators":18,"./ExecutionEnvironment":19,"./accumulate":61,"./forEachAccumulated":70,"./invariant":78}],16:[function(require,module,exports){ /** * Copyright 2013 Facebook, 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. * * @providesModule EventPluginRegistry * @typechecks static-only */ "use strict"; var invariant = require("./invariant"); /** * Injectable ordering of event plugins. */ var EventPluginOrder = null; /** * Injectable mapping from names to event plugin modules. */ var namesToPlugins = {}; /** * Recomputes the plugin list using the injected plugins and plugin ordering. * * @private */ function recomputePluginOrdering() { if (!EventPluginOrder) { // Wait until an `EventPluginOrder` is injected. return; } for (var pluginName in namesToPlugins) { var PluginModule = namesToPlugins[pluginName]; var pluginIndex = EventPluginOrder.indexOf(pluginName); invariant( pluginIndex > -1, 'EventPluginRegistry: Cannot inject event plugins that do not exist in ' + 'the plugin ordering, `%s`.', pluginName ); if (EventPluginRegistry.plugins[pluginIndex]) { continue; } invariant( PluginModule.extractEvents, 'EventPluginRegistry: Event plugins must implement an `extractEvents` ' + 'method, but `%s` does not.', pluginName ); EventPluginRegistry.plugins[pluginIndex] = PluginModule; var publishedEvents = PluginModule.eventTypes; for (var eventName in publishedEvents) { invariant( publishEventForPlugin(publishedEvents[eventName], PluginModule), 'EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.', eventName, pluginName ); } } } /** * Publishes an event so that it can be dispatched by the supplied plugin. * * @param {object} dispatchConfig Dispatch configuration for the event. * @param {object} PluginModule Plugin publishing the event. * @return {boolean} True if the event was successfully published. * @private */ function publishEventForPlugin(dispatchConfig, PluginModule) { var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; if (phasedRegistrationNames) { for (var phaseName in phasedRegistrationNames) { if (phasedRegistrationNames.hasOwnProperty(phaseName)) { var phasedRegistrationName = phasedRegistrationNames[phaseName]; publishRegistrationName(phasedRegistrationName, PluginModule); } } return true; } else if (dispatchConfig.registrationName) { publishRegistrationName(dispatchConfig.registrationName, PluginModule); return true; } return false; } /** * Publishes a registration name that is used to identify dispatched events and * can be used with `EventPluginHub.putListener` to register listeners. * * @param {string} registrationName Registration name to add. * @param {object} PluginModule Plugin publishing the event. * @private */ function publishRegistrationName(registrationName, PluginModule) { invariant( !EventPluginRegistry.registrationNames[registrationName], 'EventPluginHub: More than one plugin attempted to publish the same ' + 'registration name, `%s`.', registrationName ); EventPluginRegistry.registrationNames[registrationName] = PluginModule; EventPluginRegistry.registrationNamesKeys.push(registrationName); } /** * Registers plugins so that they can extract and dispatch events. * * @see {EventPluginHub} */ var EventPluginRegistry = { /** * Ordered list of injected plugins. */ plugins: [], /** * Mapping from registration names to plugin modules. */ registrationNames: {}, /** * The keys of `registrationNames`. */ registrationNamesKeys: [], /** * Injects an ordering of plugins (by plugin name). This allows the ordering * to be decoupled from injection of the actual plugins so that ordering is * always deterministic regardless of packaging, on-the-fly injection, etc. * * @param {array} InjectedEventPluginOrder * @internal * @see {EventPluginHub.injection.injectEventPluginOrder} */ injectEventPluginOrder: function(InjectedEventPluginOrder) { invariant( !EventPluginOrder, 'EventPluginRegistry: Cannot inject event plugin ordering more than once.' ); // Clone the ordering so it cannot be dynamically mutated. EventPluginOrder = Array.prototype.slice.call(InjectedEventPluginOrder); recomputePluginOrdering(); }, /** * Injects plugins to be used by `EventPluginHub`. The plugin names must be * in the ordering injected by `injectEventPluginOrder`. * * Plugins can be injected as part of page initialization or on-the-fly. * * @param {object} injectedNamesToPlugins Map from names to plugin modules. * @internal * @see {EventPluginHub.injection.injectEventPluginsByName} */ injectEventPluginsByName: function(injectedNamesToPlugins) { var isOrderingDirty = false; for (var pluginName in injectedNamesToPlugins) { if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) { continue; } var PluginModule = injectedNamesToPlugins[pluginName]; if (namesToPlugins[pluginName] !== PluginModule) { invariant( !namesToPlugins[pluginName], 'EventPluginRegistry: Cannot inject two different event plugins ' + 'using the same name, `%s`.', pluginName ); namesToPlugins[pluginName] = PluginModule; isOrderingDirty = true; } } if (isOrderingDirty) { recomputePluginOrdering(); } }, /** * Looks up the plugin for the supplied event. * * @param {object} event A synthetic event. * @return {?object} The plugin that created the supplied event. * @internal */ getPluginModuleForEvent: function(event) { var dispatchConfig = event.dispatchConfig; if (dispatchConfig.registrationName) { return EventPluginRegistry.registrationNames[ dispatchConfig.registrationName ] || null; } for (var phase in dispatchConfig.phasedRegistrationNames) { if (!dispatchConfig.phasedRegistrationNames.hasOwnProperty(phase)) { continue; } var PluginModule = EventPluginRegistry.registrationNames[ dispatchConfig.phasedRegistrationNames[phase] ]; if (PluginModule) { return PluginModule; } } return null; }, /** * Exposed for unit testing. * @private */ _resetEventPlugins: function() { EventPluginOrder = null; for (var pluginName in namesToPlugins) { if (namesToPlugins.hasOwnProperty(pluginName)) { delete namesToPlugins[pluginName]; } } EventPluginRegistry.plugins.length = 0; var registrationNames = EventPluginRegistry.registrationNames; for (var registrationName in registrationNames) { if (registrationNames.hasOwnProperty(registrationName)) { delete registrationNames[registrationName]; } } EventPluginRegistry.registrationNamesKeys.length = 0; } }; module.exports = EventPluginRegistry; },{"./invariant":78}],17:[function(require,module,exports){ /** * Copyright 2013 Facebook, 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. * * @providesModule EventPluginUtils */ "use strict"; var EventConstants = require("./EventConstants"); var invariant = require("./invariant"); var topLevelTypes = EventConstants.topLevelTypes; function isEndish(topLevelType) { return topLevelType === topLevelTypes.topMouseUp || topLevelType === topLevelTypes.topTouchEnd || topLevelType === topLevelTypes.topTouchCancel; } function isMoveish(topLevelType) { return topLevelType === topLevelTypes.topMouseMove || topLevelType === topLevelTypes.topTouchMove; } function isStartish(topLevelType) { return topLevelType === topLevelTypes.topMouseDown || topLevelType === topLevelTypes.topTouchStart; } var validateEventDispatches; if (true) { validateEventDispatches = function(event) { var dispatchListeners = event._dispatchListeners; var dispatchIDs = event._dispatchIDs; var listenersIsArr = Array.isArray(dispatchListeners); var idsIsArr = Array.isArray(dispatchIDs); var IDsLen = idsIsArr ? dispatchIDs.length : dispatchIDs ? 1 : 0; var listenersLen = listenersIsArr ? dispatchListeners.length : dispatchListeners ? 1 : 0; invariant( idsIsArr === listenersIsArr && IDsLen === listenersLen, 'EventPluginUtils: Invalid `event`.' ); }; } /** * Invokes `cb(event, listener, id)`. Avoids using call if no scope is * provided. The `(listener,id)` pair effectively forms the "dispatch" but are * kept separate to conserve memory. */ function forEachEventDispatch(event, cb) { var dispatchListeners = event._dispatchListeners; var dispatchIDs = event._dispatchIDs; if (true) { validateEventDispatches(event); } if (Array.isArray(dispatchListeners)) { for (var i = 0; i < dispatchListeners.length; i++) { if (event.isPropagationStopped()) { break; } // Listeners and IDs are two parallel arrays that are always in sync. cb(event, dispatchListeners[i], dispatchIDs[i]); } } else if (dispatchListeners) { cb(event, dispatchListeners, dispatchIDs); } } /** * Default implementation of PluginModule.executeDispatch(). * @param {SyntheticEvent} SyntheticEvent to handle * @param {function} Application-level callback * @param {string} domID DOM id to pass to the callback. */ function executeDispatch(event, listener, domID) { listener(event, domID); } /** * Standard/simple iteration through an event's collected dispatches. */ function executeDispatchesInOrder(event, executeDispatch) { forEachEventDispatch(event, executeDispatch); event._dispatchListeners = null; event._dispatchIDs = null; } /** * Standard/simple iteration through an event's collected dispatches, but stops * at the first dispatch execution returning true, and returns that id. * * @return id of the first dispatch execution who's listener returns true, or * null if no listener returned true. */ function executeDispatchesInOrderStopAtTrue(event) { var dispatchListeners = event._dispatchListeners; var dispatchIDs = event._dispatchIDs; if (true) { validateEventDispatches(event); } if (Array.isArray(dispatchListeners)) { for (var i = 0; i < dispatchListeners.length; i++) { if (event.isPropagationStopped()) { break; } // Listeners and IDs are two parallel arrays that are always in sync. if (dispatchListeners[i](event, dispatchIDs[i])) { return dispatchIDs[i]; } } } else if (dispatchListeners) { if (dispatchListeners(event, dispatchIDs)) { return dispatchIDs; } } return null; } /** * Execution of a "direct" dispatch - there must be at most one dispatch * accumulated on the event or it is considered an error. It doesn't really make * sense for an event with multiple dispatches (bubbled) to keep track of the * return values at each dispatch execution, but it does tend to make sense when * dealing with "direct" dispatches. * * @return The return value of executing the single dispatch. */ function executeDirectDispatch(event) { if (true) { validateEventDispatches(event); } var dispatchListener = event._dispatchListeners; var dispatchID = event._dispatchIDs; invariant( !Array.isArray(dispatchListener), 'executeDirectDispatch(...): Invalid `event`.' ); var res = dispatchListener ? dispatchListener(event, dispatchID) : null; event._dispatchListeners = null; event._dispatchIDs = null; return res; } /** * @param {SyntheticEvent} event * @return {bool} True iff number of dispatches accumulated is greater than 0. */ function hasDispatches(event) { return !!event._dispatchListeners; } /** * General utilities that are useful in creating custom Event Plugins. */ var EventPluginUtils = { isEndish: isEndish, isMoveish: isMoveish, isStartish: isStartish, executeDispatchesInOrder: executeDispatchesInOrder, executeDispatchesInOrderStopAtTrue: executeDispatchesInOrderStopAtTrue, executeDirectDispatch: executeDirectDispatch, hasDispatches: hasDispatches, executeDispatch: executeDispatch }; module.exports = EventPluginUtils; },{"./EventConstants":13,"./invariant":78}],18:[function(require,module,exports){ /** * Copyright 2013 Facebook, 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. * * @providesModule EventPropagators */ "use strict"; var CallbackRegistry = require("./CallbackRegistry"); var EventConstants = require("./EventConstants"); var accumulate = require("./accumulate"); var forEachAccumulated = require("./forEachAccumulated"); var getListener = CallbackRegistry.getListener; var PropagationPhases = EventConstants.PropagationPhases; /** * Injected dependencies: */ /** * - `InstanceHandle`: [required] Module that performs logical traversals of DOM * hierarchy given ids of the logical DOM elements involved. */ var injection = { InstanceHandle: null, injectInstanceHandle: function(InjectedInstanceHandle) { injection.InstanceHandle = InjectedInstanceHandle; if (true) { injection.validate(); } }, validate: function() { var invalid = !injection.InstanceHandle|| !injection.InstanceHandle.traverseTwoPhase || !injection.InstanceHandle.traverseEnterLeave; if (invalid) { throw new Error('InstanceHandle not injected before use!'); } } }; /** * Some event types have a notion of different registration names for different * "phases" of propagation. This finds listeners by a given phase. */ function listenerAtPhase(id, event, propagationPhase) { var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase]; return getListener(id, registrationName); } /** * Tags a `SyntheticEvent` with dispatched listeners. Creating this function * here, allows us to not have to bind or create functions for each event. * Mutating the event's members allows us to not have to create a wrapping * "dispatch" object that pairs the event with the listener. */ function accumulateDirectionalDispatches(domID, upwards, event) { if (true) { if (!domID) { throw new Error('Dispatching id must not be null'); } injection.validate(); } var phase = upwards ? PropagationPhases.bubbled : PropagationPhases.captured; var listener = listenerAtPhase(domID, event, phase); if (listener) { event._dispatchListeners = accumulate(event._dispatchListeners, listener); event._dispatchIDs = accumulate(event._dispatchIDs, domID); } } /** * Collect dispatches (must be entirely collected before dispatching - see unit * tests). Lazily allocate the array to conserve memory. We must loop through * each event and perform the traversal for each one. We can not perform a * single traversal for the entire collection of events because each event may * have a different target. */ function accumulateTwoPhaseDispatchesSingle(event) { if (event && event.dispatchConfig.phasedRegistrationNames) { injection.InstanceHandle.traverseTwoPhase( event.dispatchMarker, accumulateDirectionalDispatches, event ); } } /** * Accumulates without regard to direction, does not look for phased * registration names. Same as `accumulateDirectDispatchesSingle` but without * requiring that the `dispatchMarker` be the same as the dispatched ID. */ function accumulateDispatches(id, ignoredDirection, event) { if (event && event.dispatchConfig.registrationName) { var registrationName = event.dispatchConfig.registrationName; var listener = getListener(id, registrationName); if (listener) { event._dispatchListeners = accumulate(event._dispatchListeners, listener); event._dispatchIDs = accumulate(event._dispatchIDs, id); } } } /** * Accumulates dispatches on an `SyntheticEvent`, but only for the * `dispatchMarker`. * @param {SyntheticEvent} event */ function accumulateDirectDispatchesSingle(event) { if (event && event.dispatchConfig.registrationName) { accumulateDispatches(event.dispatchMarker, null, event); } } function accumulateTwoPhaseDispatches(events) { if (true) { injection.validate(); } forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle); } function accumulateEnterLeaveDispatches(leave, enter, fromID, toID) { if (true) { injection.validate(); } injection.InstanceHandle.traverseEnterLeave( fromID, toID, accumulateDispatches, leave, enter ); } function accumulateDirectDispatches(events) { if (true) { injection.validate(); } forEachAccumulated(events, accumulateDirectDispatchesSingle); } /** * A small set of propagation patterns, each of which will accept a small amount * of information, and generate a set of "dispatch ready event objects" - which * are sets of events that have already been annotated with a set of dispatched * listener functions/ids. The API is designed this way to discourage these * propagation strategies from actually executing the dispatches, since we * always want to collect the entire set of dispatches before executing event a * single one. * * @constructor EventPropagators */ var EventPropagators = { accumulateTwoPhaseDispatches: accumulateTwoPhaseDispatches, accumulateDirectDispatches: accumulateDirectDispatches, accumulateEnterLeaveDispatches: accumulateEnterLeaveDispatches, injection: injection }; module.exports = EventPropagators; },{"./CallbackRegistry":4,"./EventConstants":13,"./accumulate":61,"./forEachAccumulated":70}],19:[function(require,module,exports){ (function(){/** * Copyright 2013 Facebook, 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. * * @providesModule ExecutionEnvironment */ /*jslint evil: true */ "use strict"; var canUseDOM = typeof window !== 'undefined'; /** * Simple, lightweight module assisting with the detection and context of * Worker. Helps avoid circular dependencies and allows code to reason about * whether or not they are in a Worker, even if they never include the main * `ReactWorker` dependency. */ var ExecutionEnvironment = { canUseDOM: canUseDOM, canUseWorkers: typeof Worker !== 'undefined', isInWorker: !canUseDOM, // For now, this is true - might change in the future. global: new Function('return this;')() }; module.exports = ExecutionEnvironment; })() },{}],20:[function(require,module,exports){ /** * Copyright 2013 Facebook, 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. * * @providesModule MobileSafariClickEventPlugin * @typechecks static-only */ "use strict"; var EventConstants = require("./EventConstants"); var emptyFunction = require("./emptyFunction"); var topLevelTypes = EventConstants.topLevelTypes; /** * Mobile Safari does not fire properly bubble click events on non-interactive * elements, which means delegated click listeners do not fire. The workaround * for this bug involves attaching an empty click listener on the target node. * * This particular plugin works around the bug by attaching an empty click * listener on `touchstart` (which does fire on every element). */ var MobileSafariClickEventPlugin = { eventTypes: null, /** * @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) { if (topLevelType === topLevelTypes.topTouchStart) { var target = nativeEvent.target; if (target && !target.onclick) { target.onclick = emptyFunction; } } } }; module.exports = MobileSafariClickEventPlugin; },{"./EventConstants":13,"./emptyFunction":66}],21:[function(require,module,exports){ /** * Copyright 2013 Facebook, 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. * * @providesModule PooledClass */ "use strict"; /** * Static poolers. Several custom versions for each potential number of * arguments. A completely generic pooler is easy to implement, but would * require accessing the `arguments` object. In each of these, `this` refers to * the Class itself, not an instance. If any others are needed, simply add them * here, or in their own files. */ var oneArgumentPooler = function(copyFieldsFrom) { var Klass = this; if (Klass.instancePool.length) { var instance = Klass.instancePool.pop(); Klass.call(instance, copyFieldsFrom); return instance; } else { return new Klass(copyFieldsFrom); } }; var twoArgumentPooler = function(a1, a2) { var Klass = this; if (Klass.instancePool.length) { var instance = Klass.instancePool.pop(); Klass.call(instance, a1, a2); return instance; } else { return new Klass(a1, a2); } }; var threeArgumentPooler = function(a1, a2, a3) { var Klass = this; if (Klass.instancePool.length) { var instance = Klass.instancePool.pop(); Klass.call(instance, a1, a2, a3); return instance; } else { return new Klass(a1, a2, a3); } }; var fiveArgumentPooler = function(a1, a2, a3, a4, a5) { var Klass = this; if (Klass.instancePool.length) { var instance = Klass.instancePool.pop(); Klass.call(instance, a1, a2, a3, a4, a5); return instance; } else { return new Klass(a1, a2, a3, a4, a5); } }; var standardReleaser = function(instance) { var Klass = this; if (instance.destructor) { instance.destructor(); } if (Klass.instancePool.length < Klass.poolSize) { Klass.instancePool.push(instance); } }; var DEFAULT_POOL_SIZE = 10; var DEFAULT_POOLER = oneArgumentPooler; /** * Augments `CopyConstructor` to be a poolable class, augmenting only the class * itself (statically) not adding any prototypical fields. Any CopyConstructor * you give this may have a `poolSize` property, and will look for a * prototypical `destructor` on instances (optional). * * @param {Function} CopyConstructor Constructor that can be used to reset. * @param {Function} pooler Customizable pooler. */ var addPoolingTo = function(CopyConstructor, pooler) { var NewKlass = CopyConstructor; NewKlass.instancePool = []; NewKlass.getPooled = pooler || DEFAULT_POOLER; if (!NewKlass.poolSize) { NewKlass.poolSize = DEFAULT_POOL_SIZE; } NewKlass.release = standardReleaser; return NewKlass; }; var PooledClass = { addPoolingTo: addPoolingTo, oneArgumentPooler: oneArgumentPooler, twoArgumentPooler: twoArgumentPooler, threeArgumentPooler: threeArgumentPooler, fiveArgumentPooler: fiveArgumentPooler }; module.exports = PooledClass; },{}],22:[function(require,module,exports){ /** * Copyright 2013 Facebook, 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. * * @providesModule React */ "use strict"; var ReactCompositeComponent = require("./ReactCompositeComponent"); var ReactComponent = require("./ReactComponent"); var ReactDOM = require("./ReactDOM"); var ReactMount = require("./ReactMount"); var ReactPropTypes = require("./ReactPropTypes"); var ReactServerRendering = require("./ReactServerRendering"); var ReactDefaultInjection = require("./ReactDefaultInjection"); ReactDefaultInjection.inject(); var React = { DOM: ReactDOM, PropTypes: ReactPropTypes, initializeTouchEvents: function(shouldUseTouch) { ReactMount.useTouchEvents = shouldUseTouch; }, autoBind: ReactCompositeComponent.autoBind, createClass: ReactCompositeComponent.createClass, constructAndRenderComponent: ReactMount.constructAndRenderComponent, constructAndRenderComponentByID: ReactMount.constructAndRenderComponentByID, renderComponent: ReactMount.renderComponent, renderComponentToString: ReactServerRendering.renderComponentToString, unmountAndReleaseReactRootNode: ReactMount.unmountAndReleaseReactRootNode, isValidComponent: ReactComponent.isValidComponent }; module.exports = React; },{"./ReactComponent":23,"./ReactCompositeComponent":24,"./ReactDOM":26,"./ReactDefaultInjection":33,"./ReactMount":39,"./ReactPropTypes":45,"./ReactServerRendering":47}],23:[function(require,module,exports){ /** * Copyright 2013 Facebook, 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. * * @providesModule ReactComponent */ /*jslint evil: true */ "use strict"; var getReactRootElementInContainer = require("./getReactRootElementInContainer"); var ReactCurrentOwner = require("./ReactCurrentOwner"); var ReactDOMIDOperations = require("./ReactDOMIDOperations"); var ReactMarkupChecksum = require("./ReactMarkupChecksum"); var ReactMount = require("./ReactMount"); var ReactOwner = require("./ReactOwner"); var ReactReconcileTransaction = require("./ReactReconcileTransaction"); var ReactUpdates = require("./ReactUpdates"); var invariant = require("./invariant"); var keyMirror = require("./keyMirror"); var merge = require("./merge"); /** * Prop key that references a component's owner. * @private */ var OWNER = '{owner}'; /** * Props key that determines if a component's key was already validated. * @private */ var IS_KEY_VALIDATED = '{is.key.validated}'; /** * Every React component is in one of these life cycles. */ var ComponentLifeCycle = keyMirror({ /** * Mounted components have a DOM node representation and are capable of * receiving new props. */ MOUNTED: null, /** * Unmounted components are inactive and cannot receive new props. */ UNMOUNTED: null }); /** * Warn if there's no key explicitly set on dynamic arrays of children. * This allows us to keep track of children between updates. */ var ownerHasWarned = {}; /** * 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 hasn't already been validated, are required to * have a "key" property assigned to it. * * @internal * @param {ReactComponent} component Component that requires a key. */ function validateExplicitKey(component) { if (component[IS_KEY_VALIDATED] || component.props.key != null) { return; } component[IS_KEY_VALIDATED] = true; // We can't provide friendly warnings for top level components. if (!ReactCurrentOwner.current) { return; } // Name of the component whose render method tried to pass children. var currentName = ReactCurrentOwner.current.constructor.displayName; if (ownerHasWarned.hasOwnProperty(currentName)) { return; } ownerHasWarned[currentName] = true; var message = 'Each child in an array should have a unique "key" prop. ' + 'Check the render method of ' + currentName + '.'; if (!component.isOwnedBy(ReactCurrentOwner.current)) { // Name of the component that originally created this child. var childOwnerName = component.props[OWNER] && component.props[OWNER].constructor.displayName; // 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. message += ' It was passed a child from ' + childOwnerName + '.'; } console.warn(message); } /** * Ensure that every component either is passed in a static location or, if * if it's passed in an array, has an explicit key property defined. * * @internal * @param {*} component Statically passed child of any type. * @return {boolean} */ function validateChildKeys(component) { if (Array.isArray(component)) { for (var i = 0; i < component.length; i++) { var child = component[i]; if (ReactComponent.isValidComponent(child)) { validateExplicitKey(child); } } } else if (ReactComponent.isValidComponent(component)) { // This component was passed in a valid location. component[IS_KEY_VALIDATED] = true; } } /** * Components are the basic units of composition in React. * * Every component accepts a set of keyed input parameters known as "props" that * are initialized by the constructor. Once a component is mounted, the props * can be mutated using `setProps` or `replaceProps`. * * Every component is capable of the following operations: * * `mountComponent` * Initializes the component, renders markup, and registers event listeners. * * `receiveProps` * Updates the rendered DOM nodes given a new set of props. * * `unmountComponent` * Releases any resources allocated by this component. * * Components can also be "owned" by other components. Being owned by another * component means being constructed by that component. This is different from * being the child of a component, which means having a DOM representation that * is a child of the DOM representation of that component. * * @class ReactComponent */ var ReactComponent = { /** * @param {?object} object * @return {boolean} True if `object` is a valid component. * @final */ isValidComponent: function(object) { return !!( object && typeof object.mountComponentIntoNode === 'function' && typeof object.receiveProps === 'function' ); }, /** * 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} * @internal */ getKey: function(component, index) { if (component && component.props && component.props.key != null) { // Explicit key return '' + component.props.key; } // Implicit key determined by the index in the set return '' + index; }, /** * @internal */ LifeCycle: ComponentLifeCycle, /** * React references `ReactDOMIDOperations` using this property in order to * allow dependency injection. * * @internal */ DOMIDOperations: ReactDOMIDOperations, /** * React references `ReactReconcileTransaction` using this property in order * to allow dependency injection. * * @internal */ ReactReconcileTransaction: ReactReconcileTransaction, /** * @param {object} DOMIDOperations * @final */ setDOMOperations: function(DOMIDOperations) { ReactComponent.DOMIDOperations = DOMIDOperations; }, /** * @param {Transaction} ReactReconcileTransaction * @final */ setReactReconcileTransaction: function(ReactReconcileTransaction) { ReactComponent.ReactReconcileTransaction = ReactReconcileTransaction; }, /** * Base functionality for every ReactComponent constructor. * * @lends {ReactComponent.prototype} */ Mixin: { /** * Checks whether or not this component is mounted. * * @return {boolean} True if mounted, false otherwise. * @final * @protected */ isMounted: function() { return this._lifeCycleState === ComponentLifeCycle.MOUNTED; }, /** * Returns the DOM node rendered by this component. * * @return {DOMElement} The root node of this component. * @final * @protected */ getDOMNode: function() { invariant( this.isMounted(), 'getDOMNode(): A component must be mounted to have a DOM node.' ); return ReactMount.getNode(this._rootNodeID); }, /** * Sets a subset of the props. * * @param {object} partialProps Subset of the next props. * @param {?function} callback Called after props are updated. * @final * @public */ setProps: function(partialProps, callback) { // Merge with `_pendingProps` if it exists, otherwise with existing props. this.replaceProps( merge(this._pendingProps || this.props, partialProps), callback ); }, /** * Replaces all of the props. * * @param {object} props New props. * @param {?function} callback Called after props are updated. * @final * @public */ replaceProps: function(props, callback) { invariant( !this.props[OWNER], 'replaceProps(...): You called `setProps` or `replaceProps` on a ' + 'component with an owner. This is an anti-pattern since props will ' + 'get reactively updated when rendered. Instead, change the owner\'s ' + '`render` method to pass the correct value as props to the component ' + 'where it is created.' ); this._pendingProps = props; ReactUpdates.enqueueUpdate(this, callback); }, /** * Base constructor for all React component. * * Subclasses that override this method should make sure to invoke * `ReactComponent.Mixin.construct.call(this, ...)`. * * @param {?object} initialProps * @param {*} children * @internal */ construct: function(initialProps, children) { this.props = initialProps || {}; // Record the component responsible for creating this component. this.props[OWNER] = ReactCurrentOwner.current; // All components start unmounted. this._lifeCycleState = ComponentLifeCycle.UNMOUNTED; this._pendingProps = null; this._pendingCallbacks = null; // Children can be more than one argument var childrenLength = arguments.length - 1; if (childrenLength === 1) { if (true) { validateChildKeys(children); } this.props.children = children; } else if (childrenLength > 1) { var childArray = Array(childrenLength); for (var i = 0; i < childrenLength; i++) { if (true) { validateChildKeys(arguments[i + 1]); } childArray[i] = arguments[i + 1]; } this.props.children = childArray; } }, /** * Initializes the component, renders markup, and registers event listeners. * * NOTE: This does not insert any nodes into the DOM. * * Subclasses that override this method should make sure to invoke * `ReactComponent.Mixin.mountComponent.call(this, ...)`. * * @param {string} rootID DOM ID of the root node. * @param {ReactReconcileTransaction} transaction * @return {?string} Rendered markup to be inserted into the DOM. * @internal */ mountComponent: function(rootID, transaction) { invariant( !this.isMounted(), 'mountComponent(%s, ...): Can only mount an unmounted component.', rootID ); var props = this.props; if (props.ref != null) { ReactOwner.addComponentAsRefTo(this, props.ref, props[OWNER]); } this._rootNodeID = rootID; this._lifeCycleState = ComponentLifeCycle.MOUNTED; // Effectively: return ''; }, /** * Releases any resources allocated by `mountComponent`. * * NOTE: This does not remove any nodes from the DOM. * * Subclasses that override this method should make sure to invoke * `ReactComponent.Mixin.unmountComponent.call(this)`. * * @internal */ unmountComponent: function() { invariant( this.isMounted(), 'unmountComponent(): Can only unmount a mounted component.' ); var props = this.props; if (props.ref != null) { ReactOwner.removeComponentAsRefFrom(this, props.ref, props[OWNER]); } ReactMount.purgeID(this._rootNodeID); this._rootNodeID = null; this._lifeCycleState = ComponentLifeCycle.UNMOUNTED; }, /** * Updates the rendered DOM nodes given a new set of props. * * Subclasses that override this method should make sure to invoke * `ReactComponent.Mixin.receiveProps.call(this, ...)`. * * @param {object} nextProps Next set of properties. * @param {ReactReconcileTransaction} transaction * @internal */ receiveProps: function(nextProps, transaction) { invariant( this.isMounted(), 'receiveProps(...): Can only update a mounted component.' ); this._pendingProps = nextProps; this._performUpdateIfNecessary(transaction); }, /** * Call `_performUpdateIfNecessary` within a new transaction. * * @param {ReactReconcileTransaction} transaction * @internal */ performUpdateIfNecessary: function() { var transaction = ReactComponent.ReactReconcileTransaction.getPooled(); transaction.perform(this._performUpdateIfNecessary, this, transaction); ReactComponent.ReactReconcileTransaction.release(transaction); }, /** * If `_pendingProps` is set, update the component. * * @param {ReactReconcileTransaction} transaction * @internal */ _performUpdateIfNecessary: function(transaction) { if (this._pendingProps == null) { return; } var prevProps = this.props; this.props = this._pendingProps; this._pendingProps = null; this.updateComponent(transaction, prevProps); }, /** * Updates the component's currently mounted representation. * * @param {ReactReconcileTransaction} transaction * @param {object} prevProps * @internal */ updateComponent: function(transaction, prevProps) { var props = this.props; // If either the owner or a `ref` has changed, make sure the newest owner // has stored a reference to `this`, and the previous owner (if different) // has forgotten the reference to `this`. if (props[OWNER] !== prevProps[OWNER] || props.ref !== prevProps.ref) { if (prevProps.ref != null) { ReactOwner.removeComponentAsRefFrom( this, prevProps.ref, prevProps[OWNER] ); } // Correct, even if the owner is the same, and only the ref has changed. if (props.ref != null) { ReactOwner.addComponentAsRefTo(this, props.ref, props[OWNER]); } } }, /** * Mounts this component and inserts it into the DOM. * * @param {string} rootID DOM ID of the root node. * @param {DOMElement} container DOM element to mount into. * @param {boolean} shouldReuseMarkup If true, do not insert markup * @final * @internal * @see {ReactMount.renderComponent} */ mountComponentIntoNode: function(rootID, container, shouldReuseMarkup) { var transaction = ReactComponent.ReactReconcileTransaction.getPooled(); transaction.perform( this._mountComponentIntoNode, this, rootID, container, transaction, shouldReuseMarkup ); ReactComponent.ReactReconcileTransaction.release(transaction); }, /** * @param {string} rootID DOM ID of the root node. * @param {DOMElement} container DOM element to mount into. * @param {ReactReconcileTransaction} transaction * @param {boolean} shouldReuseMarkup If true, do not insert markup * @final * @private */ _mountComponentIntoNode: function( rootID, container, transaction, shouldReuseMarkup) { invariant( container && container.nodeType === 1, 'mountComponentIntoNode(...): Target container is not a DOM element.' ); var markup = this.mountComponent(rootID, transaction); if (shouldReuseMarkup) { if (ReactMarkupChecksum.canReuseMarkup( markup, getReactRootElementInContainer(container))) { return; } else { if (true) { console.warn( 'React attempted to use reuse markup in a container but the ' + 'checksum was invalid. This generally means that you are using ' + 'server rendering and the markup generated on the server was ' + 'not what the client was expecting. React injected new markup ' + 'to compensate which works but you have lost many of the ' + 'benefits of server rendering. Instead, figure out why the ' + 'markup being generated is different on the client or server.' ); } } } // Asynchronously inject markup by ensuring that the container is not in // the document when settings its `innerHTML`. var parent = container.parentNode; if (parent) { var next = container.nextSibling; parent.removeChild(container); container.innerHTML = markup; if (next) { parent.insertBefore(container, next); } else { parent.appendChild(container); } } else { container.innerHTML = markup; } }, /** * Unmounts this component and removes it from the DOM. * * @param {DOMElement} container DOM element to unmount from. * @final * @internal * @see {ReactMount.unmountAndReleaseReactRootNode} */ unmountComponentFromNode: function(container) { this.unmountComponent(); // http://jsperf.com/emptying-a-node while (container.lastChild) { container.removeChild(container.lastChild); } }, /** * Checks if this component is owned by the supplied `owner` component. * * @param {ReactComponent} owner Component to check. * @return {boolean} True if `owners` owns this component. * @final * @internal */ isOwnedBy: function(owner) { return this.props[OWNER] === owner; }, /** * Gets another component, that shares the same owner as this one, by ref. * * @param {string} ref of a sibling Component. * @return {?ReactComponent} the actual sibling Component. * @final * @internal */ getSiblingByRef: function(ref) { var owner = this.props[OWNER]; if (!owner || !owner.refs) { return null; } return owner.refs[ref]; } } }; module.exports = ReactComponent; },{"./ReactCurrentOwner":25,"./ReactDOMIDOperations":28,"./ReactMarkupChecksum":38,"./ReactMount":39,"./ReactOwner":43,"./ReactReconcileTransaction":46,"./ReactUpdates":49,"./getReactRootElementInContainer":73,"./invariant":78,"./keyMirror":81,"./merge":84}],24:[function(require,module,exports){ (function(){/** * Copyright 2013 Facebook, 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. * * @providesModule ReactCompositeComponent */ "use strict"; var ReactComponent = require("./ReactComponent"); var ReactCurrentOwner = require("./ReactCurrentOwner"); var ReactOwner = require("./ReactOwner"); var ReactPropTransferer = require("./ReactPropTransferer"); var ReactUpdates = require("./ReactUpdates"); var invariant = require("./invariant"); var keyMirror = require("./keyMirror"); var merge = require("./merge"); var mixInto = require("./mixInto"); /** * 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 }); /** * 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
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, /** * Definition of prop types for this component. * * @type {object} * @optional */ propTypes: SpecPolicy.DEFINE_ONCE, // ==== 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_ONCE, /** * 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_ONCE, /** * 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
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) { * 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 and state. * * Use this as an opportunity to `return false` when you're certain that the * transition to the new props and state will not require a component update. * * shouldComponentUpdate: function(nextProps, nextState) { * return !equal(nextProps, this.props) || !equal(nextState, this.state); * } * * @param {object} nextProps * @param {?object} nextState * @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` and `this.state` to `nextProps` and `nextState`. * * 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 {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 {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 in the specification when defining classes * using `React.createClass`, they will not be on the component's prototype. */ 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]); } } }, propTypes: function(Constructor, propTypes) { Constructor.propTypes = propTypes; } }; function validateMethodOverride(proto, name) { var specPolicy = ReactCompositeComponentInterface[name]; // Disallow overriding of base class methods unless explicitly allowed. if (ReactCompositeComponentMixin.hasOwnProperty(name)) { 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 ); } // Disallow defining methods more than once unless explicitly allowed. if (proto.hasOwnProperty(name)) { invariant( specPolicy === SpecPolicy.DEFINE_MANY, 'ReactCompositeComponentInterface: You are attempting to define ' + '`%s` on your component more than once. This conflict may be due ' + 'to a mixin.', name ); } } function validateLifeCycleOnReplaceState(instance) { var compositeLifeCycleState = instance._compositeLifeCycleState; invariant( instance.isMounted() || compositeLifeCycleState === CompositeLifeCycle.MOUNTING, 'replaceState(...): Can only update a mounted or mounting component.' ); invariant( compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE && compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING, 'replaceState(...): Cannot update while unmounting component or during ' + 'an existing state transition (such as within `render`).' ); } /** * Custom version of `mixInto` which handles policy validation and reserved * specification keys when building `ReactCompositeComponent` classses. */ function mixSpecIntoComponent(Constructor, spec) { var proto = Constructor.prototype; for (var name in spec) { var property = spec[name]; if (!spec.hasOwnProperty(name) || !property) { continue; } 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 = name in ReactCompositeComponentInterface; var isInherited = name in proto; var markedDontBind = property.__reactDontBind; var isFunction = typeof property === 'function'; var shouldAutoBind = isFunction && !isCompositeComponentMethod && !isInherited && !markedDontBind; if (shouldAutoBind) { if (!proto.__reactAutoBindMap) { proto.__reactAutoBindMap = {}; } proto.__reactAutoBindMap[name] = property; proto[name] = property; } else { if (isInherited) { // For methods which are defined more than once, call the existing // methods before calling the new property. proto[name] = createChainedFunction(proto[name], property); } else { proto[name] = property; } } } } } /** * 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-|RECEIV|-0-|RECEIV|-0-|RECEIV|-0-| UN |--->0 | * | | | |PROPS | | PROPS| | STATE| |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, /** * Components that are mounted and receiving new state are guarded against * additional state changes. */ RECEIVING_STATE: null }); /** * @lends {ReactCompositeComponent.prototype} */ var ReactCompositeComponentMixin = { /** * Base constructor for all composite component. * * @param {?object} initialProps * @param {*} children * @final * @internal */ construct: function(initialProps, children) { // Children can be either an array or more than one argument ReactComponent.Mixin.construct.apply(this, arguments); this.state = null; this._pendingState = 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} transaction * @return {?string} Rendered markup to be inserted into the DOM. * @final * @internal */ mountComponent: function(rootID, transaction) { ReactComponent.Mixin.mountComponent.call(this, rootID, transaction); this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING; this._defaultProps = this.getDefaultProps ? this.getDefaultProps() : null; this._processProps(this.props); if (this.__reactAutoBindMap) { this._bindAutoBindMethods(); } this.state = this.getInitialState ? this.getInitialState() : null; 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 = this._renderValidatedComponent(); // Done with mounting, `setState` will now trigger UI changes. this._compositeLifeCycleState = null; var markup = this._renderedComponent.mountComponent(rootID, transaction); if (this.componentDidMount) { transaction.getReactOnDOMReady().enqueue(this, this.componentDidMount); } 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._defaultProps = null; ReactComponent.Mixin.unmountComponent.call(this); this._renderedComponent.unmountComponent(); this._renderedComponent = null; if (this.refs) { this.refs = null; } // 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) { // Merge with `_pendingState` if it exists, otherwise with existing state. this.replaceState( merge(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; ReactUpdates.enqueueUpdate(this, callback); }, /** * Processes props by setting default values for unspecified props and * asserting that the props are valid. * * @param {object} props * @private */ _processProps: function(props) { var propName; var defaultProps = this._defaultProps; for (propName in defaultProps) { if (!(propName in props)) { props[propName] = defaultProps[propName]; } } var propTypes = this.constructor.propTypes; if (propTypes) { var componentName = this.constructor.displayName; for (propName in propTypes) { var checkProp = propTypes[propName]; if (checkProp) { checkProp(props, propName, componentName); } } } }, performUpdateIfNecessary: function() { 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; } ReactComponent.Mixin.performUpdateIfNecessary.call(this); }, /** * If any of `_pendingProps`, `_pendingState`, or `_pendingForceUpdate` is * set, update the component. * * @param {ReactReconcileTransaction} transaction * @internal */ _performUpdateIfNecessary: function(transaction) { if (this._pendingProps == null && this._pendingState == null && !this._pendingForceUpdate) { return; } var nextProps = this.props; if (this._pendingProps != null) { nextProps = this._pendingProps; this._processProps(nextProps); this._pendingProps = null; this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS; if (this.componentWillReceiveProps) { this.componentWillReceiveProps(nextProps, transaction); } } this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_STATE; var nextState = this._pendingState || this.state; this._pendingState = null; if (this._pendingForceUpdate || !this.shouldComponentUpdate || this.shouldComponentUpdate(nextProps, nextState)) { this._pendingForceUpdate = false; // Will set `this.props` and `this.state`. this._performComponentUpdate(nextProps, nextState, transaction); } else { // If it's determined that a component should not update, we still want // to set props and state. this.props = nextProps; this.state = nextState; } this._compositeLifeCycleState = null; }, /** * Merges new props and state, notifies delegate methods of update and * performs update. * * @param {object} nextProps Next object to set as properties. * @param {?object} nextState Next object to set as state. * @param {ReactReconcileTransaction} transaction * @private */ _performComponentUpdate: function(nextProps, nextState, transaction) { var prevProps = this.props; var prevState = this.state; if (this.componentWillUpdate) { this.componentWillUpdate(nextProps, nextState, transaction); } this.props = nextProps; this.state = nextState; this.updateComponent(transaction, prevProps, prevState); if (this.componentDidUpdate) { transaction.getReactOnDOMReady().enqueue( this, this.componentDidUpdate.bind(this, prevProps, prevState) ); } }, /** * 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 {object} prevProps * @param {?object} prevState * @internal * @overridable */ updateComponent: function(transaction, prevProps, prevState) { ReactComponent.Mixin.updateComponent.call(this, transaction, prevProps); var currentComponent = this._renderedComponent; var nextComponent = this._renderValidatedComponent(); if (currentComponent.constructor === nextComponent.constructor) { currentComponent.receiveProps(nextComponent.props, transaction); } else { // These two IDs are actually the same! But nothing should rely on that. var thisID = this._rootNodeID; var currentComponentID = currentComponent._rootNodeID; currentComponent.unmountComponent(); var nextMarkup = nextComponent.mountComponent(thisID, transaction); ReactComponent.DOMIDOperations.dangerouslyReplaceNodeWithMarkupByID( currentComponentID, nextMarkup ); this._renderedComponent = nextComponent; } }, /** * 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; invariant( this.isMounted() || compositeLifeCycleState === CompositeLifeCycle.MOUNTING, 'forceUpdate(...): Can only force an update on mounted or mounting ' + 'components.' ); invariant( compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE && compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING, 'forceUpdate(...): Cannot force an update while unmounting component ' + 'or during an existing state transition (such as within `render`).' ); this._pendingForceUpdate = true; ReactUpdates.enqueueUpdate(this, callback); }, /** * @private */ _renderValidatedComponent: function() { var renderedComponent; ReactCurrentOwner.current = this; try { renderedComponent = this.render(); } catch (error) { // IE8 requires `catch` in order to use `finally`. throw error; } finally { ReactCurrentOwner.current = null; } invariant( ReactComponent.isValidComponent(renderedComponent), '%s.render(): A valid ReactComponent must be returned.', this.constructor.displayName || 'ReactCompositeComponent' ); 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(method); } }, /** * Binds a method to the component. * * @param {function} method Method to be bound. * @private */ _bindAutoBindMethod: function(method) { var component = this; var boundMethod = function() { return method.apply(component, arguments); }; if (true) { var componentName = component.constructor.displayName; var _bind = boundMethod.bind; boundMethod.bind = function(newThis) { // 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) { console.warn( 'bind(): React component methods may only be bound to the ' + 'component instance. See ' + componentName ); } else if (arguments.length === 1) { 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; } return _bind.apply(boundMethod, arguments); }; } return boundMethod; } }; var ReactCompositeComponentBase = function() {}; mixInto(ReactCompositeComponentBase, ReactComponent.Mixin); mixInto(ReactCompositeComponentBase, ReactOwner.Mixin); mixInto(ReactCompositeComponentBase, ReactPropTransferer.Mixin); mixInto(ReactCompositeComponentBase, 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() {}; Constructor.prototype = new ReactCompositeComponentBase(); Constructor.prototype.constructor = Constructor; mixSpecIntoComponent(Constructor, spec); invariant( Constructor.prototype.render, 'createClass(...): Class specification must implement a `render` method.' ); // Reduce time spent doing lookups by setting these on the prototype. for (var methodName in ReactCompositeComponentInterface) { if (!Constructor.prototype[methodName]) { Constructor.prototype[methodName] = null; } } var ConvenienceConstructor = function(props, children) { var instance = new Constructor(); instance.construct.apply(instance, arguments); return instance; }; ConvenienceConstructor.componentConstructor = Constructor; ConvenienceConstructor.originalSpec = spec; return ConvenienceConstructor; }, /** * TODO: Delete this when all callers have been updated to rely on this * behavior being the default. * * Backwards compatible stub for what is now the default behavior. * @param {function} method Method to be bound. * @public */ autoBind: function(method) { if (true) { console.warn( 'React.autoBind() is now deprecated. All React component methods ' + 'are auto bound by default, so React.autoBind() is a no-op. It ' + 'will be removed in the next version of React' ); } return method; } }; module.exports = ReactCompositeComponent; })() },{"./ReactComponent":23,"./ReactCurrentOwner":25,"./ReactOwner":43,"./ReactPropTransferer":44,"./ReactUpdates":49,"./invariant":78,"./keyMirror":81,"./merge":84,"./mixInto":87}],25:[function(require,module,exports){ /** * Copyright 2013 Facebook, 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. * * @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; },{}],26:[function(require,module,exports){ /** * Copyright 2013 Facebook, 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. * * @providesModule ReactDOM * @typechecks static-only */ "use strict"; var ReactNativeComponent = require("./ReactNativeComponent"); var mergeInto = require("./mergeInto"); var objMapKeyVal = require("./objMapKeyVal"); /** * 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. * * @param {string} tag Tag name (e.g. `div`). * @param {boolean} omitClose True if the close tag should be omitted. * @private */ function createDOMComponentClass(tag, omitClose) { var Constructor = function() {}; Constructor.prototype = new ReactNativeComponent(tag, omitClose); Constructor.prototype.constructor = Constructor; var ConvenienceConstructor = function(props, children) { var instance = new Constructor(); instance.construct.apply(instance, arguments); return instance; }; ConvenienceConstructor.componentConstructor = Constructor; return ConvenienceConstructor; } /** * Creates a mapping from supported HTML tags to `ReactNativeComponent` classes. * This is also accessible via `React.DOM`. * * @public */ var ReactDOM = objMapKeyVal({ a: false, abbr: false, address: false, area: false, article: false, aside: false, audio: false, b: false, base: false, bdi: false, bdo: false, big: false, blockquote: false, body: false, br: true, button: false, canvas: false, caption: false, cite: false, code: false, col: true, colgroup: false, data: false, datalist: false, dd: false, del: false, details: false, dfn: false, div: false, dl: false, dt: false, em: false, embed: true, fieldset: false, figcaption: false, figure: false, footer: false, form: false, // NOTE: Injected, see `ReactDOMForm`. h1: false, h2: false, h3: false, h4: false, h5: false, h6: false, head: false, header: false, hr: true, html: false, i: false, iframe: false, img: true, input: true, ins: false, kbd: false, keygen: true, label: false, legend: false, li: false, link: false, main: false, map: false, mark: false, menu: false, menuitem: false, // NOTE: Close tag should be omitted, but causes problems. meta: true, meter: false, nav: false, noscript: false, object: false, ol: false, optgroup: false, option: false, output: false, p: false, param: true, pre: false, progress: false, q: false, rp: false, rt: false, ruby: false, s: false, samp: false, script: false, section: false, select: false, small: false, source: false, span: false, strong: false, style: false, sub: false, summary: false, sup: false, table: false, tbody: false, td: false, textarea: false, // NOTE: Injected, see `ReactDOMTextarea`. tfoot: false, th: false, thead: false, time: false, title: false, tr: false, track: true, u: false, ul: false, 'var': false, video: false, wbr: false, // SVG circle: false, g: false, line: false, path: false, polyline: false, rect: false, svg: false, text: false }, createDOMComponentClass); var injection = { injectComponentClasses: function(componentClasses) { mergeInto(ReactDOM, componentClasses); } }; ReactDOM.injection = injection; module.exports = ReactDOM; },{"./ReactNativeComponent":41,"./mergeInto":86,"./objMapKeyVal":88}],27:[function(require,module,exports){ /** * Copyright 2013 Facebook, 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. * * @providesModule ReactDOMForm */ "use strict"; var ReactCompositeComponent = require("./ReactCompositeComponent"); var ReactDOM = require("./ReactDOM"); var ReactEventEmitter = require("./ReactEventEmitter"); var EventConstants = require("./EventConstants"); // Store a reference to the
`ReactNativeComponent`. var form = ReactDOM.form; /** * Since onSubmit doesn't bubble OR capture on the top level in IE8, we need * to capture it on the element itself. There are lots of hacks we could * do to accomplish this, but the most reliable is to make a * composite component and use `componentDidMount` to attach the event handlers. */ var ReactDOMForm = ReactCompositeComponent.createClass({ 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 this.transferPropsTo(form(null, this.props.children)); }, componentDidMount: function(node) { ReactEventEmitter.trapBubbledEvent( EventConstants.topLevelTypes.topSubmit, 'submit', node ); } }); module.exports = ReactDOMForm; },{"./EventConstants":13,"./ReactCompositeComponent":24,"./ReactDOM":26,"./ReactEventEmitter":34}],28:[function(require,module,exports){ (function(){/** * Copyright 2013 Facebook, 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. * * @providesModule ReactDOMIDOperations * @typechecks static-only */ /*jslint evil: true */ "use strict"; var CSSPropertyOperations = require("./CSSPropertyOperations"); var DOMChildrenOperations = require("./DOMChildrenOperations"); var DOMPropertyOperations = require("./DOMPropertyOperations"); var ReactMount = require("./ReactMount"); var getTextContentAccessor = require("./getTextContentAccessor"); var invariant = require("./invariant"); /** * 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()`.' }; /** * The DOM property to use when setting text content. * * @type {string} * @private */ var textContentAccessor = getTextContentAccessor() || 'NA'; /** * Operations used to process updates to DOM nodes. This is made injectable via * `ReactComponent.DOMIDOperations`. */ 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: function(id, name, value) { var node = ReactMount.getNode(id); invariant( !INVALID_PROPERTY_ERRORS.hasOwnProperty(name), 'updatePropertyByID(...): %s', INVALID_PROPERTY_ERRORS[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: function(id, name, value) { var node = ReactMount.getNode(id); invariant( !INVALID_PROPERTY_ERRORS.hasOwnProperty(name), 'updatePropertyByID(...): %s', INVALID_PROPERTY_ERRORS[name] ); DOMPropertyOperations.deleteValueForProperty(node, name, value); }, /** * This should almost never be used instead of `updatePropertyByID()` due to * the extra object allocation required by the API. That said, this is useful * for batching up several operations across worker thread boundaries. * * @param {string} id ID of the node to update. * @param {object} properties A mapping of valid property names. * @internal * @see {ReactDOMIDOperations.updatePropertyByID} */ updatePropertiesByID: function(id, properties) { for (var name in properties) { if (!properties.hasOwnProperty(name)) { continue; } ReactDOMIDOperations.updatePropertiesByID(id, name, properties[name]); } }, /** * 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: function(id, styles) { var node = ReactMount.getNode(id); CSSPropertyOperations.setValueForStyles(node, styles); }, /** * Updates a DOM node's innerHTML set by `props.dangerouslySetInnerHTML`. * * @param {string} id ID of the node to update. * @param {object} html An HTML object with the `__html` property. * @internal */ updateInnerHTMLByID: function(id, html) { var node = ReactMount.getNode(id); // HACK: IE8- normalize whitespace in innerHTML, removing leading spaces. // @see quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html node.innerHTML = (html && html.__html || '').replace(/^ /g, ' '); }, /** * 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: function(id, content) { var node = ReactMount.getNode(id); node[textContentAccessor] = 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: function(id, markup) { var node = ReactMount.getNode(id); DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup(node, markup); }, /** * TODO: We only actually *need* to purge the cache when we remove elements. * Detect if any elements were removed instead of blindly purging. */ manageChildrenByParentID: function(parentID, domOperations) { var parent = ReactMount.getNode(parentID); DOMChildrenOperations.manageChildren(parent, domOperations); } }; module.exports = ReactDOMIDOperations; })() },{"./CSSPropertyOperations":3,"./DOMChildrenOperations":6,"./DOMPropertyOperations":8,"./ReactMount":39,"./getTextContentAccessor":74,"./invariant":78}],29:[function(require,module,exports){ /** * Copyright 2013 Facebook, 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. * * @providesModule ReactDOMInput */ "use strict"; var DOMPropertyOperations = require("./DOMPropertyOperations"); var ReactCompositeComponent = require("./ReactCompositeComponent"); var ReactDOM = require("./ReactDOM"); var merge = require("./merge"); // Store a reference to the `ReactNativeComponent`. var input = ReactDOM.input; /** * Implements an 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({ getInitialState: function() { return { checked: this.props.defaultChecked || false, value: this.props.defaultValue || '' }; }, shouldComponentUpdate: function() { // Defer any updates to this component during the `onChange` handler. return !this._isChanging; }, getChecked: function() { return this.props.checked != null ? this.props.checked : this.state.checked; }, getValue: function() { // Cast `this.props.value` to a string so equality checks pass. return this.props.value != null ? '' + this.props.value : this.state.value; }, render: function() { // Clone `this.props` so we don't mutate the input. var props = merge(this.props); props.checked = this.getChecked(); props.value = this.getValue(); props.onChange = this.handleChange; return input(props, this.props.children); }, componentDidUpdate: function(prevProps, prevState, rootNode) { if (this.props.checked != null) { DOMPropertyOperations.setValueForProperty( rootNode, 'checked', this.props.checked || false ); } if (this.props.value != null) { // Cast `this.props.value` to a string so falsey values that cast to // truthy strings are not ignored. DOMPropertyOperations.setValueForProperty( rootNode, 'value', '' + this.props.value || '' ); } }, handleChange: function(event) { var returnValue; if (this.props.onChange) { this._isChanging = true; returnValue = this.props.onChange(event); this._isChanging = false; } this.setState({ checked: event.target.checked, value: event.target.value }); return returnValue; } }); module.exports = ReactDOMInput; },{"./DOMPropertyOperations":8,"./ReactCompositeComponent":24,"./ReactDOM":26,"./merge":84}],30:[function(require,module,exports){ /** * Copyright 2013 Facebook, 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. * * @providesModule ReactDOMOption */ "use strict"; var ReactCompositeComponent = require("./ReactCompositeComponent"); var ReactDOM = require("./ReactDOM"); // Store a reference to the