diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000..9df8e8e
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,3 @@
+{
+ "stage": 2
+}
diff --git a/app/App.js b/app/App.js
index 9f9f7a8..db757e8 100644
--- a/app/App.js
+++ b/app/App.js
@@ -1,4 +1,3 @@
-/** @jsx React.DOM */
var React = require('react');
var Store = require('./Store.js');
var actions = require('./actions.js');
diff --git a/app/Store.js b/app/Store.js
index 7a7c0db..f00b73c 100644
--- a/app/Store.js
+++ b/app/Store.js
@@ -15,4 +15,4 @@ module.exports = flux.createStore({
return this.messages;
}
}
-});
\ No newline at end of file
+});
diff --git a/app/main.js b/app/main.js
index f5b9c1d..8bd2784 100644
--- a/app/main.js
+++ b/app/main.js
@@ -1,4 +1,3 @@
-/** @jsx React.DOM */
var React = require('react');
var App = require('./App.js');
-React.render(, document.body);
\ No newline at end of file
+React.render(, document.body);
diff --git a/build/main.js b/build/main.js
index 5522348..e89bc35 100755
--- a/build/main.js
+++ b/build/main.js
@@ -1,33 +1,31 @@
-(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) {
- var fn = queue.shift();
- fn();
- }
- }
- }, true);
+function drainQueue() {
+ if (draining) {
+ return;
+ }
+ var timeout = setTimeout(cleanUpNextTick);
+ draining = true;
- return function nextTick(fn) {
- queue.push(fn);
- window.postMessage('process-tick', '*');
- };
+ var len = queue.length;
+ while(len) {
+ currentQueue = queue;
+ queue = [];
+ while (++queueIndex < len) {
+ currentQueue[queueIndex].run();
+ }
+ queueIndex = -1;
+ len = queue.length;
}
+ currentQueue = null;
+ draining = false;
+ clearTimeout(timeout);
+}
- return function nextTick(fn) {
- setTimeout(fn, 0);
- };
-})();
+process.nextTick = function (fun) {
+ var args = new Array(arguments.length - 1);
+ if (arguments.length > 1) {
+ for (var i = 1; i < arguments.length; i++) {
+ args[i - 1] = arguments[i];
+ }
+ }
+ queue.push(new Item(fun, args));
+ if (queue.length === 1 && !draining) {
+ setTimeout(drainQueue, 0);
+ }
+};
+// v8 likes predictible objects
+function Item(fun, array) {
+ this.fun = fun;
+ this.array = array;
+}
+Item.prototype.run = function () {
+ this.fun.apply(null, this.array);
+};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
+process.version = ''; // empty string to avoid regexp issues
+process.versions = {};
function noop() {}
@@ -85,6 +88,7 @@ process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
+process.umask = function() { return 0; };
},{}],2:[function(require,module,exports){
/*!
@@ -662,26 +666,185 @@ process.chdir = function (dir) {
}();
},{}],3:[function(require,module,exports){
+var isObject = function (obj) {
+ return typeof obj === 'object' && obj !== null && !Array.isArray(obj);
+};
+
+var isSame = function (a, b) {
+ var keys = Object.keys(a);
+ for (var x = 0; x < keys.length; x++) {
+ if (!b[keys[x]] || a[keys[x]] !== b[keys[x]]) {
+ return false;
+ }
+ }
+ return true;
+};
+
+module.exports = {
+ update: function () {
+ this.setState({});
+ },
+ shouldComponentUpdate: function (nextProps, nextState) {
+
+ var currentPropsLength = this.props ? Object.keys(this.props).length : 0;
+ var nextPropsLength = nextProps ? Object.keys(nextProps).length : 0;
+ var currentStateLength = this.state ? Object.keys(this.state).length : 0;
+ var nextStateLength = nextState ? Object.keys(nextState).length : 0;
+
+ if (!currentPropsLength && !nextPropsLength && !currentStateLength && !nextStateLength) {
+ return false;
+ } else if (currentPropsLength !== nextPropsLength || currentStateLength !== nextStateLength) {
+ return true;
+ } else {
+ return !isSame(nextProps, this.props) || !isSame(nextState, this.state);
+ }
+
+ }
+};
+
+},{}],4:[function(require,module,exports){
+/*
+ * ACTION
+ * ====================================================================================
+ * Creates a single function or a map of functions that when called with arguments will
+ * emit a "trigger" event, passing the arguments
+ * ====================================================================================
+ */
+
+var EventEmitter = require('eventemitter2').EventEmitter2 || require('eventemitter2');
+var safeDeepClone = require('./safeDeepClone.js');
+
+var createActionFunction = function (actionName) {
+
+ // Create the action function
+ var fn = function () {
+
+ // Grab all the arguments and convert to array
+ var args = safeDeepClone('[Circular]', [], Array.prototype.slice.call(arguments, 0));
+
+ if (!fn._events) {
+ throw new Error('You are triggering the action: ' + fn.handlerName + ', and nobody is listening to it yet. Remember to load up the store first');
+ }
+
+ // Merge arguments array with "trigger", which is the
+ // event that will be triggered, passing the original arguments
+ // as arguments to the "trigger" event
+ args = ['trigger'].concat(args);
+ fn.emit.apply(fn, args);
+
+ };
+
+ var emitter = new EventEmitter();
+
+ // It is possible to listen to the function and to achieve that we
+ // have to manually inherit methods from EventEmitter
+ for (var prop in EventEmitter.prototype) {
+ if (EventEmitter.prototype.hasOwnProperty(prop)) {
+ fn[prop] = EventEmitter.prototype[prop];
+ }
+ }
+
+ // Add handlerName
+ fn.handlerName = actionName;
+
+ return fn;
+
+};
+
+var action = function () {
+
+ if (Array.isArray(arguments[0])) {
+ var actionMap = {};
+ arguments[0].forEach(function (actionName) {
+ actionMap[actionName] = createActionFunction(actionName);
+ });
+ return actionMap;
+ }
+
+ throw new Error('You are not passing an array to createActions');
+
+};
+
+module.exports = action;
+
+},{"./safeDeepClone.js":5,"eventemitter2":2}],5:[function(require,module,exports){
+(function (global){
+function safeDeepClone(circularValue, refs, obj) {
+ var copy, tmp;
+
+ // object is a false or empty value, or otherwise not an object
+ if (!obj || "object" !== typeof obj ||
+ ('ArrayBuffer' in global && obj instanceof ArrayBuffer) ||
+ ('Blob' in global && obj instanceof Blob) ||
+ ('File' in global && obj instanceof File))
+ {
+ return obj;
+ }
+
+ // Handle Date
+ if (obj instanceof Date) {
+ copy = new Date();
+ copy.setTime(obj.getTime());
+ return copy;
+ }
+
+ // Handle Array - or array-like items (Buffers)
+ if (obj instanceof Array || obj.length) {
+
+ refs.push(obj);
+ copy = [];
+ for (var i = 0, len = obj.length; i < len; i++) {
+ if (refs.indexOf(obj[i]) >= 0) {
+ copy[i] = circularValue;
+ } else {
+ copy[i] = safeDeepClone(circularValue, refs, obj[i]);
+ }
+ }
+ refs.pop();
+ return copy;
+ }
+
+ // Handle Object
+ refs.push(obj);
+ copy = {};
+
+ if (obj instanceof Error) {
+ //raise inherited error properties for the clone
+ copy.name = obj.name;
+ copy.message = obj.message;
+ copy.stack = obj.stack;
+ }
+
+ for (var attr in obj) {
+ if (obj.hasOwnProperty(attr)) {
+ if (refs.indexOf(obj[attr]) >= 0) {
+ copy[attr] = circularValue;
+ } else {
+ copy[attr] = safeDeepClone(circularValue, refs, obj[attr]);
+ }
+ }
+ }
+ refs.pop();
+ return copy;
+}
+
+module.exports = safeDeepClone;
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+
+},{}],6:[function(require,module,exports){
/**
- * Copyright 2013-2014 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
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
*
- * 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.
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule AutoFocusMixin
* @typechecks static-only
*/
-"use strict";
+'use strict';
var focusNode = require("./focusNode");
@@ -695,39 +858,61 @@ var AutoFocusMixin = {
module.exports = AutoFocusMixin;
-},{"./focusNode":108}],4:[function(require,module,exports){
+},{"./focusNode":139}],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
+ * Copyright 2013-2015 Facebook, Inc.
+ * All rights reserved.
*
- * 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.
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule BeforeInputEventPlugin
* @typechecks static-only
*/
-"use strict";
+'use strict';
var EventConstants = require("./EventConstants");
var EventPropagators = require("./EventPropagators");
var ExecutionEnvironment = require("./ExecutionEnvironment");
+var FallbackCompositionState = require("./FallbackCompositionState");
+var SyntheticCompositionEvent = require("./SyntheticCompositionEvent");
var SyntheticInputEvent = require("./SyntheticInputEvent");
var keyOf = require("./keyOf");
+var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space
+var START_KEYCODE = 229;
+
+var canUseCompositionEvent = (
+ ExecutionEnvironment.canUseDOM &&
+ 'CompositionEvent' in window
+);
+
+var documentMode = null;
+if (ExecutionEnvironment.canUseDOM && 'documentMode' in document) {
+ documentMode = document.documentMode;
+}
+
+// Webkit offers a very useful `textInput` event that can be used to
+// directly represent `beforeInput`. The IE `textinput` event is not as
+// useful, so we don't use it.
var canUseTextInputEvent = (
ExecutionEnvironment.canUseDOM &&
'TextEvent' in window &&
- !('documentMode' in document || isPresto())
+ !documentMode &&
+ !isPresto()
+);
+
+// In IE9+, we have access to composition events, but the data supplied
+// by the native compositionend event may be incorrect. Japanese ideographic
+// spaces, for instance (\u3000) are not recorded correctly.
+var useFallbackCompositionData = (
+ ExecutionEnvironment.canUseDOM &&
+ (
+ (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11)
+ )
);
/**
@@ -761,231 +946,595 @@ var eventTypes = {
topLevelTypes.topTextInput,
topLevelTypes.topPaste
]
- }
-};
-
-// Track characters inserted via keypress and composition events.
-var fallbackChars = null;
-
-/**
- * Return whether a native keypress event is assumed to be a command.
- * This is required because Firefox fires `keypress` events for key commands
- * (cut, copy, select-all, etc.) even though no character is inserted.
- */
-function isKeypressCommand(nativeEvent) {
- return (
- (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) &&
- // ctrlKey && altKey is equivalent to AltGr, and is not a command.
- !(nativeEvent.ctrlKey && nativeEvent.altKey)
- );
-}
-
-/**
- * Create an `onBeforeInput` event to match
- * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents.
- *
- * This event plugin is based on the native `textInput` event
- * available in Chrome, Safari, Opera, and IE. This event fires after
- * `onKeyPress` and `onCompositionEnd`, but before `onInput`.
- *
- * `beforeInput` is spec'd but not implemented in any browsers, and
- * the `input` event does not provide any useful information about what has
- * actually been added, contrary to the spec. Thus, `textInput` is the best
- * available event to identify the characters that have actually been inserted
- * into the target node.
- */
-var BeforeInputEventPlugin = {
+ },
+ compositionEnd: {
+ phasedRegistrationNames: {
+ bubbled: keyOf({onCompositionEnd: null}),
+ captured: keyOf({onCompositionEndCapture: null})
+ },
+ dependencies: [
+ topLevelTypes.topBlur,
+ topLevelTypes.topCompositionEnd,
+ topLevelTypes.topKeyDown,
+ topLevelTypes.topKeyPress,
+ topLevelTypes.topKeyUp,
+ topLevelTypes.topMouseDown
+ ]
+ },
+ compositionStart: {
+ phasedRegistrationNames: {
+ bubbled: keyOf({onCompositionStart: null}),
+ captured: keyOf({onCompositionStartCapture: null})
+ },
+ dependencies: [
+ topLevelTypes.topBlur,
+ topLevelTypes.topCompositionStart,
+ topLevelTypes.topKeyDown,
+ topLevelTypes.topKeyPress,
+ topLevelTypes.topKeyUp,
+ topLevelTypes.topMouseDown
+ ]
+ },
+ compositionUpdate: {
+ phasedRegistrationNames: {
+ bubbled: keyOf({onCompositionUpdate: null}),
+ captured: keyOf({onCompositionUpdateCapture: null})
+ },
+ dependencies: [
+ topLevelTypes.topBlur,
+ topLevelTypes.topCompositionUpdate,
+ topLevelTypes.topKeyDown,
+ topLevelTypes.topKeyPress,
+ topLevelTypes.topKeyUp,
+ topLevelTypes.topMouseDown
+ ]
+ }
+};
- eventTypes: eventTypes,
+// Track whether we've ever handled a keypress on the space key.
+var hasSpaceKeypress = false;
- /**
- * @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) {
+/**
+ * Return whether a native keypress event is assumed to be a command.
+ * This is required because Firefox fires `keypress` events for key commands
+ * (cut, copy, select-all, etc.) even though no character is inserted.
+ */
+function isKeypressCommand(nativeEvent) {
+ return (
+ (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) &&
+ // ctrlKey && altKey is equivalent to AltGr, and is not a command.
+ !(nativeEvent.ctrlKey && nativeEvent.altKey)
+ );
+}
- var chars;
-
- if (canUseTextInputEvent) {
- switch (topLevelType) {
- case topLevelTypes.topKeyPress:
- /**
- * If native `textInput` events are available, our goal is to make
- * use of them. However, there is a special case: the spacebar key.
- * In Webkit, preventing default on a spacebar `textInput` event
- * cancels character insertion, but it *also* causes the browser
- * to fall back to its default spacebar behavior of scrolling the
- * page.
- *
- * Tracking at:
- * https://code.google.com/p/chromium/issues/detail?id=355103
- *
- * To avoid this issue, use the keypress event as if no `textInput`
- * event is available.
- */
- var which = nativeEvent.which;
- if (which !== SPACEBAR_CODE) {
- return;
- }
- chars = String.fromCharCode(which);
- break;
+/**
+ * Translate native top level events into event types.
+ *
+ * @param {string} topLevelType
+ * @return {object}
+ */
+function getCompositionEventType(topLevelType) {
+ switch (topLevelType) {
+ case topLevelTypes.topCompositionStart:
+ return eventTypes.compositionStart;
+ case topLevelTypes.topCompositionEnd:
+ return eventTypes.compositionEnd;
+ case topLevelTypes.topCompositionUpdate:
+ return eventTypes.compositionUpdate;
+ }
+}
- case topLevelTypes.topTextInput:
- // Record the characters to be added to the DOM.
- chars = nativeEvent.data;
+/**
+ * Does our fallback best-guess model think this event signifies that
+ * composition has begun?
+ *
+ * @param {string} topLevelType
+ * @param {object} nativeEvent
+ * @return {boolean}
+ */
+function isFallbackCompositionStart(topLevelType, nativeEvent) {
+ return (
+ topLevelType === topLevelTypes.topKeyDown &&
+ nativeEvent.keyCode === START_KEYCODE
+ );
+}
- // If it's a spacebar character, assume that we have already handled
- // it at the keypress level and bail immediately.
- if (chars === SPACEBAR_CHAR) {
- return;
- }
+/**
+ * Does our fallback mode think that this event is the end of composition?
+ *
+ * @param {string} topLevelType
+ * @param {object} nativeEvent
+ * @return {boolean}
+ */
+function isFallbackCompositionEnd(topLevelType, nativeEvent) {
+ switch (topLevelType) {
+ case topLevelTypes.topKeyUp:
+ // Command keys insert or clear IME input.
+ return (END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1);
+ case topLevelTypes.topKeyDown:
+ // Expect IME keyCode on each keydown. If we get any other
+ // code we must have exited earlier.
+ return (nativeEvent.keyCode !== START_KEYCODE);
+ case topLevelTypes.topKeyPress:
+ case topLevelTypes.topMouseDown:
+ case topLevelTypes.topBlur:
+ // Events are not possible without cancelling IME.
+ return true;
+ default:
+ return false;
+ }
+}
- // Otherwise, carry on.
- break;
+/**
+ * Google Input Tools provides composition data via a CustomEvent,
+ * with the `data` property populated in the `detail` object. If this
+ * is available on the event object, use it. If not, this is a plain
+ * composition event and we have nothing special to extract.
+ *
+ * @param {object} nativeEvent
+ * @return {?string}
+ */
+function getDataFromCustomEvent(nativeEvent) {
+ var detail = nativeEvent.detail;
+ if (typeof detail === 'object' && 'data' in detail) {
+ return detail.data;
+ }
+ return null;
+}
- default:
- // For other native event types, do nothing.
- return;
- }
- } else {
- switch (topLevelType) {
- case topLevelTypes.topPaste:
- // If a paste event occurs after a keypress, throw out the input
- // chars. Paste events should not lead to BeforeInput events.
- fallbackChars = null;
- break;
- case topLevelTypes.topKeyPress:
- /**
- * As of v27, Firefox may fire keypress events even when no character
- * will be inserted. A few possibilities:
- *
- * - `which` is `0`. Arrow keys, Esc key, etc.
- *
- * - `which` is the pressed key code, but no char is available.
- * Ex: 'AltGr + d` in Polish. There is no modified character for
- * this key combination and no character is inserted into the
- * document, but FF fires the keypress for char code `100` anyway.
- * No `input` event will occur.
- *
- * - `which` is the pressed key code, but a command combination is
- * being used. Ex: `Cmd+C`. No character is inserted, and no
- * `input` event will occur.
- */
- if (nativeEvent.which && !isKeypressCommand(nativeEvent)) {
- fallbackChars = String.fromCharCode(nativeEvent.which);
- }
- break;
- case topLevelTypes.topCompositionEnd:
- fallbackChars = nativeEvent.data;
- break;
- }
+// Track the current IME composition fallback object, if any.
+var currentComposition = null;
- // If no changes have occurred to the fallback string, no relevant
- // event has fired and we're done.
- if (fallbackChars === null) {
- return;
- }
+/**
+ * @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 {?object} A SyntheticCompositionEvent.
+ */
+function extractCompositionEvent(
+ topLevelType,
+ topLevelTarget,
+ topLevelTargetID,
+ nativeEvent
+) {
+ var eventType;
+ var fallbackData;
- chars = fallbackChars;
+ if (canUseCompositionEvent) {
+ eventType = getCompositionEventType(topLevelType);
+ } else if (!currentComposition) {
+ if (isFallbackCompositionStart(topLevelType, nativeEvent)) {
+ eventType = eventTypes.compositionStart;
}
+ } else if (isFallbackCompositionEnd(topLevelType, nativeEvent)) {
+ eventType = eventTypes.compositionEnd;
+ }
- // If no characters are being inserted, no BeforeInput event should
- // be fired.
- if (!chars) {
- return;
+ if (!eventType) {
+ return null;
+ }
+
+ if (useFallbackCompositionData) {
+ // The current composition is stored statically and must not be
+ // overwritten while composition continues.
+ if (!currentComposition && eventType === eventTypes.compositionStart) {
+ currentComposition = FallbackCompositionState.getPooled(topLevelTarget);
+ } else if (eventType === eventTypes.compositionEnd) {
+ if (currentComposition) {
+ fallbackData = currentComposition.getData();
+ }
}
+ }
- var event = SyntheticInputEvent.getPooled(
- eventTypes.beforeInput,
- topLevelTargetID,
- nativeEvent
- );
+ var event = SyntheticCompositionEvent.getPooled(
+ eventType,
+ topLevelTargetID,
+ nativeEvent
+ );
- event.data = chars;
- fallbackChars = null;
- EventPropagators.accumulateTwoPhaseDispatches(event);
- return event;
+ if (fallbackData) {
+ // Inject data generated from fallback path into the synthetic event.
+ // This matches the property of native CompositionEventInterface.
+ event.data = fallbackData;
+ } else {
+ var customData = getDataFromCustomEvent(nativeEvent);
+ if (customData !== null) {
+ event.data = customData;
+ }
}
-};
-module.exports = BeforeInputEventPlugin;
+ EventPropagators.accumulateTwoPhaseDispatches(event);
+ return event;
+}
-},{"./EventConstants":17,"./EventPropagators":22,"./ExecutionEnvironment":23,"./SyntheticInputEvent":88,"./keyOf":129}],5:[function(require,module,exports){
/**
- * Copyright 2013-2014 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 CSSProperty
+ * @param {string} topLevelType Record from `EventConstants`.
+ * @param {object} nativeEvent Native browser event.
+ * @return {?string} The string corresponding to this `beforeInput` event.
*/
+function getNativeBeforeInputChars(topLevelType, nativeEvent) {
+ switch (topLevelType) {
+ case topLevelTypes.topCompositionEnd:
+ return getDataFromCustomEvent(nativeEvent);
+ case topLevelTypes.topKeyPress:
+ /**
+ * If native `textInput` events are available, our goal is to make
+ * use of them. However, there is a special case: the spacebar key.
+ * In Webkit, preventing default on a spacebar `textInput` event
+ * cancels character insertion, but it *also* causes the browser
+ * to fall back to its default spacebar behavior of scrolling the
+ * page.
+ *
+ * Tracking at:
+ * https://code.google.com/p/chromium/issues/detail?id=355103
+ *
+ * To avoid this issue, use the keypress event as if no `textInput`
+ * event is available.
+ */
+ var which = nativeEvent.which;
+ if (which !== SPACEBAR_CODE) {
+ return null;
+ }
-"use strict";
+ hasSpaceKeypress = true;
+ return SPACEBAR_CHAR;
-/**
- * CSS properties which accept numbers but are not in units of "px".
- */
-var isUnitlessNumber = {
- columnCount: true,
- fillOpacity: true,
- flex: true,
- flexGrow: true,
- flexShrink: true,
- fontWeight: true,
- lineClamp: true,
- lineHeight: true,
- opacity: true,
- order: true,
- orphans: true,
- widows: true,
- zIndex: true,
- zoom: true
-};
+ case topLevelTypes.topTextInput:
+ // Record the characters to be added to the DOM.
+ var chars = nativeEvent.data;
-/**
- * @param {string} prefix vendor-specific prefix, eg: Webkit
- * @param {string} key style name, eg: transitionDuration
- * @return {string} style name prefixed with `prefix`, properly camelCased, eg:
- * WebkitTransitionDuration
- */
-function prefixKey(prefix, key) {
- return prefix + key.charAt(0).toUpperCase() + key.substring(1);
+ // If it's a spacebar character, assume that we have already handled
+ // it at the keypress level and bail immediately. Android Chrome
+ // doesn't give us keycodes, so we need to blacklist it.
+ if (chars === SPACEBAR_CHAR && hasSpaceKeypress) {
+ return null;
+ }
+
+ return chars;
+
+ default:
+ // For other native event types, do nothing.
+ return null;
+ }
}
/**
- * Support style names that may come passed in prefixed by adding permutations
- * of vendor prefixes.
- */
-var prefixes = ['Webkit', 'ms', 'Moz', 'O'];
+ * For browsers that do not provide the `textInput` event, extract the
+ * appropriate string to use for SyntheticInputEvent.
+ *
+ * @param {string} topLevelType Record from `EventConstants`.
+ * @param {object} nativeEvent Native browser event.
+ * @return {?string} The fallback string for this `beforeInput` event.
+ */
+function getFallbackBeforeInputChars(topLevelType, nativeEvent) {
+ // If we are currently composing (IME) and using a fallback to do so,
+ // try to extract the composed characters from the fallback object.
+ if (currentComposition) {
+ if (
+ topLevelType === topLevelTypes.topCompositionEnd ||
+ isFallbackCompositionEnd(topLevelType, nativeEvent)
+ ) {
+ var chars = currentComposition.getData();
+ FallbackCompositionState.release(currentComposition);
+ currentComposition = null;
+ return chars;
+ }
+ return null;
+ }
-// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an
-// infinite loop, because it iterates over the newly added props too.
-Object.keys(isUnitlessNumber).forEach(function(prop) {
- prefixes.forEach(function(prefix) {
- isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];
- });
-});
+ switch (topLevelType) {
+ case topLevelTypes.topPaste:
+ // If a paste event occurs after a keypress, throw out the input
+ // chars. Paste events should not lead to BeforeInput events.
+ return null;
+ case topLevelTypes.topKeyPress:
+ /**
+ * As of v27, Firefox may fire keypress events even when no character
+ * will be inserted. A few possibilities:
+ *
+ * - `which` is `0`. Arrow keys, Esc key, etc.
+ *
+ * - `which` is the pressed key code, but no char is available.
+ * Ex: 'AltGr + d` in Polish. There is no modified character for
+ * this key combination and no character is inserted into the
+ * document, but FF fires the keypress for char code `100` anyway.
+ * No `input` event will occur.
+ *
+ * - `which` is the pressed key code, but a command combination is
+ * being used. Ex: `Cmd+C`. No character is inserted, and no
+ * `input` event will occur.
+ */
+ if (nativeEvent.which && !isKeypressCommand(nativeEvent)) {
+ return String.fromCharCode(nativeEvent.which);
+ }
+ return null;
+ case topLevelTypes.topCompositionEnd:
+ return useFallbackCompositionData ? null : nativeEvent.data;
+ default:
+ return null;
+ }
+}
/**
- * Most style properties can be unset by doing .style[prop] = '' but IE8
+ * Extract a SyntheticInputEvent for `beforeInput`, based on either native
+ * `textInput` or fallback behavior.
+ *
+ * @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 {?object} A SyntheticInputEvent.
+ */
+function extractBeforeInputEvent(
+ topLevelType,
+ topLevelTarget,
+ topLevelTargetID,
+ nativeEvent
+) {
+ var chars;
+
+ if (canUseTextInputEvent) {
+ chars = getNativeBeforeInputChars(topLevelType, nativeEvent);
+ } else {
+ chars = getFallbackBeforeInputChars(topLevelType, nativeEvent);
+ }
+
+ // If no characters are being inserted, no BeforeInput event should
+ // be fired.
+ if (!chars) {
+ return null;
+ }
+
+ var event = SyntheticInputEvent.getPooled(
+ eventTypes.beforeInput,
+ topLevelTargetID,
+ nativeEvent
+ );
+
+ event.data = chars;
+ EventPropagators.accumulateTwoPhaseDispatches(event);
+ return event;
+}
+
+/**
+ * Create an `onBeforeInput` event to match
+ * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents.
+ *
+ * This event plugin is based on the native `textInput` event
+ * available in Chrome, Safari, Opera, and IE. This event fires after
+ * `onKeyPress` and `onCompositionEnd`, but before `onInput`.
+ *
+ * `beforeInput` is spec'd but not implemented in any browsers, and
+ * the `input` event does not provide any useful information about what has
+ * actually been added, contrary to the spec. Thus, `textInput` is the best
+ * available event to identify the characters that have actually been inserted
+ * into the target node.
+ *
+ * This plugin is also responsible for emitting `composition` events, thus
+ * allowing us to share composition fallback code for both `beforeInput` and
+ * `composition` event types.
+ */
+var BeforeInputEventPlugin = {
+
+ eventTypes: eventTypes,
+
+ /**
+ * @param {string} topLevelType Record from `EventConstants`.
+ * @param {DOMEventTarget} topLevelTarget The listening component root node.
+ * @param {string} topLevelTargetID ID of `topLevelTarget`.
+ * @param {object} nativeEvent Native browser event.
+ * @return {*} An accumulation of synthetic events.
+ * @see {EventPluginHub.extractEvents}
+ */
+ extractEvents: function(
+ topLevelType,
+ topLevelTarget,
+ topLevelTargetID,
+ nativeEvent
+ ) {
+ return [
+ extractCompositionEvent(
+ topLevelType,
+ topLevelTarget,
+ topLevelTargetID,
+ nativeEvent
+ ),
+ extractBeforeInputEvent(
+ topLevelType,
+ topLevelTarget,
+ topLevelTargetID,
+ nativeEvent
+ )
+ ];
+ }
+};
+
+module.exports = BeforeInputEventPlugin;
+
+},{"./EventConstants":20,"./EventPropagators":25,"./ExecutionEnvironment":26,"./FallbackCompositionState":27,"./SyntheticCompositionEvent":111,"./SyntheticInputEvent":115,"./keyOf":162}],8:[function(require,module,exports){
+(function (process){
+/**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule CSSCore
+ * @typechecks
+ */
+
+var invariant = require("./invariant");
+
+/**
+ * The CSSCore module specifies the API (and implements most of the methods)
+ * that should be used when dealing with the display of elements (via their
+ * CSS classes and visibility on screen. It is an API focused on mutating the
+ * display and not reading it as no logical state should be encoded in the
+ * display of elements.
+ */
+
+var CSSCore = {
+
+ /**
+ * Adds the class passed in to the element if it doesn't already have it.
+ *
+ * @param {DOMElement} element the element to set the class on
+ * @param {string} className the CSS className
+ * @return {DOMElement} the element passed in
+ */
+ addClass: function(element, className) {
+ ("production" !== process.env.NODE_ENV ? invariant(
+ !/\s/.test(className),
+ 'CSSCore.addClass takes only a single class name. "%s" contains ' +
+ 'multiple classes.', className
+ ) : invariant(!/\s/.test(className)));
+
+ if (className) {
+ if (element.classList) {
+ element.classList.add(className);
+ } else if (!CSSCore.hasClass(element, className)) {
+ element.className = element.className + ' ' + className;
+ }
+ }
+ return element;
+ },
+
+ /**
+ * Removes the class passed in from the element
+ *
+ * @param {DOMElement} element the element to set the class on
+ * @param {string} className the CSS className
+ * @return {DOMElement} the element passed in
+ */
+ removeClass: function(element, className) {
+ ("production" !== process.env.NODE_ENV ? invariant(
+ !/\s/.test(className),
+ 'CSSCore.removeClass takes only a single class name. "%s" contains ' +
+ 'multiple classes.', className
+ ) : invariant(!/\s/.test(className)));
+
+ if (className) {
+ if (element.classList) {
+ element.classList.remove(className);
+ } else if (CSSCore.hasClass(element, className)) {
+ element.className = element.className
+ .replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)', 'g'), '$1')
+ .replace(/\s+/g, ' ') // multiple spaces to one
+ .replace(/^\s*|\s*$/g, ''); // trim the ends
+ }
+ }
+ return element;
+ },
+
+ /**
+ * Helper to add or remove a class from an element based on a condition.
+ *
+ * @param {DOMElement} element the element to set the class on
+ * @param {string} className the CSS className
+ * @param {*} bool condition to whether to add or remove the class
+ * @return {DOMElement} the element passed in
+ */
+ conditionClass: function(element, className, bool) {
+ return (bool ? CSSCore.addClass : CSSCore.removeClass)(element, className);
+ },
+
+ /**
+ * Tests whether the element has the class specified.
+ *
+ * @param {DOMNode|DOMWindow} element the element to set the class on
+ * @param {string} className the CSS className
+ * @return {boolean} true if the element has the class, false if not
+ */
+ hasClass: function(element, className) {
+ ("production" !== process.env.NODE_ENV ? invariant(
+ !/\s/.test(className),
+ 'CSS.hasClass takes only a single class name.'
+ ) : invariant(!/\s/.test(className)));
+ if (element.classList) {
+ return !!className && element.classList.contains(className);
+ }
+ return (' ' + element.className + ' ').indexOf(' ' + className + ' ') > -1;
+ }
+
+};
+
+module.exports = CSSCore;
+
+}).call(this,require('_process'))
+
+},{"./invariant":155,"_process":1}],9:[function(require,module,exports){
+/**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule CSSProperty
+ */
+
+'use strict';
+
+/**
+ * CSS properties which accept numbers but are not in units of "px".
+ */
+var isUnitlessNumber = {
+ boxFlex: true,
+ boxFlexGroup: true,
+ columnCount: true,
+ flex: true,
+ flexGrow: true,
+ flexPositive: true,
+ flexShrink: true,
+ flexNegative: true,
+ fontWeight: true,
+ lineClamp: true,
+ lineHeight: true,
+ opacity: true,
+ order: true,
+ orphans: true,
+ widows: true,
+ zIndex: true,
+ zoom: true,
+
+ // SVG-related properties
+ fillOpacity: true,
+ strokeDashoffset: true,
+ strokeOpacity: true,
+ strokeWidth: true
+};
+
+/**
+ * @param {string} prefix vendor-specific prefix, eg: Webkit
+ * @param {string} key style name, eg: transitionDuration
+ * @return {string} style name prefixed with `prefix`, properly camelCased, eg:
+ * WebkitTransitionDuration
+ */
+function prefixKey(prefix, key) {
+ return prefix + key.charAt(0).toUpperCase() + key.substring(1);
+}
+
+/**
+ * Support style names that may come passed in prefixed by adding permutations
+ * of vendor prefixes.
+ */
+var prefixes = ['Webkit', 'ms', 'Moz', 'O'];
+
+// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an
+// infinite loop, because it iterates over the newly added props too.
+Object.keys(isUnitlessNumber).forEach(function(prop) {
+ prefixes.forEach(function(prefix) {
+ isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];
+ });
+});
+
+/**
+ * Most style properties can be unset by doing .style[prop] = '' but IE8
* doesn't like doing that with shorthand properties so for the properties that
* IE8 breaks on, which are listed here, we instead unset each of the
* individual properties. See http://bugs.jquery.com/ticket/12385.
@@ -1042,38 +1591,111 @@ var CSSProperty = {
module.exports = CSSProperty;
-},{}],6:[function(require,module,exports){
+},{}],10:[function(require,module,exports){
+(function (process){
/**
- * Copyright 2013-2014 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
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
*
- * 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.
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule CSSPropertyOperations
* @typechecks static-only
*/
-"use strict";
+'use strict';
var CSSProperty = require("./CSSProperty");
+var ExecutionEnvironment = require("./ExecutionEnvironment");
+var camelizeStyleName = require("./camelizeStyleName");
var dangerousStyleValue = require("./dangerousStyleValue");
var hyphenateStyleName = require("./hyphenateStyleName");
var memoizeStringOnly = require("./memoizeStringOnly");
+var warning = require("./warning");
var processStyleName = memoizeStringOnly(function(styleName) {
return hyphenateStyleName(styleName);
});
+var styleFloatAccessor = 'cssFloat';
+if (ExecutionEnvironment.canUseDOM) {
+ // IE8 only supports accessing cssFloat (standard) as styleFloat
+ if (document.documentElement.style.cssFloat === undefined) {
+ styleFloatAccessor = 'styleFloat';
+ }
+}
+
+if ("production" !== process.env.NODE_ENV) {
+ // 'msTransform' is correct, but the other prefixes should be capitalized
+ var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/;
+
+ // style values shouldn't contain a semicolon
+ var badStyleValueWithSemicolonPattern = /;\s*$/;
+
+ var warnedStyleNames = {};
+ var warnedStyleValues = {};
+
+ var warnHyphenatedStyleName = function(name) {
+ if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
+ return;
+ }
+
+ warnedStyleNames[name] = true;
+ ("production" !== process.env.NODE_ENV ? warning(
+ false,
+ 'Unsupported style property %s. Did you mean %s?',
+ name,
+ camelizeStyleName(name)
+ ) : null);
+ };
+
+ var warnBadVendoredStyleName = function(name) {
+ if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
+ return;
+ }
+
+ warnedStyleNames[name] = true;
+ ("production" !== process.env.NODE_ENV ? warning(
+ false,
+ 'Unsupported vendor-prefixed style property %s. Did you mean %s?',
+ name,
+ name.charAt(0).toUpperCase() + name.slice(1)
+ ) : null);
+ };
+
+ var warnStyleValueWithSemicolon = function(name, value) {
+ if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) {
+ return;
+ }
+
+ warnedStyleValues[value] = true;
+ ("production" !== process.env.NODE_ENV ? warning(
+ false,
+ 'Style property values shouldn\'t contain a semicolon. ' +
+ 'Try "%s: %s" instead.',
+ name,
+ value.replace(badStyleValueWithSemicolonPattern, '')
+ ) : null);
+ };
+
+ /**
+ * @param {string} name
+ * @param {*} value
+ */
+ var warnValidStyle = function(name, value) {
+ if (name.indexOf('-') > -1) {
+ warnHyphenatedStyleName(name);
+ } else if (badVendoredStyleNamePattern.test(name)) {
+ warnBadVendoredStyleName(name);
+ } else if (badStyleValueWithSemicolonPattern.test(value)) {
+ warnStyleValueWithSemicolon(name, value);
+ }
+ };
+}
+
/**
* Operations for dealing with CSS properties.
*/
@@ -1098,6 +1720,9 @@ var CSSPropertyOperations = {
continue;
}
var styleValue = styles[styleName];
+ if ("production" !== process.env.NODE_ENV) {
+ warnValidStyle(styleName, styleValue);
+ }
if (styleValue != null) {
serialized += processStyleName(styleName) + ':';
serialized += dangerousStyleValue(styleName, styleValue) + ';';
@@ -1119,7 +1744,13 @@ var CSSPropertyOperations = {
if (!styles.hasOwnProperty(styleName)) {
continue;
}
+ if ("production" !== process.env.NODE_ENV) {
+ warnValidStyle(styleName, styles[styleName]);
+ }
var styleValue = dangerousStyleValue(styleName, styles[styleName]);
+ if (styleName === 'float') {
+ styleName = styleFloatAccessor;
+ }
if (styleValue) {
style[styleName] = styleValue;
} else {
@@ -1141,32 +1772,27 @@ var CSSPropertyOperations = {
module.exports = CSSPropertyOperations;
-},{"./CSSProperty":5,"./dangerousStyleValue":103,"./hyphenateStyleName":120,"./memoizeStringOnly":131}],7:[function(require,module,exports){
+}).call(this,require('_process'))
+
+},{"./CSSProperty":9,"./ExecutionEnvironment":26,"./camelizeStyleName":126,"./dangerousStyleValue":133,"./hyphenateStyleName":153,"./memoizeStringOnly":164,"./warning":176,"_process":1}],11:[function(require,module,exports){
(function (process){
/**
- * Copyright 2013-2014 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
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
*
- * 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.
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule CallbackQueue
*/
-"use strict";
+'use strict';
var PooledClass = require("./PooledClass");
+var assign = require("./Object.assign");
var invariant = require("./invariant");
-var mixInto = require("./mixInto");
/**
* A specialized pseudo-event module to help keep track of components waiting to
@@ -1184,7 +1810,7 @@ function CallbackQueue() {
this._contexts = null;
}
-mixInto(CallbackQueue, {
+assign(CallbackQueue.prototype, {
/**
* Enqueues a callback to be invoked when `notifyAll` is invoked.
@@ -1212,7 +1838,7 @@ mixInto(CallbackQueue, {
if (callbacks) {
("production" !== process.env.NODE_ENV ? invariant(
callbacks.length === contexts.length,
- "Mismatched list of contexts in callback queue"
+ 'Mismatched list of contexts in callback queue'
) : invariant(callbacks.length === contexts.length));
this._callbacks = null;
this._contexts = null;
@@ -1249,26 +1875,19 @@ module.exports = CallbackQueue;
}).call(this,require('_process'))
-},{"./PooledClass":28,"./invariant":122,"./mixInto":135,"_process":1}],8:[function(require,module,exports){
+},{"./Object.assign":33,"./PooledClass":34,"./invariant":155,"_process":1}],12:[function(require,module,exports){
/**
- * Copyright 2013-2014 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
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
*
- * 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.
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ChangeEventPlugin
*/
-"use strict";
+'use strict';
var EventConstants = require("./EventConstants");
var EventPluginHub = require("./EventPluginHub");
@@ -1324,7 +1943,7 @@ var doesChangeEventBubble = false;
if (ExecutionEnvironment.canUseDOM) {
// See `handleChange` comment below
doesChangeEventBubble = isEventSupported('change') && (
- !('documentMode' in document) || document.documentMode > 8
+ (!('documentMode' in document) || document.documentMode > 8)
);
}
@@ -1401,7 +2020,7 @@ 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
+ (!('documentMode' in document) || document.documentMode > 9)
);
}
@@ -1638,27 +2257,20 @@ var ChangeEventPlugin = {
module.exports = ChangeEventPlugin;
-},{"./EventConstants":17,"./EventPluginHub":19,"./EventPropagators":22,"./ExecutionEnvironment":23,"./ReactUpdates":78,"./SyntheticEvent":86,"./isEventSupported":123,"./isTextInputElement":125,"./keyOf":129}],9:[function(require,module,exports){
+},{"./EventConstants":20,"./EventPluginHub":22,"./EventPropagators":25,"./ExecutionEnvironment":26,"./ReactUpdates":104,"./SyntheticEvent":113,"./isEventSupported":156,"./isTextInputElement":158,"./keyOf":162}],13:[function(require,module,exports){
/**
- * Copyright 2013-2014 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
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
*
- * 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.
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ClientReactRootIndex
* @typechecks
*/
-"use strict";
+'use strict';
var nextReactRootIndex = 0;
@@ -1670,367 +2282,55 @@ var ClientReactRootIndex = {
module.exports = ClientReactRootIndex;
-},{}],10:[function(require,module,exports){
+},{}],14:[function(require,module,exports){
+(function (process){
/**
- * Copyright 2013-2014 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
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
*
- * 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.
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
*
- * @providesModule CompositionEventPlugin
+ * @providesModule DOMChildrenOperations
* @typechecks static-only
*/
-"use strict";
-
-var EventConstants = require("./EventConstants");
-var EventPropagators = require("./EventPropagators");
-var ExecutionEnvironment = require("./ExecutionEnvironment");
-var ReactInputSelection = require("./ReactInputSelection");
-var SyntheticCompositionEvent = require("./SyntheticCompositionEvent");
-
-var getTextContentAccessor = require("./getTextContentAccessor");
-var keyOf = require("./keyOf");
-
-var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space
-var START_KEYCODE = 229;
-
-var useCompositionEvent = (
- ExecutionEnvironment.canUseDOM &&
- 'CompositionEvent' in window
-);
-
-// In IE9+, we have access to composition events, but the data supplied
-// by the native compositionend event may be incorrect. In Korean, for example,
-// the compositionend event contains only one character regardless of
-// how many characters have been composed since compositionstart.
-// We therefore use the fallback data while still using the native
-// events as triggers.
-var useFallbackData = (
- !useCompositionEvent ||
- (
- 'documentMode' in document &&
- document.documentMode > 8 &&
- document.documentMode <= 11
- )
-);
-
-var topLevelTypes = EventConstants.topLevelTypes;
-var currentComposition = null;
+'use strict';
-// Events and their corresponding property names.
-var eventTypes = {
- compositionEnd: {
- phasedRegistrationNames: {
- bubbled: keyOf({onCompositionEnd: null}),
- captured: keyOf({onCompositionEndCapture: null})
- },
- dependencies: [
- topLevelTypes.topBlur,
- topLevelTypes.topCompositionEnd,
- topLevelTypes.topKeyDown,
- topLevelTypes.topKeyPress,
- topLevelTypes.topKeyUp,
- topLevelTypes.topMouseDown
- ]
- },
- compositionStart: {
- phasedRegistrationNames: {
- bubbled: keyOf({onCompositionStart: null}),
- captured: keyOf({onCompositionStartCapture: null})
- },
- dependencies: [
- topLevelTypes.topBlur,
- topLevelTypes.topCompositionStart,
- topLevelTypes.topKeyDown,
- topLevelTypes.topKeyPress,
- topLevelTypes.topKeyUp,
- topLevelTypes.topMouseDown
- ]
- },
- compositionUpdate: {
- phasedRegistrationNames: {
- bubbled: keyOf({onCompositionUpdate: null}),
- captured: keyOf({onCompositionUpdateCapture: null})
- },
- dependencies: [
- topLevelTypes.topBlur,
- topLevelTypes.topCompositionUpdate,
- topLevelTypes.topKeyDown,
- topLevelTypes.topKeyPress,
- topLevelTypes.topKeyUp,
- topLevelTypes.topMouseDown
- ]
- }
-};
+var Danger = require("./Danger");
+var ReactMultiChildUpdateTypes = require("./ReactMultiChildUpdateTypes");
-/**
- * Translate native top level events into event types.
- *
- * @param {string} topLevelType
- * @return {object}
- */
-function getCompositionEventType(topLevelType) {
- switch (topLevelType) {
- case topLevelTypes.topCompositionStart:
- return eventTypes.compositionStart;
- case topLevelTypes.topCompositionEnd:
- return eventTypes.compositionEnd;
- case topLevelTypes.topCompositionUpdate:
- return eventTypes.compositionUpdate;
- }
-}
+var setTextContent = require("./setTextContent");
+var invariant = require("./invariant");
/**
- * Does our fallback best-guess model think this event signifies that
- * composition has begun?
+ * Inserts `childNode` as a child of `parentNode` at the `index`.
*
- * @param {string} topLevelType
- * @param {object} nativeEvent
- * @return {boolean}
+ * @param {DOMElement} parentNode Parent node in which to insert.
+ * @param {DOMElement} childNode Child node to insert.
+ * @param {number} index Index at which to insert the child.
+ * @internal
*/
-function isFallbackStart(topLevelType, nativeEvent) {
- return (
- topLevelType === topLevelTypes.topKeyDown &&
- nativeEvent.keyCode === START_KEYCODE
+function insertChildAt(parentNode, childNode, index) {
+ // By exploiting arrays returning `undefined` for an undefined index, we can
+ // rely exclusively on `insertBefore(node, null)` instead of also using
+ // `appendChild(node)`. However, using `undefined` is not allowed by all
+ // browsers so we must replace it with `null`.
+ parentNode.insertBefore(
+ childNode,
+ parentNode.childNodes[index] || null
);
}
/**
- * Does our fallback mode think that this event is the end of composition?
- *
- * @param {string} topLevelType
- * @param {object} nativeEvent
- * @return {boolean}
- */
-function isFallbackEnd(topLevelType, nativeEvent) {
- switch (topLevelType) {
- case topLevelTypes.topKeyUp:
- // Command keys insert or clear IME input.
- return (END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1);
- case topLevelTypes.topKeyDown:
- // Expect IME keyCode on each keydown. If we get any other
- // code we must have exited earlier.
- return (nativeEvent.keyCode !== START_KEYCODE);
- case topLevelTypes.topKeyPress:
- case topLevelTypes.topMouseDown:
- case topLevelTypes.topBlur:
- // Events are not possible without cancelling IME.
- return true;
- default:
- return false;
- }
-}
-
-/**
- * Helper class stores information about selection and document state
- * so we can figure out what changed at a later date.
- *
- * @param {DOMEventTarget} root
- */
-function FallbackCompositionState(root) {
- this.root = root;
- this.startSelection = ReactInputSelection.getSelection(root);
- this.startValue = this.getText();
-}
-
-/**
- * Get current text of input.
- *
- * @return {string}
- */
-FallbackCompositionState.prototype.getText = function() {
- return this.root.value || this.root[getTextContentAccessor()];
-};
-
-/**
- * Text that has changed since the start of composition.
- *
- * @return {string}
- */
-FallbackCompositionState.prototype.getData = function() {
- var endValue = this.getText();
- var prefixLength = this.startSelection.start;
- var suffixLength = this.startValue.length - this.startSelection.end;
-
- return endValue.substr(
- prefixLength,
- endValue.length - suffixLength - prefixLength
- );
-};
-
-/**
- * This plugin creates `onCompositionStart`, `onCompositionUpdate` and
- * `onCompositionEnd` events on inputs, textareas and contentEditable
- * nodes.
- */
-var CompositionEventPlugin = {
-
- eventTypes: eventTypes,
-
- /**
- * @param {string} topLevelType Record from `EventConstants`.
- * @param {DOMEventTarget} topLevelTarget The listening component root node.
- * @param {string} topLevelTargetID ID of `topLevelTarget`.
- * @param {object} nativeEvent Native browser event.
- * @return {*} An accumulation of synthetic events.
- * @see {EventPluginHub.extractEvents}
- */
- extractEvents: function(
- topLevelType,
- topLevelTarget,
- topLevelTargetID,
- nativeEvent) {
-
- var eventType;
- var data;
-
- if (useCompositionEvent) {
- eventType = getCompositionEventType(topLevelType);
- } else if (!currentComposition) {
- if (isFallbackStart(topLevelType, nativeEvent)) {
- eventType = eventTypes.compositionStart;
- }
- } else if (isFallbackEnd(topLevelType, nativeEvent)) {
- eventType = eventTypes.compositionEnd;
- }
-
- if (useFallbackData) {
- // The current composition is stored statically and must not be
- // overwritten while composition continues.
- if (!currentComposition && eventType === eventTypes.compositionStart) {
- currentComposition = new FallbackCompositionState(topLevelTarget);
- } else if (eventType === eventTypes.compositionEnd) {
- if (currentComposition) {
- data = currentComposition.getData();
- currentComposition = null;
- }
- }
- }
-
- if (eventType) {
- var event = SyntheticCompositionEvent.getPooled(
- eventType,
- topLevelTargetID,
- nativeEvent
- );
- if (data) {
- // Inject data generated from fallback path into the synthetic event.
- // This matches the property of native CompositionEventInterface.
- event.data = data;
- }
- EventPropagators.accumulateTwoPhaseDispatches(event);
- return event;
- }
- }
-};
-
-module.exports = CompositionEventPlugin;
-
-},{"./EventConstants":17,"./EventPropagators":22,"./ExecutionEnvironment":23,"./ReactInputSelection":60,"./SyntheticCompositionEvent":84,"./getTextContentAccessor":117,"./keyOf":129}],11:[function(require,module,exports){
-(function (process){
-/**
- * Copyright 2013-2014 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
- * @typechecks static-only
- */
-
-"use strict";
-
-var Danger = require("./Danger");
-var ReactMultiChildUpdateTypes = require("./ReactMultiChildUpdateTypes");
-
-var getTextContentAccessor = require("./getTextContentAccessor");
-var invariant = require("./invariant");
-
-/**
- * The DOM property to use when setting text content.
- *
- * @type {string}
- * @private
- */
-var textContentAccessor = getTextContentAccessor();
-
-/**
- * Inserts `childNode` as a child of `parentNode` at the `index`.
- *
- * @param {DOMElement} parentNode Parent node in which to insert.
- * @param {DOMElement} childNode Child node to insert.
- * @param {number} index Index at which to insert the child.
- * @internal
- */
-function insertChildAt(parentNode, childNode, index) {
- // By exploiting arrays returning `undefined` for an undefined index, we can
- // rely exclusively on `insertBefore(node, null)` instead of also using
- // `appendChild(node)`. However, using `undefined` is not allowed by all
- // browsers so we must replace it with `null`.
- parentNode.insertBefore(
- childNode,
- parentNode.childNodes[index] || null
- );
-}
-
-var updateTextContent;
-if (textContentAccessor === 'textContent') {
- /**
- * Sets the text content of `node` to `text`.
- *
- * @param {DOMElement} node Node to change
- * @param {string} text New text content
- */
- updateTextContent = function(node, text) {
- node.textContent = text;
- };
-} else {
- /**
- * Sets the text content of `node` to `text`.
- *
- * @param {DOMElement} node Node to change
- * @param {string} text New text content
- */
- updateTextContent = function(node, text) {
- // In order to preserve newlines correctly, we can't use .innerText to set
- // the contents (see #1080), so we empty the element then append a text node
- while (node.firstChild) {
- node.removeChild(node.firstChild);
- }
- if (text) {
- var doc = node.ownerDocument || document;
- node.appendChild(doc.createTextNode(text));
- }
- };
-}
-
-/**
- * Operations for updating with DOM children.
+ * Operations for updating with DOM children.
*/
var DOMChildrenOperations = {
dangerouslyReplaceNodeWithMarkup: Danger.dangerouslyReplaceNodeWithMarkup,
- updateTextContent: updateTextContent,
+ updateTextContent: setTextContent,
/**
* Updates a component's children by processing a series of updates. The
@@ -2047,7 +2347,8 @@ var DOMChildrenOperations = {
// List of children that will be moved or removed.
var updatedChildren = null;
- for (var i = 0; update = updates[i]; i++) {
+ for (var i = 0; i < updates.length; i++) {
+ update = updates[i];
if (update.type === ReactMultiChildUpdateTypes.MOVE_EXISTING ||
update.type === ReactMultiChildUpdateTypes.REMOVE_NODE) {
var updatedIndex = update.fromIndex;
@@ -2059,9 +2360,9 @@ var DOMChildrenOperations = {
'processUpdates(): Unable to find child %s of element. This ' +
'probably means the DOM was unexpectedly mutated (e.g., by the ' +
'browser), usually due to forgetting a when using tables, ' +
- 'nesting