react / react-0.13.3 / examples / basic-commonjs / node_modules / reactify / node_modules / react-tools / src / browser / eventPlugins / BeforeInputEventPlugin.js
81155 views/**1* Copyright 2013 Facebook, Inc.2* All rights reserved.3*4* This source code is licensed under the BSD-style license found in the5* LICENSE file in the root directory of this source tree. An additional grant6* of patent rights can be found in the PATENTS file in the same directory.7*8* @providesModule BeforeInputEventPlugin9* @typechecks static-only10*/1112"use strict";1314var EventConstants = require('EventConstants');15var EventPropagators = require('EventPropagators');16var ExecutionEnvironment = require('ExecutionEnvironment');17var SyntheticInputEvent = require('SyntheticInputEvent');1819var keyOf = require('keyOf');2021var canUseTextInputEvent = (22ExecutionEnvironment.canUseDOM &&23'TextEvent' in window &&24!('documentMode' in document || isPresto())25);2627/**28* Opera <= 12 includes TextEvent in window, but does not fire29* text input events. Rely on keypress instead.30*/31function isPresto() {32var opera = window.opera;33return (34typeof opera === 'object' &&35typeof opera.version === 'function' &&36parseInt(opera.version(), 10) <= 1237);38}3940var SPACEBAR_CODE = 32;41var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE);4243var topLevelTypes = EventConstants.topLevelTypes;4445// Events and their corresponding property names.46var eventTypes = {47beforeInput: {48phasedRegistrationNames: {49bubbled: keyOf({onBeforeInput: null}),50captured: keyOf({onBeforeInputCapture: null})51},52dependencies: [53topLevelTypes.topCompositionEnd,54topLevelTypes.topKeyPress,55topLevelTypes.topTextInput,56topLevelTypes.topPaste57]58}59};6061// Track characters inserted via keypress and composition events.62var fallbackChars = null;6364// Track whether we've ever handled a keypress on the space key.65var hasSpaceKeypress = false;6667/**68* Return whether a native keypress event is assumed to be a command.69* This is required because Firefox fires `keypress` events for key commands70* (cut, copy, select-all, etc.) even though no character is inserted.71*/72function isKeypressCommand(nativeEvent) {73return (74(nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) &&75// ctrlKey && altKey is equivalent to AltGr, and is not a command.76!(nativeEvent.ctrlKey && nativeEvent.altKey)77);78}7980/**81* Create an `onBeforeInput` event to match82* http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents.83*84* This event plugin is based on the native `textInput` event85* available in Chrome, Safari, Opera, and IE. This event fires after86* `onKeyPress` and `onCompositionEnd`, but before `onInput`.87*88* `beforeInput` is spec'd but not implemented in any browsers, and89* the `input` event does not provide any useful information about what has90* actually been added, contrary to the spec. Thus, `textInput` is the best91* available event to identify the characters that have actually been inserted92* into the target node.93*/94var BeforeInputEventPlugin = {9596eventTypes: eventTypes,9798/**99* @param {string} topLevelType Record from `EventConstants`.100* @param {DOMEventTarget} topLevelTarget The listening component root node.101* @param {string} topLevelTargetID ID of `topLevelTarget`.102* @param {object} nativeEvent Native browser event.103* @return {*} An accumulation of synthetic events.104* @see {EventPluginHub.extractEvents}105*/106extractEvents: function(107topLevelType,108topLevelTarget,109topLevelTargetID,110nativeEvent) {111112var chars;113114if (canUseTextInputEvent) {115switch (topLevelType) {116case topLevelTypes.topKeyPress:117/**118* If native `textInput` events are available, our goal is to make119* use of them. However, there is a special case: the spacebar key.120* In Webkit, preventing default on a spacebar `textInput` event121* cancels character insertion, but it *also* causes the browser122* to fall back to its default spacebar behavior of scrolling the123* page.124*125* Tracking at:126* https://code.google.com/p/chromium/issues/detail?id=355103127*128* To avoid this issue, use the keypress event as if no `textInput`129* event is available.130*/131var which = nativeEvent.which;132if (which !== SPACEBAR_CODE) {133return;134}135136hasSpaceKeypress = true;137chars = SPACEBAR_CHAR;138break;139140case topLevelTypes.topTextInput:141// Record the characters to be added to the DOM.142chars = nativeEvent.data;143144// If it's a spacebar character, assume that we have already handled145// it at the keypress level and bail immediately. Android Chrome146// doesn't give us keycodes, so we need to blacklist it.147if (chars === SPACEBAR_CHAR && hasSpaceKeypress) {148return;149}150151// Otherwise, carry on.152break;153154default:155// For other native event types, do nothing.156return;157}158} else {159switch (topLevelType) {160case topLevelTypes.topPaste:161// If a paste event occurs after a keypress, throw out the input162// chars. Paste events should not lead to BeforeInput events.163fallbackChars = null;164break;165case topLevelTypes.topKeyPress:166/**167* As of v27, Firefox may fire keypress events even when no character168* will be inserted. A few possibilities:169*170* - `which` is `0`. Arrow keys, Esc key, etc.171*172* - `which` is the pressed key code, but no char is available.173* Ex: 'AltGr + d` in Polish. There is no modified character for174* this key combination and no character is inserted into the175* document, but FF fires the keypress for char code `100` anyway.176* No `input` event will occur.177*178* - `which` is the pressed key code, but a command combination is179* being used. Ex: `Cmd+C`. No character is inserted, and no180* `input` event will occur.181*/182if (nativeEvent.which && !isKeypressCommand(nativeEvent)) {183fallbackChars = String.fromCharCode(nativeEvent.which);184}185break;186case topLevelTypes.topCompositionEnd:187fallbackChars = nativeEvent.data;188break;189}190191// If no changes have occurred to the fallback string, no relevant192// event has fired and we're done.193if (fallbackChars === null) {194return;195}196197chars = fallbackChars;198}199200// If no characters are being inserted, no BeforeInput event should201// be fired.202if (!chars) {203return;204}205206var event = SyntheticInputEvent.getPooled(207eventTypes.beforeInput,208topLevelTargetID,209nativeEvent210);211212event.data = chars;213fallbackChars = null;214EventPropagators.accumulateTwoPhaseDispatches(event);215return event;216}217};218219module.exports = BeforeInputEventPlugin;220221222