diff --git a/README.md b/README.md index 486ce5f8..85508694 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,7 @@ Base class extending `PopupContainer` with the following methods: This is the top-level component that must be mounted for children ones to be rendered. Refer to Leaflet documentation for more information about the properties. **Properties** +- `bounds` (optional, dynamic): A rectangle for the map to contain. It will be centered, and the map will zoom in as close as it can while still showing the full bounds. This property is dynamic, if you change it it will be reflected on the map. - `center: LatLng` (optional, dynamic): Center of the map. This property is dynamic, if you change it it will be reflected in the map. - `className: String` (optional, dynamic): className property of the `
` container for the map. - `id: String` (optional): The ID of the `
` container for the map. If you don't provide it, a unique one will be created. diff --git a/example/app.js b/example/app.js index 94490004..62ed2372 100644 --- a/example/app.js +++ b/example/app.js @@ -4,6 +4,7 @@ import { render } from 'react-dom'; import SimpleExample from './simple'; import EventsExample from './events'; import VectorLayersExample from './vector-layers'; +import BoundsExample from './bounds'; const examples = (
@@ -15,6 +16,9 @@ const examples = (

Vector layers

+

Map view by bounds

+

Click a rectangle to fit the map to its bounds

+
); diff --git a/example/bounds.js b/example/bounds.js new file mode 100644 index 00000000..014f0366 --- /dev/null +++ b/example/bounds.js @@ -0,0 +1,49 @@ +import React, { Component } from 'react'; +import { Map, TileLayer, Rectangle } from 'react-leaflet'; + +const outer = [ + [50.505, -29.09], + [52.505, 29.09], +]; +const inner = [ + [49.505, -2.09], + [53.505, 2.09], +]; + +export default class BoundsExample extends Component { + constructor() { + super(); + this.state = { + bounds: outer, + }; + } + + handleClick() { + if (this.state.bounds === outer) { + this.setState({bounds: inner}); + } else { + this.setState({bounds: outer}); + } + } + + render() { + return ( + + + this.setState({bounds: outer})} + /> + this.setState({bounds: inner})} + /> + + ); + } +} diff --git a/example/build/app.js b/example/build/app.js index b49dbd8f..40fb4d4b 100755 --- a/example/build/app.js +++ b/example/build/app.js @@ -21,6 +21,10 @@ var _vectorLayers = require('./vector-layers'); var _vectorLayers2 = _interopRequireDefault(_vectorLayers); +var _bounds = require('./bounds'); + +var _bounds2 = _interopRequireDefault(_bounds); + var examples = _react2['default'].createElement( 'div', null, @@ -51,12 +55,106 @@ var examples = _react2['default'].createElement( null, 'Vector layers' ), - _react2['default'].createElement(_vectorLayers2['default'], null) + _react2['default'].createElement(_vectorLayers2['default'], null), + _react2['default'].createElement( + 'h2', + null, + 'Map view by bounds' + ), + _react2['default'].createElement( + 'p', + null, + 'Click a rectangle to fit the map to its bounds' + ), + _react2['default'].createElement(_bounds2['default'], null) ); (0, _reactDom.render)(examples, document.getElementById('app')); -},{"./events":2,"./simple":3,"./vector-layers":4,"react":"react","react-dom":"react-dom"}],2:[function(require,module,exports){ +},{"./bounds":2,"./events":3,"./simple":4,"./vector-layers":5,"react":"react","react-dom":"react-dom"}],2:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, '__esModule', { + value: true +}); + +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + +function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactLeaflet = require('react-leaflet'); + +var outer = [[50.505, -29.09], [52.505, 29.09]]; +var inner = [[49.505, -2.09], [53.505, 2.09]]; + +var BoundsExample = (function (_Component) { + _inherits(BoundsExample, _Component); + + function BoundsExample() { + _classCallCheck(this, BoundsExample); + + _get(Object.getPrototypeOf(BoundsExample.prototype), 'constructor', this).call(this); + this.state = { + bounds: outer + }; + } + + _createClass(BoundsExample, [{ + key: 'handleClick', + value: function handleClick() { + if (this.state.bounds === outer) { + this.setState({ bounds: inner }); + } else { + this.setState({ bounds: outer }); + } + } + }, { + key: 'render', + value: function render() { + var _this = this; + + return _react2['default'].createElement( + _reactLeaflet.Map, + { bounds: this.state.bounds }, + _react2['default'].createElement(_reactLeaflet.TileLayer, { + attribution: '© OpenStreetMap contributors', + url: 'http://{s}.tile.osm.org/{z}/{x}/{y}.png' + }), + _react2['default'].createElement(_reactLeaflet.Rectangle, { + bounds: outer, + color: this.state.bounds === outer ? 'red' : 'white', + onClick: function () { + return _this.setState({ bounds: outer }); + } + }), + _react2['default'].createElement(_reactLeaflet.Rectangle, { + bounds: inner, + color: this.state.bounds === inner ? 'red' : 'white', + onClick: function () { + return _this.setState({ bounds: inner }); + } + }) + ); + } + }]); + + return BoundsExample; +})(_react.Component); + +exports['default'] = BoundsExample; +module.exports = exports['default']; + +},{"react":"react","react-leaflet":"react-leaflet"}],3:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, '__esModule', { @@ -149,7 +247,7 @@ var EventsExample = (function (_Component) { exports['default'] = EventsExample; module.exports = exports['default']; -},{"react":"react","react-leaflet":"react-leaflet"}],3:[function(require,module,exports){ +},{"react":"react","react-leaflet":"react-leaflet"}],4:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, '__esModule', { @@ -222,7 +320,7 @@ var SimpleExample = (function (_Component) { exports['default'] = SimpleExample; module.exports = exports['default']; -},{"react":"react","react-leaflet":"react-leaflet"}],4:[function(require,module,exports){ +},{"react":"react","react-leaflet":"react-leaflet"}],5:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, '__esModule', { diff --git a/example/build/dependencies.js b/example/build/dependencies.js index 52cf5852..d60e4f70 100755 --- a/example/build/dependencies.js +++ b/example/build/dependencies.js @@ -1,91 +1,97 @@ require=(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 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; } - }; - } else { - if (process.env.NODE_ENV !== 'production') { - console.error('Attempted to listen to events during the capture phase on a ' + 'browser that does not support the capture phase. Your application ' + 'will not receive some events.'); - } - return { - remove: emptyFunction - }; } - }, + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + setTimeout(drainQueue, 0); + } +}; - registerDefault: function () {} +// 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 = {}; -module.exports = EventListener; -}).call(this,require('_process')) -},{"./emptyFunction":8,"_process":27}],2:[function(require,module,exports){ +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +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){ /** * Copyright 2013-2015, Facebook, Inc. * All rights reserved. @@ -94,458 +100,441 @@ module.exports = EventListener; * 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 ExecutionEnvironment + * @providesModule AutoFocusUtils + * @typechecks static-only */ 'use strict'; -var canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement); - -/** - * 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', +var ReactMount = require('./ReactMount'); - canUseEventListeners: canUseDOM && !!(window.addEventListener || window.attachEvent), +var findDOMNode = require('./findDOMNode'); +var focusNode = require('fbjs/lib/focusNode'); - canUseViewport: canUseDOM && !!window.screen, +var Mixin = { + componentDidMount: function () { + if (this.props.autoFocus) { + focusNode(findDOMNode(this)); + } + } +}; - isInWorker: !canUseDOM // For now, this is true - might change in the future. +var AutoFocusUtils = { + Mixin: Mixin, + focusDOMComponent: function () { + focusNode(ReactMount.getNode(this._rootNodeID)); + } }; -module.exports = ExecutionEnvironment; -},{}],3:[function(require,module,exports){ +module.exports = AutoFocusUtils; +},{"./ReactMount":66,"./findDOMNode":108,"fbjs/lib/focusNode":139}],3:[function(require,module,exports){ /** - * Copyright 2013-2015, Facebook, Inc. + * 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 camelize - * @typechecks + * @providesModule BeforeInputEventPlugin + * @typechecks static-only */ -"use strict"; +'use strict'; -var _hyphenPattern = /-(.)/g; +var EventConstants = require('./EventConstants'); +var EventPropagators = require('./EventPropagators'); +var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment'); +var FallbackCompositionState = require('./FallbackCompositionState'); +var SyntheticCompositionEvent = require('./SyntheticCompositionEvent'); +var SyntheticInputEvent = require('./SyntheticInputEvent'); -/** - * Camelcases a hyphenated string, for example: - * - * > camelize('background-color') - * < "backgroundColor" - * - * @param {string} string - * @return {string} - */ -function camelize(string) { - return string.replace(_hyphenPattern, function (_, character) { - return character.toUpperCase(); - }); -} +var keyOf = require('fbjs/lib/keyOf'); -module.exports = camelize; -},{}],4:[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 camelizeStyleName - * @typechecks - */ +var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space +var START_KEYCODE = 229; -'use strict'; +var canUseCompositionEvent = ExecutionEnvironment.canUseDOM && 'CompositionEvent' in window; -var camelize = require('./camelize'); +var documentMode = null; +if (ExecutionEnvironment.canUseDOM && 'documentMode' in document) { + documentMode = document.documentMode; +} -var msPattern = /^-ms-/; +// 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 && !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); /** - * Camelcases a hyphenated CSS property name, for example: - * - * > camelizeStyleName('background-color') - * < "backgroundColor" - * > camelizeStyleName('-moz-transition') - * < "MozTransition" - * > camelizeStyleName('-ms-transition') - * < "msTransition" - * - * As Andi Smith suggests - * (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix - * is converted to lowercase `ms`. - * - * @param {string} string - * @return {string} + * Opera <= 12 includes TextEvent in window, but does not fire + * text input events. Rely on keypress instead. */ -function camelizeStyleName(string) { - return camelize(string.replace(msPattern, 'ms-')); +function isPresto() { + var opera = window.opera; + return typeof opera === 'object' && typeof opera.version === 'function' && parseInt(opera.version(), 10) <= 12; } -module.exports = camelizeStyleName; -},{"./camelize":3}],5:[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 containsNode - * @typechecks - */ +var SPACEBAR_CODE = 32; +var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE); -'use strict'; +var topLevelTypes = EventConstants.topLevelTypes; -var isTextNode = require('./isTextNode'); +// Events and their corresponding property names. +var eventTypes = { + beforeInput: { + phasedRegistrationNames: { + bubbled: keyOf({ onBeforeInput: null }), + captured: keyOf({ onBeforeInputCapture: null }) + }, + dependencies: [topLevelTypes.topCompositionEnd, topLevelTypes.topKeyPress, topLevelTypes.topTextInput, topLevelTypes.topPaste] + }, + 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] + } +}; -/*eslint-disable no-bitwise */ +// Track whether we've ever handled a keypress on the space key. +var hasSpaceKeypress = false; /** - * Checks if a given DOM node contains or is another DOM node. - * - * @param {?DOMNode} outerNode Outer DOM node. - * @param {?DOMNode} innerNode Inner DOM node. - * @return {boolean} True if `outerNode` contains or is `innerNode`. + * 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 containsNode(_x, _x2) { - var _again = true; - - _function: while (_again) { - var outerNode = _x, - innerNode = _x2; - _again = false; - - if (!outerNode || !innerNode) { - return false; - } else if (outerNode === innerNode) { - return true; - } else if (isTextNode(outerNode)) { - return false; - } else if (isTextNode(innerNode)) { - _x = outerNode; - _x2 = innerNode.parentNode; - _again = true; - continue _function; - } else if (outerNode.contains) { - return outerNode.contains(innerNode); - } else if (outerNode.compareDocumentPosition) { - return !!(outerNode.compareDocumentPosition(innerNode) & 16); - } else { - return false; - } - } +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); } -module.exports = containsNode; -},{"./isTextNode":18}],6:[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. + * Translate native top level events into event types. * - * @providesModule createArrayFromMixed - * @typechecks + * @param {string} topLevelType + * @return {object} */ - -'use strict'; - -var toArray = require('./toArray'); +function getCompositionEventType(topLevelType) { + switch (topLevelType) { + case topLevelTypes.topCompositionStart: + return eventTypes.compositionStart; + case topLevelTypes.topCompositionEnd: + return eventTypes.compositionEnd; + case topLevelTypes.topCompositionUpdate: + return eventTypes.compositionUpdate; + } +} /** - * Perform a heuristic test to determine if an object is "array-like". - * - * A monk asked Joshu, a Zen master, "Has a dog Buddha nature?" - * Joshu replied: "Mu." - * - * This function determines if its argument has "array nature": it returns - * true if the argument is an actual array, an `arguments' object, or an - * HTMLCollection (e.g. node.childNodes or node.getElementsByTagName()). - * - * It will return false for other array-like objects like Filelist. + * Does our fallback best-guess model think this event signifies that + * composition has begun? * - * @param {*} obj + * @param {string} topLevelType + * @param {object} nativeEvent * @return {boolean} */ -function hasArrayNature(obj) { - return( - // not null/false - !!obj && ( - // arrays are objects, NodeLists are functions in Safari - typeof obj == 'object' || typeof obj == 'function') && - // quacks like an array - 'length' in obj && - // not window - !('setInterval' in obj) && - // no DOM node should be considered an array-like - // a 'select' element has 'length' and 'item' properties on IE8 - typeof obj.nodeType != 'number' && ( - // a real array - Array.isArray(obj) || - // arguments - 'callee' in obj || - // HTMLCollection/NodeList - 'item' in obj) - ); +function isFallbackCompositionStart(topLevelType, nativeEvent) { + return topLevelType === topLevelTypes.topKeyDown && nativeEvent.keyCode === START_KEYCODE; } /** - * Ensure that the argument is an array by wrapping it in an array if it is not. - * Creates a copy of the argument if it is already an array. - * - * This is mostly useful idiomatically: - * - * var createArrayFromMixed = require('createArrayFromMixed'); - * - * function takesOneOrMoreThings(things) { - * things = createArrayFromMixed(things); - * ... - * } - * - * This allows you to treat `things' as an array, but accept scalars in the API. - * - * If you need to convert an array-like object, like `arguments`, into an array - * use toArray instead. + * Does our fallback mode think that this event is the end of composition? * - * @param {*} obj - * @return {array} + * @param {string} topLevelType + * @param {object} nativeEvent + * @return {boolean} */ -function createArrayFromMixed(obj) { - if (!hasArrayNature(obj)) { - return [obj]; - } else if (Array.isArray(obj)) { - return obj.slice(); - } else { - return toArray(obj); +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; } } -module.exports = createArrayFromMixed; -},{"./toArray":25}],7:[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. + * 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. * - * @providesModule createNodesFromMarkup - * @typechecks + * @param {object} nativeEvent + * @return {?string} */ +function getDataFromCustomEvent(nativeEvent) { + var detail = nativeEvent.detail; + if (typeof detail === 'object' && 'data' in detail) { + return detail.data; + } + return null; +} -/*eslint-disable fb-www/unsafe-html*/ - -'use strict'; - -var ExecutionEnvironment = require('./ExecutionEnvironment'); - -var createArrayFromMixed = require('./createArrayFromMixed'); -var getMarkupWrap = require('./getMarkupWrap'); -var invariant = require('./invariant'); - -/** - * Dummy container used to render all markup. - */ -var dummyNode = ExecutionEnvironment.canUseDOM ? document.createElement('div') : null; +// Track the current IME composition fallback object, if any. +var currentComposition = null; /** - * Pattern used by `getNodeName`. - */ -var nodeNamePattern = /^\s*<(\w+)/; - -/** - * Extracts the `nodeName` of the first element in a string of markup. - * - * @param {string} markup String of markup. - * @return {?string} Node name of the supplied markup. + * @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 getNodeName(markup) { - var nodeNameMatch = markup.match(nodeNamePattern); - return nodeNameMatch && nodeNameMatch[1].toLowerCase(); -} +function extractCompositionEvent(topLevelType, topLevelTarget, topLevelTargetID, nativeEvent, nativeEventTarget) { + var eventType; + var fallbackData; -/** - * Creates an array containing the nodes rendered from the supplied markup. The - * optionally supplied `handleScript` function will be invoked once for each - *